00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "surface.h"
00022 #include "screen.h"
00023
00024 #include <iostream>
00025
00026 using namespace std;
00027
00028
00029 SDL_Rect surface::srcrect;
00030 SDL_Rect surface::dstrect;
00031
00032 void surface::resize_aux (u_int16 l, u_int16 h)
00033 {
00034 if (l == length () && h == height ()) return;
00035
00036 if (vis) SDL_FreeSurface (vis);
00037
00038 set_length (l);
00039 set_height (h);
00040
00041 vis = SDL_CreateRGBSurface (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_ASYNCBLIT,
00042 l, h,
00043 screen::bytes_per_pixel () * 8,
00044 screen::display.vis->format->Rmask,
00045 screen::display.vis->format->Gmask,
00046 screen::display.vis->format->Bmask,
00047 screen::display.vis->format->Amask);
00048 changed = true;
00049 }
00050
00051 void surface::double_size(const surface & src)
00052 {
00053 u_int32 col;
00054
00055 lock ();
00056 src.lock ();
00057
00058 dbl_mode = src.is_dbl_mode ();
00059 resize(src.length(), src.height());
00060 for (u_int16 j = 0; j < height(); j++)
00061 for (u_int16 i = 0; i < length(); i++)
00062 {
00063 src.get_pix_aux(i, j, col);
00064 put_pix(i, j, col);
00065 }
00066
00067 src.unlock ();
00068 unlock ();
00069 }
00070
00071 void surface::half_size(const surface & src)
00072 {
00073 u_int32 col;
00074
00075 lock ();
00076 src.lock ();
00077
00078 dbl_mode = src.is_dbl_mode ();
00079 resize_aux(src.length(), src.height());
00080 for (u_int16 j = 0; j < src.height() - 1; j++)
00081 for (u_int16 i = 0; i < src.length() - 1; i++)
00082 {
00083 src.get_pix(i, j, col);
00084 put_pix_aux(i, j, col);
00085 }
00086
00087 src.unlock ();
00088 unlock ();
00089 }
00090
00091 void surface::get_pix_aux (u_int16 x, u_int16 y, u_int32& col) const
00092 {
00093 u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
00094 + x * vis->format->BytesPerPixel;
00095
00096 switch (vis->format->BytesPerPixel)
00097 {
00098 case 1:
00099 col = *((Uint8 *)(offset));
00100 break;
00101 case 2:
00102 col = *((Uint16 *)(offset));
00103 break;
00104 case 3:
00105 {
00106 u_int8 r, g, b;
00107 col = 0;
00108 u_int32 t;
00109
00110 r = *((offset) + (vis->format->Rshift >> 3));
00111 g = *((offset) + (vis->format->Gshift >> 3));
00112 b = *((offset) + (vis->format->Bshift >> 3));
00113
00114 t = r << vis->format->Rshift;
00115 col |= t;
00116 t = g << vis->format->Gshift;
00117 col |= t;
00118 t = b << vis->format->Bshift;
00119 col |= t;
00120
00121 break;
00122 }
00123 case 4:
00124 col = *((Uint32 *)(offset));
00125 break;
00126 }
00127 }
00128
00129 void surface::put_pix_aux (u_int16 x, u_int16 y, u_int32 col)
00130 {
00131 u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
00132 + x*vis->format->BytesPerPixel;
00133
00134 switch (vis->format->BytesPerPixel)
00135 {
00136 case 2:
00137 *((Uint16 *) (offset)) = (Uint16) col;
00138 if (dbl_mode)
00139 {
00140 *((Uint16 *) (offset+vis->format->BytesPerPixel)) = (Uint16) col;
00141 *((Uint16 *) (offset+vis->pitch)) = (Uint16) col;
00142 *((Uint16 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint16) col;
00143 }
00144 break;
00145 case 3:
00146 {
00147 u_int8 r, g, b;
00148
00149 r = (col >> vis->format->Rshift);
00150 g = (col >> vis->format->Gshift);
00151 b = (col >> vis->format->Bshift);
00152 *((offset) + (vis->format->Rshift >> 3)) = r;
00153 *((offset) + (vis->format->Gshift >> 3)) = g;
00154 *((offset) + (vis->format->Bshift >> 3)) = b;
00155 if (dbl_mode)
00156 {
00157 *((offset+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
00158 *((offset+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
00159 *((offset+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
00160 *((offset+vis->pitch) + (vis->format->Rshift >> 3)) = r;
00161 *((offset+vis->pitch) + (vis->format->Gshift >> 3)) = g;
00162 *((offset+vis->pitch) + (vis->format->Bshift >> 3)) = b;
00163 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
00164 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
00165 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
00166 }
00167 break;
00168 }
00169 case 4:
00170 *((Uint32 *)(offset)) = (Uint32) col;
00171 if (dbl_mode)
00172 {
00173 *((Uint32 *) (offset+vis->format->BytesPerPixel)) = (Uint32) col;
00174 *((Uint32 *) (offset+vis->pitch)) = (Uint32) col;
00175 *((Uint32 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint32) col;
00176 }
00177 break;
00178 }
00179 changed = true;
00180 }
00181
00182
00183 surface::surface (bool mode) : drawable ()
00184 {
00185 vis = NULL;
00186 alpha_ = 255;
00187 mask_on = false;
00188 not_screen = true;
00189 changed = false;
00190 dbl_mode = mode ? screen::dbl_mode () : false;
00191 }
00192
00193 surface::~surface ()
00194 {
00195 if (vis && not_screen) SDL_FreeSurface (vis);
00196 }
00197
00198 void surface::set_mask (bool m)
00199 {
00200 if (m != is_masked ())
00201 {
00202 mask_on = m;
00203 changed = true;
00204 }
00205 }
00206
00207
00208 void surface::set_alpha (u_int8 t)
00209 {
00210 if ((t == 255) && (alpha_ != 255) && vis)
00211 SDL_SetAlpha (vis, 0, 0);
00212 alpha_ = t;
00213 }
00214
00215 void surface::draw (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy, u_int16 sl,
00216 u_int16 sh, const drawing_area * da_opt,
00217 surface * target) const
00218 {
00219 if (target == NULL) target = &screen::display;
00220
00221 setup_rects (x, y, sx, sy, sl, sh, da_opt);
00222
00223 if (screen::dbl_mode())
00224 {
00225 x <<= 1;
00226 y <<= 1;
00227 sx <<= 1;
00228 sy <<= 1;
00229 sl <<= 1;
00230 sh <<= 1;
00231 srcrect.x <<= 1;
00232 srcrect.y <<= 1;
00233 srcrect.w <<= 1;
00234 srcrect.h <<= 1;
00235 dstrect.x <<= 1;
00236 dstrect.y <<= 1;
00237 dstrect.w <<= 1;
00238 dstrect.h <<= 1;
00239 }
00240
00241 if (!dstrect.w || !dstrect.h)
00242 return;
00243
00244 if (changed)
00245 {
00246 changed = false;
00247 if (is_masked ())
00248 SDL_SetColorKey (vis, SDL_SRCCOLORKEY | SDL_RLEACCEL, screen::trans_col ());
00249 else
00250 SDL_SetColorKey (vis, 0, 0);
00251 }
00252
00253 if (alpha () != 255)
00254 SDL_SetAlpha (vis, SDL_SRCALPHA, alpha_);
00255
00256 SDL_BlitSurface (vis, &srcrect, target->vis, &dstrect);
00257 target->changed = true;
00258 }
00259
00260 void surface::fillrect (s_int16 x, s_int16 y, u_int16 l, u_int16 h, u_int32 col,
00261 drawing_area * da_opt)
00262 {
00263 if (da_opt)
00264 {
00265 dstrect = da_opt->setup_rects ();
00266 }
00267 else
00268 {
00269 dstrect.x = x;
00270 dstrect.y = y;
00271 dstrect.w = l;
00272 dstrect.h = h;
00273 }
00274
00275 if (screen::dbl_mode ())
00276 {
00277 dstrect.x <<= 1;
00278 dstrect.y <<= 1;
00279 dstrect.w <<= 1;
00280 dstrect.h <<= 1;
00281 }
00282
00283 SDL_FillRect (vis, &dstrect, col);
00284 changed = true;
00285 }
00286
00287 void surface::lock () const
00288 {
00289 if (!length () || !height ()) return;
00290 if (SDL_MUSTLOCK(vis))
00291 SDL_LockSurface (vis);
00292 }
00293
00294 void surface::unlock () const
00295 {
00296 if (!length () || !height ()) return;
00297 if (SDL_MUSTLOCK(vis))
00298 SDL_UnlockSurface (vis);
00299 }
00300
00301 void surface::put_pix (u_int16 x, u_int16 y, u_int32 col)
00302 {
00303 if (dbl_mode)
00304 {
00305 x <<= 1;
00306 y <<= 1;
00307 }
00308
00309 u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
00310 + x*vis->format->BytesPerPixel;
00311
00312 switch (vis->format->BytesPerPixel)
00313 {
00314 case 2:
00315 *((Uint16 *) (offset)) = (Uint16) col;
00316 if (dbl_mode)
00317 {
00318 *((Uint16 *) (offset+vis->format->BytesPerPixel)) = (Uint16) col;
00319 *((Uint16 *) (offset+vis->pitch)) = (Uint16) col;
00320 *((Uint16 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint16) col;
00321 }
00322 break;
00323 case 3:
00324 {
00325 u_int8 r, g, b;
00326
00327 r = (col >> vis->format->Rshift);
00328 g = (col >> vis->format->Gshift);
00329 b = (col >> vis->format->Bshift);
00330 *((offset) + (vis->format->Rshift >> 3)) = r;
00331 *((offset) + (vis->format->Gshift >> 3)) = g;
00332 *((offset) + (vis->format->Bshift >> 3)) = b;
00333 if (dbl_mode)
00334 {
00335 *((offset+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
00336 *((offset+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
00337 *((offset+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
00338 *((offset+vis->pitch) + (vis->format->Rshift >> 3)) = r;
00339 *((offset+vis->pitch) + (vis->format->Gshift >> 3)) = g;
00340 *((offset+vis->pitch) + (vis->format->Bshift >> 3)) = b;
00341 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Rshift >> 3)) = r;
00342 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Gshift >> 3)) = g;
00343 *((offset+vis->pitch+vis->format->BytesPerPixel) + (vis->format->Bshift >> 3)) = b;
00344 }
00345 break;
00346 }
00347 case 4:
00348 *((Uint32 *)(offset)) = (Uint32) col;
00349 if (dbl_mode)
00350 {
00351 *((Uint32 *) (offset+vis->format->BytesPerPixel)) = (Uint32) col;
00352 *((Uint32 *) (offset+vis->pitch)) = (Uint32) col;
00353 *((Uint32 *) (offset+vis->pitch+vis->format->BytesPerPixel)) = (Uint32) col;
00354 }
00355 break;
00356 }
00357 changed = true;
00358 }
00359
00360 void surface::get_pix (u_int16 x, u_int16 y, u_int32& col) const
00361 {
00362 if (dbl_mode)
00363 {
00364 x <<= 1;
00365 y <<= 1;
00366 }
00367 u_int8 * offset = ((Uint8 *) vis->pixels) + y * vis->pitch
00368 + x * vis->format->BytesPerPixel;
00369
00370 switch (vis->format->BytesPerPixel)
00371 {
00372 case 2:
00373 col = *((Uint16 *)(offset));
00374 break;
00375 case 3:
00376 {
00377 u_int8 r, g, b;
00378 col = 0;
00379 u_int32 t;
00380
00381 r = *((offset) + (vis->format->Rshift >> 3));
00382 g = *((offset) + (vis->format->Gshift >> 3));
00383 b = *((offset) + (vis->format->Bshift >> 3));
00384
00385 t = r << vis->format->Rshift;
00386 col |= t;
00387 t = g << vis->format->Gshift;
00388 col |= t;
00389 t = b << vis->format->Bshift;
00390 col |= t;
00391
00392 break;
00393 }
00394 case 4:
00395 col = *((Uint32 *)(offset));
00396 break;
00397 }
00398 }
00399
00400 surface& surface::operator = (surface& src)
00401 {
00402 (drawable&) (*this) = (drawable&) src;
00403 mask_on = src.mask_on;
00404 alpha_ = src.alpha_;
00405 not_screen = src.not_screen;
00406 dbl_mode = src.dbl_mode;
00407 if (vis) SDL_FreeSurface (vis);
00408 if (!src.vis)
00409 vis = NULL;
00410 else
00411 vis = SDL_DisplayFormat (src.vis);
00412 changed = true;
00413 return *this;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422 void surface::resize (u_int16 l, u_int16 h)
00423 {
00424 if (l == length () && h == height ()) return;
00425
00426 if (vis) SDL_FreeSurface (vis);
00427
00428 set_length (l);
00429 set_height (h);
00430
00431 if (screen::dbl_mode ())
00432 {
00433 l <<= 1;
00434 h <<= 1;
00435 }
00436
00437 vis = SDL_CreateRGBSurface (SDL_SRCCOLORKEY | SDL_SRCALPHA | SDL_ASYNCBLIT,
00438 l, h,
00439 screen::bytes_per_pixel () * 8,
00440 screen::display.vis->format->Rmask,
00441 screen::display.vis->format->Gmask,
00442 screen::display.vis->format->Bmask,
00443 screen::display.vis->format->Amask);
00444 changed = true;
00445 }
00446
00447 void surface::clear ()
00448 {
00449 if (vis)
00450 {
00451 SDL_FreeSurface (vis);
00452 vis = NULL;
00453 set_length (0);
00454 set_height (0);
00455 set_alpha (255);
00456 set_mask (false);
00457 changed = true;
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 void surface::setup_rects (s_int16 x, s_int16 y, s_int16 sx, s_int16 sy,
00468 u_int16 sl, u_int16 sh, const drawing_area * draw_to) const
00469 {
00470 if (draw_to)
00471 {
00472 drawing_area im_zone (x, y, sl, sh);
00473 SDL_Rect tr = draw_to->setup_rects ();
00474
00475 drawing_area da_int;
00476 da_int = tr;
00477
00478 im_zone.assign_drawing_area (&da_int);
00479 tr = im_zone.setup_rects ();
00480
00481 dstrect = tr;
00482 srcrect = dstrect;
00483 srcrect.x = x < dstrect.x ? sx + dstrect.x - x : sx;
00484 srcrect.y = y < dstrect.y ? sy + dstrect.y - y : sy;
00485 }
00486 else
00487 {
00488 srcrect.x = sx;
00489 srcrect.y = sy;
00490 srcrect.w = sl;
00491 srcrect.h = sh;
00492
00493 dstrect = srcrect;
00494
00495 dstrect.x = x;
00496 dstrect.y = y;
00497 }
00498 }