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

gradient.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     gradient - gradient drawing 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/gradient.cpp,v $
00027     CVS/RCS Revision: $Revision: 1.2 $
00028     Status:           $State: Exp $
00029 */
00030 
00031 #include "pgdraw.h"
00032 
00033 #include <cmath>
00034 #include <cassert>
00035 
00036 SDL_Surface* PG_Draw::CreateGradient(const PG_Rect& r, PG_Gradient& gradient) {
00037         return CreateGradient(
00038                    r,
00039                    gradient.colors[0],
00040                    gradient.colors[1],
00041                    gradient.colors[2],
00042                    gradient.colors[3]);
00043 }
00044 
00045 SDL_Surface* PG_Draw::CreateGradient(const PG_Rect& r, const PG_Color& ul, const PG_Color& ur, const PG_Color& dl, const PG_Color& dr) {
00046         SDL_Surface *grd = PG_Draw::CreateRGBSurface(r.w, r.h);
00047 
00048         r.my_xpos = 0;
00049         r.my_ypos = 0;
00050         PG_Draw::DrawGradient(grd, r, ul, ur, dl, dr);
00051 
00052         return grd;
00053 }
00054 
00055 void PG_Draw::DrawGradient(SDL_Surface* surface, const PG_Rect& r, PG_Gradient& gradient) {
00056         PG_Draw::DrawGradient(
00057             surface,
00058             r,
00059             gradient.colors[0],
00060             gradient.colors[1],
00061             gradient.colors[2],
00062             gradient.colors[3]);
00063 }
00064 
00065 void PG_Draw::DrawGradient(SDL_Surface * surface, const PG_Rect& rect, const PG_Color& ul, const PG_Color& ur, const PG_Color& dl, const PG_Color& dr) {
00066         Sint32 v00,v01,v02;
00067         Sint32 v10,v11,v12;
00068 
00069         Sint32 w = rect.my_width;
00070         Sint32 h = rect.my_height;
00071 
00072         if (!surface)
00073                 return;
00074 
00075         if(w == 0 || h == 0)
00076                 return;
00077 
00078         if (w > surface->w || h > surface->h)
00079                 return;
00080 
00081         Uint32 c1 = ul.MapRGB(surface->format);
00082         Uint32 c2 = ur.MapRGB(surface->format);
00083         Uint32 c3 = dl.MapRGB(surface->format);
00084         Uint32 c4 = dr.MapRGB(surface->format);
00085 
00086         // solid color gradient ?
00087         if((c1 == c2) && (c2 == c3) && (c3 == c4)) {
00088                 SDL_FillRect(surface, (PG_Rect*)&rect, c1);
00089                 return;
00090         }
00091 
00092         PG_Rect clip;
00093         SDL_GetClipRect(surface, &clip);
00094         PG_Rect drawrect = rect.IntersectRect(clip);
00095 
00096         if(drawrect.IsNull()) {
00097                 return;
00098         }
00099 
00100         int ox = drawrect.x - rect.x;
00101         int oy = drawrect.y - rect.y;
00102 
00103         if(SDL_MUSTLOCK(surface)) {
00104                 SDL_LockSurface(surface);
00105         }
00106 
00107         // color space vectors
00108         v00 = ((ur.r - ul.r) * 256) / w;
00109         v01 = ((ur.g - ul.g) * 256) / w;
00110         v02 = ((ur.b - ul.b) * 256) / w;
00111 
00112         v10 = ((dr.r - dl.r) * 256) / w;
00113         v11 = ((dr.g - dl.g) * 256) / w;
00114         v12 = ((dr.b - dl.b) * 256) / w;
00115 
00116         Sint32 r1, g1, b1;
00117         Sint32 r2, g2, b2;
00118         Sint32 yr, yg, yb;
00119         Sint32 r,g,b;
00120 
00121         r1 = ul.r * 256;
00122         g1 = ul.g * 256;
00123         b1 = ul.b * 256;
00124 
00125         r2 = dl.r * 256;
00126         g2 = dl.g * 256;
00127         b2 = dl.b * 256;
00128 
00129         // set colors with offset (ox)
00130         r1 += v00 * ox;
00131         g1 += v01 * ox;
00132         b1 += v02 * ox;
00133         r2 += v10 * ox;
00134         g2 += v11 * ox;
00135         b2 += v12 * ox;
00136 
00137         SDL_PixelFormat* format = surface->format;
00138         Uint8 Rloss = 8+format->Rloss;
00139         Uint8 Gloss = 8+format->Gloss;
00140         Uint8 Bloss = 8+format->Bloss;
00141         Uint8 Rshift = format->Rshift;
00142         Uint8 Gshift = format->Gshift;
00143         Uint8 Bshift = format->Bshift;
00144         Uint32 Amask = format->Amask;
00145         Uint8 Ashift = format->Ashift;
00146 
00147         Uint8 bpp = format->BytesPerPixel;
00148         Uint32 pitch = surface->pitch;
00149         Uint8* bits = ((Uint8 *) surface->pixels) + (rect.y + oy)* pitch + (rect.x + ox)* bpp;
00150         Uint32 y_pitch = pitch*drawrect.h - bpp;
00151         register Uint32 pixel = 0;
00152 
00153         for (register Sint32 x = 0; x < drawrect.w; x++) {
00154 
00155                 yr = (r2 - r1) / h;
00156                 yg = (g2 - g1) / h;
00157                 yb = (b2 - b1) / h;
00158 
00159                 r = r1;
00160                 g = g1;
00161                 b = b1;
00162                 r += yr * oy;
00163                 g += yg * oy;
00164                 b += yb * oy;
00165 
00166                 for (register Sint32 y = 0; y < drawrect.h; y++) {
00167 
00168                         /* Set the pixel */
00169                         switch (bpp) {
00170                                 case 1:
00171                                         pixel = SDL_MapRGB ( surface->format, r>>8, g>>8, b>>8 );
00172                                         *((Uint8 *) (bits)) = (Uint8) pixel;
00173                                         break;
00174 
00175                                 case 2:
00176                                         pixel =  (r>>Rloss) << Rshift
00177                                                  | (g>>Gloss) << Gshift
00178                                                  | (b>>Bloss) << Bshift;
00179 
00180                                         *((Uint16 *) (bits)) = (Uint16) pixel;
00181                                         break;
00182 
00183                                 case 3: {
00184                                                 pixel =  (r>>Rloss) << Rshift
00185                                                          | (g>>Gloss) << Gshift
00186                                                          | (b>>Bloss) << Bshift;
00187 
00188                                                 Uint8 ri = (pixel >> surface->format->Rshift) & 0xFF;
00189                                                 Uint8 gi = (pixel >> surface->format->Gshift) & 0xFF;
00190                                                 Uint8 bi = (pixel >> surface->format->Bshift) & 0xFF;
00191                                                 *((bits) + surface->format->Rshift / 8) = ri;
00192                                                 *((bits) + surface->format->Gshift / 8) = gi;
00193                                                 *((bits) + surface->format->Bshift / 8) = bi;
00194                                         }
00195                                         break;
00196 
00197                                 case 4:
00198                                         pixel =  (r>>Rloss) << Rshift
00199                                                  | (g>>Gloss) << Gshift
00200                                                  | (b>>Bloss) << Bshift
00201                                                  | ((SDL_ALPHA_OPAQUE << Ashift) & Amask);
00202 
00203                                         *((Uint32 *) (bits)) = (Uint32) pixel;
00204                                         break;
00205                         }
00206 
00207                         r += yr;
00208                         g += yg;
00209                         b += yb;
00210 
00211                         // next pixel
00212                         bits += pitch;
00213                 }
00214 
00215                 r1 += v00;
00216                 g1 += v01;
00217                 b1 += v02;
00218                 r2 += v10;
00219                 g2 += v11;
00220                 b2 += v12;
00221 
00222                 bits -= y_pitch;
00223         }
00224 
00225         if(SDL_MUSTLOCK(surface)) {
00226                 SDL_UnlockSurface(surface);
00227         }
00228 }

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