• Main Page
  • Related Pages
  • Classes
  • Files
  • File List
  • File Members

surface.cc

Go to the documentation of this file.
00001 /*
00002    $Id: surface.cc,v 1.15 2004/10/25 06:55:01 ksterker Exp $
00003 
00004    Copyright (C) 1999/2000/2001/2004   Alexandre Courbot
00005    Part of the Adonthell Project http://adonthell.linuxgames.com
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 
00016 /**
00017  * @file surface.cc
00018  * Defines the surface class.
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 // Protected methods
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 // Private methods
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 }

Generated on Tue Jul 27 2010 for Adonthell by  doxygen 1.7.1