00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
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
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 }