Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

surface.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     surface - surface creation and manipulation functions
00004  
00005     Copyright (C) 2000,2001,2002  Alexander Pipelka
00006  
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011  
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016  
00017     You should have received a copy of the GNU Library General Public
00018     License along with this library; if not, write to the Free
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  
00021     Alexander Pipelka
00022     pipelka@teleweb.at
00023  
00024     Last Update:      $Author: mbickel $
00025     Update Date:      $Date: 2007-04-13 16:16:01 $
00026     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/draw/surface.cpp,v $
00027     CVS/RCS Revision: $Revision: 1.2 $
00028     Status:           $State: Exp $
00029 */
00030 
00031 #include "pgdraw.h"
00032 #include "pglog.h"
00033 
00034 SDL_Surface* PG_Draw::CreateRGBSurface(Uint16 w, Uint16 h, int flags) {
00035         SDL_Surface* screen = SDL_GetVideoSurface();
00036 
00037         // credits to Peter Kasting!
00038         if (screen == NULL) {
00039                 PG_LogWRN("CreateRGBSurface() failed: current display surface invalid or n/a.");
00040                 return NULL;
00041         }
00042 
00043         return SDL_CreateRGBSurface (
00044                    flags,
00045                    w, h,
00046                    screen->format->BitsPerPixel,
00047                    screen->format->Rmask,
00048                    screen->format->Gmask,
00049                    screen->format->Bmask,
00050                    0);
00051 }
00052 
00053 static void Draw3TileH(SDL_Surface* src, const PG_Rect& r, SDL_Surface* dst, Uint8 blend = 0) {
00054         PG_Rect srcrect;
00055         PG_Rect dstrect;
00056         SDL_Surface* temp;
00057         int w,h;
00058 
00059         // source rectangles
00060         h = r.h;
00061         w = (int)( ( (double)h / (double)src->h) * (double)src->w );
00062         srcrect.SetRect(0,0,w,h);
00063         w /= 3;
00064 
00065         if (!w) {
00066                 return;
00067         }
00068 
00069         // rescale surface
00070 
00071         if(h == src->h) {
00072                 temp = src;
00073         } else {
00074                 temp = PG_Draw::ScaleSurface(src, srcrect);
00075         }
00076 
00077         // set per surface alpha
00078         if(blend > 0) {
00079                 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00080         } else {
00081                 SDL_SetAlpha(temp, 0, 0);
00082         }
00083 
00084         // blit part 1 (left)
00085 
00086         SDL_SetClipRect(dst, NULL);
00087         dstrect.SetRect(r.x,r.y,w,h);
00088         srcrect.SetRect(0, 0, w, h);
00089         PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00090 
00091         // blit part 2 (middle)
00092 
00093         dstrect.SetRect(r.x+w, r.y, r.w-w*2, h);
00094         SDL_SetClipRect(dst, &dstrect);
00095 
00096         // blit it
00097         srcrect.SetRect(w, 0, w, h);
00098         for(int i = 1; i<(r.w/w); i++) {
00099                 dstrect.SetRect(r.x+w*i, r.y, w, h);
00100                 PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00101         }
00102         SDL_SetClipRect(dst, NULL);
00103 
00104         // blit part 3 (right)
00105 
00106         dstrect.SetRect(r.x+r.w-w, r.y,w,h);
00107         srcrect.SetRect(w*2, 0, w, h);
00108         PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00109 
00110         // free temp surface
00111         if(h != src->h) {
00112                 SDL_FreeSurface(temp);
00113         }
00114 
00115 }
00116 
00117 static void Draw3TileV(SDL_Surface* src, const PG_Rect& r, SDL_Surface* dst, Uint8 blend = 0) {
00118         PG_Rect srcrect;
00119         PG_Rect dstrect;
00120         SDL_Surface* temp;
00121         int w,h;
00122 
00123         // source rectangles
00124         w = r.w;
00125         h = (int)( ( (double)w / (double)src->w) * (double)src->h );
00126         srcrect.SetRect(0,0,w,h);
00127         h /= 3;
00128 
00129         if (!h) {
00130                 return;
00131         }
00132 
00133         // rescale surface
00134 
00135         if(w == src->w) {
00136                 temp = src;
00137         } else {
00138                 temp = PG_Draw::ScaleSurface(src, srcrect);
00139         }
00140 
00141         // set per surface alpha
00142         if(blend > 0) {
00143                 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00144         } else {
00145                 SDL_SetAlpha(temp, 0, 0);
00146         }
00147 
00148         // blit part 1 (top)
00149 
00150         SDL_SetClipRect(dst, NULL);
00151         dstrect.SetRect(r.x,r.y,w,h);
00152         srcrect.SetRect(0, 0, w, h);
00153         PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00154 
00155         // blit part 2 (middle)
00156 
00157         // set cliprect
00158         dstrect.SetRect(r.x,r.y+h,w,r.h-h*2);
00159         SDL_SetClipRect(dst, &dstrect);
00160 
00161         // blit it
00162         srcrect.SetRect(0, h, w, h);
00163         for(int i = 1; i<(r.h/h); i++) {
00164                 dstrect.SetRect(r.x, r.y+h*i, w, h);
00165                 PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00166         }
00167         SDL_SetClipRect(dst, NULL);
00168 
00169         // blit part 3 (bottom)
00170 
00171         dstrect.SetRect(r.x,r.y+r.h-h,w,h);
00172         srcrect.SetRect(0, h*2, w, h);
00173         PG_Draw::BlitSurface(temp, srcrect, dst, dstrect);
00174 
00175         // free temp surface
00176         if(w != src->w) {
00177                 SDL_FreeSurface(temp);
00178         }
00179 
00180 }
00181 
00182 static void DrawTileSurface(SDL_Surface* src, const PG_Rect& r, SDL_Surface* dst, Uint8 blend = 0) {
00183         PG_Rect srcrect;
00184         PG_Rect dstrect;
00185 
00186         // tile the background image over the r in surface
00187         dstrect = r;
00188 
00189         srcrect.SetRect(0, 0, src->w, src->h);
00190 
00191         int yc = (r.my_height / src->h) +1;
00192         int xc = (r.my_width / src->w) +1;
00193 
00194         if(blend > 0) {
00195                 SDL_SetAlpha(src, SDL_SRCALPHA, 255-blend);
00196         } else {
00197                 SDL_SetAlpha(src, 0, 0);
00198         }
00199 
00200         srcrect.my_width = src->w;
00201         srcrect.my_height = src->h;
00202         dstrect.my_width = src->w;
00203         dstrect.my_height = src->h;
00204 
00205         SDL_SetClipRect(dst, &r);
00206         for(int y=0; y<yc; y++) {
00207                 for(int x=0; x<xc; x++) {
00208                         dstrect.x = r.my_xpos + src->w * x;
00209                         dstrect.y = r.my_ypos + src->h * y;
00210 
00211                         PG_Draw::BlitSurface(src, srcrect, dst, dstrect);
00212                 }
00213         }
00214         SDL_SetClipRect(dst, NULL);
00215 }
00216 
00217 /*
00218 **      9TILE
00219 **
00220 **      ABC
00221 **      DEF
00222 **      GHI
00223 **
00224 **        v
00225 **
00226 **      ABBBBBBC
00227 **      DEEEEEEEF
00228 **      DEEEEEEEF
00229 **      DEEEEEEEF
00230 **      DEEEEEEEF
00231 **      DEEEEEEEF
00232 **      GHHHHHHI
00233 */
00234 static void Draw9Tile(SDL_Surface* src, const PG_Rect& r, SDL_Surface* dst, Uint8 blend = 0) {
00235         PG_Rect srcrect;
00236         PG_Rect dstrect;
00237         int i = 0;
00238 
00239         // 3 source stripes (ABC, DEF, HGI)
00240         SDL_Surface* src_stripe[3];
00241         int h_src_stripe = src->h / 3;
00242 
00243         // copy source stripes
00244         dstrect.SetRect(0, 0, src->w, h_src_stripe);
00245         for(i=0; i<3; i++) {
00246                 // set source rect
00247                 srcrect.SetRect(0, i*h_src_stripe, src->w, h_src_stripe);
00248 
00249                 // create stripe surface
00250                 src_stripe[i] = SDL_CreateRGBSurface(
00251                                     SDL_SWSURFACE,
00252                                     srcrect.w,
00253                                     srcrect.h,
00254                                     32, //src->format->BitsPerPixel,
00255                                     0, //src->format->Rmask,
00256                                     0, //src->format->Gmask,
00257                                     0, //src->format->Bmask,
00258                                     0 //src->format->Amask
00259                                 );
00260 
00261                 // copy stripe
00262                 PG_Draw::BlitSurface(src, srcrect, src_stripe[i], dstrect);
00263         }
00264 
00265         // 3 destination stripes (ABBBBBBC, DEEEEEEEF, GHHHHHHI)
00266         SDL_Surface* dst_stripe[3];
00267         int h_dst_stripe = src->h / 3;
00268 
00269         // create destination stripes
00270         dstrect.SetRect(0, 0, r.w, h_dst_stripe);
00271         for(i=0; i<3; i++) {
00272                 // create dest. stripe
00273                 dst_stripe[i] = SDL_CreateRGBSurface(
00274                                     SDL_SWSURFACE,
00275                                     dstrect.w,
00276                                     dstrect.h,
00277                                     32, //src->format->BitsPerPixel,
00278                                     0, //src->format->Rmask,
00279                                     0, //src->format->Gmask,
00280                                     0, //src->format->Bmask,
00281                                     0 //src->format->Amask
00282                                 );
00283 
00284                 // 3TILEH the source to the dest. stripe
00285                 Draw3TileH(src_stripe[i], dstrect, dst_stripe[i], blend);
00286                 // set alpha
00287                 /*if(blend > 0) {
00288                         SDL_SetAlpha(dst_stripe[i], SDL_SRCALPHA, 255-blend);
00289                 } else {
00290                         SDL_SetAlpha(dst_stripe[i], 0, 0);
00291                 }*/
00292         }
00293 
00294         // copy stripe 0 (top)
00295         srcrect.SetRect(0, 0, dst_stripe[0]->w, dst_stripe[0]->h);
00296         dstrect.SetRect(r.x, r.y, r.w, dst_stripe[0]->h);
00297         PG_Draw::BlitSurface(dst_stripe[0], srcrect, dst, dstrect);
00298 
00299         // tile stripe 1 (middle part)
00300         dstrect.SetRect(r.x, r.y + dst_stripe[0]->h, r.w, r.h - 2*dst_stripe[0]->h);
00301         DrawTileSurface(dst_stripe[1], dstrect, dst, blend);
00302 
00303         // copy stripe 2 (bottom)
00304         srcrect.SetRect(0, 0, dst_stripe[2]->w, dst_stripe[2]->h);
00305         dstrect.SetRect(r.x, r.y+r.h-dst_stripe[2]->h, r.w, dst_stripe[2]->h);
00306         PG_Draw::BlitSurface(dst_stripe[2], srcrect, dst, dstrect);
00307 
00308         // cleanup
00309         for(i=0; i<3; i++) {
00310                 SDL_FreeSurface(src_stripe[i]);
00311                 SDL_FreeSurface(dst_stripe[i]);
00312         }
00313 
00314 }
00315 
00316 void PG_Draw::DrawThemedSurface(SDL_Surface* surface, const PG_Rect& r, PG_Gradient* gradient,SDL_Surface* background, BkMode bkmode, Uint8 blend) {
00317         static PG_Rect srcrect;
00318         static PG_Rect dstrect;
00319         //int x,y;
00320         bool bColorKey = false;
00321         PG_Color uColorKey;
00322         Uint32 c;
00323         PG_Rect oldclip;
00324 
00325         // check if we have anything to do
00326         if (!surface || !r.h || !r.w)
00327                 return;
00328 
00329         // draw the gradient first
00330         if((background == NULL) || (background && (blend > 0))) {
00331                 if(gradient != NULL) {
00332                         if(SDL_MUSTLOCK(surface)) {
00333                                 SDL_LockSurface(surface);
00334                         }
00335                         DrawGradient(surface, r, *gradient);
00336                         if(SDL_MUSTLOCK(surface)) {
00337                                 SDL_UnlockSurface(surface);
00338                         }
00339                 }
00340         }
00341 
00342         if(!background)
00343                 return;
00344 
00345         if (!background->w || !background->h)
00346                 return;
00347 
00348         //int yc;
00349         //int xc;
00350         SDL_Surface* temp;
00351         //int w,h;
00352 
00353         bColorKey = (background->flags & SDL_SRCCOLORKEY) != 0;
00354         Uint8 rc,gc,bc;
00355 
00356         SDL_GetRGB(background->format->colorkey, background->format, &rc, &gc, &bc);
00357         uColorKey = (Uint32)((rc << 16) | (gc << 8) | bc);
00358 
00359         if(((gradient == NULL) || (blend == 0)) && bColorKey) {
00360                 SDL_SetColorKey(background, 0, 0);
00361         }
00362 
00363         SDL_GetClipRect(surface, &oldclip);
00364 
00365    // prevent any aliasing if the sizes match
00366    if ( bkmode == STRETCH && r.w==background->w && r.h == background->h )
00367       bkmode = TILE;
00368    
00369         switch(bkmode) {
00370 
00371                         //
00372                         // BKMODE_TILE
00373                         //
00374 
00375                 case TILE:
00376                         DrawTileSurface(background, r, surface, blend);
00377                         break;
00378 
00379                         //
00380                         // BKMODE_STRETCH
00381                         //
00382 
00383                 case STRETCH:
00384                         // stretch the background to fit the surface
00385 
00386                         // Scale the background to fit this widget, using
00387                         // anti-aliasing
00388                         temp = PG_Draw::ScaleSurface(background, r);
00389 
00390                         // set per surface alpha
00391                         if(blend > 0) {
00392                                 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00393                         } else {
00394                                 SDL_SetAlpha(temp, 0, 0);
00395                         }
00396 
00397                         // blit it
00398                         SDL_BlitSurface(temp, NULL, surface, (PG_Rect*)&r);
00399 
00400                         // free the temp surface
00401                         SDL_FreeSurface(temp);
00402                         break;
00403 
00404                         //
00405                         // BKMODE_3TILEH
00406                         //
00407 
00408                 case TILE3H:
00409                         Draw3TileH(background, r, surface, blend);
00410                         break;
00411 
00412                         //
00413                         // BKMODE_3TILEV
00414                         //
00415 
00416                 case TILE3V:
00417                         Draw3TileV(background, r, surface, blend);
00418                         break;
00419 
00420                         //
00421                         // BKMODE_9TILE
00422                         //
00423 
00424                 case TILE9:
00425                         Draw9Tile(background, r, surface, blend);
00426                         break;
00427 
00428         }
00429 
00430         SDL_SetClipRect(surface, const_cast<PG_Rect*>(&oldclip));
00431 
00432         if((/*(gradient == NULL) ||*/ (blend == 0)) && bColorKey) {
00433                 c = uColorKey.MapRGB(background->format);
00434                 SDL_SetColorKey(background, SDL_SRCCOLORKEY, c);
00435                 c = uColorKey.MapRGB(surface->format);
00436                 SDL_SetColorKey(surface, SDL_SRCCOLORKEY, c);
00437         }
00438 }

Generated on Tue Jun 24 01:27:52 2008 for Advanced Strategic Command by  doxygen 1.4.2