Adonthell  0.4
surface.cc
Go to the documentation of this file.
1 /*
2  $Id: surface.cc,v 1.15 2004/10/25 06:55:01 ksterker Exp $
3 
4  Copyright (C) 1999/2000/2001/2004 Alexandre Courbot
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 
16 /**
17  * @file surface.cc
18  * Defines the surface class.
19  */
20 
21 #include "surface.h"
22 #include "screen.h"
23 
24 #include <iostream>
25 
26 using namespace std;
27 
28 
29 SDL_Rect surface::srcrect;
30 SDL_Rect surface::dstrect;
31 
32 void surface::resize_aux (u_int16 l, u_int16 h)
33 {
34  if (l == length () && h == height ()) return;
35 
36  if (vis) SDL_FreeSurface (vis);
37 
38  set_length (l);
39  set_height (h);
40 
41  vis = SDL_CreateRGBSurface (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_ASYNCBLIT,
42  l, h,
44  screen::display.vis->format->Rmask,
45  screen::display.vis->format->Gmask,
46  screen::display.vis->format->Bmask,
47  screen::display.vis->format->Amask);
48  changed = true;
49 }
50 
51 void surface::double_size(const surface & src)
52 {
53  u_int32 col;
54 
55  lock ();
56  src.lock ();
57 
58  dbl_mode = src.is_dbl_mode ();
59  resize(src.length(), src.height());
60  for (u_int16 j = 0; j < height(); j++)
61  for (u_int16 i = 0; i < length(); i++)
62  {
63  src.get_pix_aux(i, j, col);
64  put_pix(i, j, col);
65  }
66 
67  src.unlock ();
68  unlock ();
69 }
70 
71 void surface::half_size(const surface & src)
72 {
73  u_int32 col;
74 
75  lock ();
76  src.lock ();
77 
78  dbl_mode = src.is_dbl_mode ();
79  resize_aux(src.length(), src.height());
80  for (u_int16 j = 0; j < src.height() - 1; j++)
81  for (u_int16 i = 0; i < src.length() - 1; i++)
82  {
83  src.get_pix(i, j, col);
84  put_pix_aux(i, j, col);
85  }
86 
87  src.unlock ();
88  unlock ();
89 }
90 
91 void surface::get_pix_aux (u_int16 x, u_int16 y, u_int32& col) const
92 {
93  u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
94  + x * vis->format->BytesPerPixel;
95 
96  switch (vis->format->BytesPerPixel)
97  {
98  case 1:
99  col = *((Uint8 *)(offset));
100  break;
101  case 2:
102  col = *((Uint16 *)(offset));
103  break;
104  case 3:
105  {
106  u_int8 r, g, b;
107  col = 0;
108  u_int32 t;
109 
110  r = *((offset) + (vis->format->Rshift >> 3));
111  g = *((offset) + (vis->format->Gshift >> 3));
112  b = *((offset) + (vis->format->Bshift >> 3));
113 
114  t = r << vis->format->Rshift;
115  col |= t;
116  t = g << vis->format->Gshift;
117  col |= t;
118  t = b << vis->format->Bshift;
119  col |= t;
120 
121  break;
122  }
123  case 4:
124  col = *((Uint32 *)(offset));
125  break;
126  }
127 }
128 
129 void surface::put_pix_aux (u_int16 x, u_int16 y, u_int32 col)
130 {
131  u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
132  + x*vis->format->BytesPerPixel;
133 
134  switch (vis->format->BytesPerPixel)
135  {
136  case 2:
137  *((Uint16 *) (offset)) = (Uint16) col;
138  if (dbl_mode)
139  {
140  *((Uint16 *) (offset+vis->format->BytesPerPixel)) = (Uint16) col;
141  *((Uint16 *) (offset+vis->pitch)) = (Uint16) col;
142  *((Uint16 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint16) col;
143  }
144  break;
145  case 3:
146  {
147  u_int8 r, g, b;
148 
149  r = (col >> vis->format->Rshift);
150  g = (col >> vis->format->Gshift);
151  b = (col >> vis->format->Bshift);
152  *((offset) + (vis->format->Rshift >> 3)) = r;
153  *((offset) + (vis->format->Gshift >> 3)) = g;
154  *((offset) + (vis->format->Bshift >> 3)) = b;
155  if (dbl_mode)
156  {
157  *((offset+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
158  *((offset+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
159  *((offset+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
160  *((offset+vis->pitch) + (vis->format->Rshift >> 3)) = r;
161  *((offset+vis->pitch) + (vis->format->Gshift >> 3)) = g;
162  *((offset+vis->pitch) + (vis->format->Bshift >> 3)) = b;
163  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
164  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
165  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
166  }
167  break;
168  }
169  case 4:
170  *((Uint32 *)(offset)) = (Uint32) col;
171  if (dbl_mode)
172  {
173  *((Uint32 *) (offset+vis->format->BytesPerPixel)) = (Uint32) col;
174  *((Uint32 *) (offset+vis->pitch)) = (Uint32) col;
175  *((Uint32 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint32) col;
176  }
177  break;
178  }
179  changed = true;
180 }
181 
182 
183 surface::surface (bool mode) : drawable ()
184 {
185  vis = NULL;
186  alpha_ = 255;
187  mask_on = false;
188  not_screen = true;
189  changed = false;
190  dbl_mode = mode ? screen::dbl_mode () : false;
191 }
192 
194 {
195  if (vis && not_screen) SDL_FreeSurface (vis);
196 }
197 
198 void surface::set_mask (bool m)
199 {
200  if (m != is_masked ())
201  {
202  mask_on = m;
203  changed = true;
204  }
205 }
206 
207 
209 {
210  if ((t == 255) && (alpha_ != 255) && vis)
211  SDL_SetAlpha (vis, 0, 0);
212  alpha_ = t;
213 }
214 
216  u_int16 sh, const drawing_area * da_opt,
217  surface * target) const
218 {
219  if (target == NULL) target = &screen::display;
220 
221  setup_rects (x, y, sx, sy, sl, sh, da_opt);
222 
223  if (screen::dbl_mode())
224  {
225  x <<= 1;
226  y <<= 1;
227  sx <<= 1;
228  sy <<= 1;
229  sl <<= 1;
230  sh <<= 1;
231  srcrect.x <<= 1;
232  srcrect.y <<= 1;
233  srcrect.w <<= 1;
234  srcrect.h <<= 1;
235  dstrect.x <<= 1;
236  dstrect.y <<= 1;
237  dstrect.w <<= 1;
238  dstrect.h <<= 1;
239  }
240 
241  if (!dstrect.w || !dstrect.h)
242  return;
243 
244  if (changed)
245  {
246  changed = false;
247  if (is_masked ())
248  SDL_SetColorKey (vis, SDL_SRCCOLORKEY | SDL_RLEACCEL, screen::trans_col ());
249  else
250  SDL_SetColorKey (vis, 0, 0);
251  }
252 
253  if (alpha () != 255)
254  SDL_SetAlpha (vis, SDL_SRCALPHA, alpha_);
255 
256  SDL_BlitSurface (vis, &srcrect, target->vis, &dstrect);
257  target->changed = true;
258 }
259 
261  drawing_area * da_opt)
262 {
263  if (da_opt)
264  {
265  dstrect = da_opt->setup_rects ();
266  }
267  else
268  {
269  dstrect.x = x;
270  dstrect.y = y;
271  dstrect.w = l;
272  dstrect.h = h;
273  }
274 
275  if (screen::dbl_mode ())
276  {
277  dstrect.x <<= 1;
278  dstrect.y <<= 1;
279  dstrect.w <<= 1;
280  dstrect.h <<= 1;
281  }
282 
283  SDL_FillRect (vis, &dstrect, col);
284  changed = true;
285 }
286 
287 void surface::lock () const
288 {
289  if (!length () || !height ()) return;
290  if (SDL_MUSTLOCK(vis))
291  SDL_LockSurface (vis);
292 }
293 
294 void surface::unlock () const
295 {
296  if (!length () || !height ()) return;
297  if (SDL_MUSTLOCK(vis))
298  SDL_UnlockSurface (vis);
299 }
300 
302 {
303  if (dbl_mode)
304  {
305  x <<= 1;
306  y <<= 1;
307  }
308 
309  u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
310  + x*vis->format->BytesPerPixel;
311 
312  switch (vis->format->BytesPerPixel)
313  {
314  case 2:
315  *((Uint16 *) (offset)) = (Uint16) col;
316  if (dbl_mode)
317  {
318  *((Uint16 *) (offset+vis->format->BytesPerPixel)) = (Uint16) col;
319  *((Uint16 *) (offset+vis->pitch)) = (Uint16) col;
320  *((Uint16 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint16) col;
321  }
322  break;
323  case 3:
324  {
325  u_int8 r, g, b;
326 
327  r = (col >> vis->format->Rshift);
328  g = (col >> vis->format->Gshift);
329  b = (col >> vis->format->Bshift);
330  *((offset) + (vis->format->Rshift >> 3)) = r;
331  *((offset) + (vis->format->Gshift >> 3)) = g;
332  *((offset) + (vis->format->Bshift >> 3)) = b;
333  if (dbl_mode)
334  {
335  *((offset+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
336  *((offset+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
337  *((offset+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
338  *((offset+vis->pitch) + (vis->format->Rshift >> 3)) = r;
339  *((offset+vis->pitch) + (vis->format->Gshift >> 3)) = g;
340  *((offset+vis->pitch) + (vis->format->Bshift >> 3)) = b;
341  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
342  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
343  *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
344  }
345  break;
346  }
347  case 4:
348  *((Uint32 *)(offset)) = (Uint32) col;
349  if (dbl_mode)
350  {
351  *((Uint32 *) (offset+vis->format->BytesPerPixel)) = (Uint32) col;
352  *((Uint32 *) (offset+vis->pitch)) = (Uint32) col;
353  *((Uint32 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint32) col;
354  }
355  break;
356  }
357  changed = true;
358 }
359 
360 void surface::get_pix (u_int16 x, u_int16 y, u_int32& col) const
361 {
362  if (dbl_mode)
363  {
364  x <<= 1;
365  y <<= 1;
366  }
367  u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
368  + x * vis->format->BytesPerPixel;
369 
370  switch (vis->format->BytesPerPixel)
371  {
372  case 2:
373  col = *((Uint16 *)(offset));
374  break;
375  case 3:
376  {
377  u_int8 r, g, b;
378  col = 0;
379  u_int32 t;
380 
381  r = *((offset) + (vis->format->Rshift >> 3));
382  g = *((offset) + (vis->format->Gshift >> 3));
383  b = *((offset) + (vis->format->Bshift >> 3));
384 
385  t = r << vis->format->Rshift;
386  col |= t;
387  t = g << vis->format->Gshift;
388  col |= t;
389  t = b << vis->format->Bshift;
390  col |= t;
391 
392  break;
393  }
394  case 4:
395  col = *((Uint32 *)(offset));
396  break;
397  }
398 }
399 
401 {
402  (drawable&) (*this) = (drawable&) src;
403  mask_on = src.mask_on;
404  alpha_ = src.alpha_;
405  not_screen = src.not_screen;
406  dbl_mode = src.dbl_mode;
407  if (vis) SDL_FreeSurface (vis);
408  if (!src.vis)
409  vis = NULL;
410  else
411  vis = SDL_DisplayFormat (src.vis);
412  changed = true;
413  return *this;
414 }
415 
416 
417 
418 // Protected methods
419 
420 
421 
423 {
424  if (l == length () && h == height ()) return;
425 
426  if (vis) SDL_FreeSurface (vis);
427 
428  set_length (l);
429  set_height (h);
430 
431  if (screen::dbl_mode ())
432  {
433  l <<= 1;
434  h <<= 1;
435  }
436 
437  vis = SDL_CreateRGBSurface (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_ASYNCBLIT,
438  l, h,
440  screen::display.vis->format->Rmask,
441  screen::display.vis->format->Gmask,
442  screen::display.vis->format->Bmask,
443  screen::display.vis->format->Amask);
444  changed = true;
445 }
446 
448 {
449  if (vis)
450  {
451  SDL_FreeSurface (vis);
452  vis = NULL;
453  set_length (0);
454  set_height (0);
455  set_alpha (255);
456  set_mask (false);
457  changed = true;
458  }
459 }
460 
461 
462 
463 // Private methods
464 
465 
466 
467 void surface::setup_rects (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy,
468  u_int16 sl, u_int16 sh, const drawing_area * draw_to) const
469 {
470  if (draw_to)
471  {
472  drawing_area im_zone (x, y, sl, sh);
473  SDL_Rect tr = draw_to->setup_rects ();
474 
475  drawing_area da_int;
476  da_int = tr;
477 
478  im_zone.assign_drawing_area (&da_int);
479  tr = im_zone.setup_rects ();
480 
481  dstrect = tr;
482  srcrect = dstrect;
483  srcrect.x = x < dstrect.x ? sx + dstrect.x - x : sx;
484  srcrect.y = y < dstrect.y ? sy + dstrect.y - y : sy;
485  }
486  else
487  {
488  srcrect.x = sx;
489  srcrect.y = sy;
490  srcrect.w = sl;
491  srcrect.h = sh;
492 
493  dstrect = srcrect;
494 
495  dstrect.x = x;
496  dstrect.y = y;
497  }
498 }