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 #include "pglog.h"
00033
00034 SDL_Surface* PG_Draw::CreateRGBSurface(Uint16 w, Uint16 h, int flags) {
00035 SDL_Surface* screen = SDL_GetVideoSurface();
00036
00037
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
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
00070
00071 if(h == src->h) {
00072 temp = src;
00073 } else {
00074 temp = PG_Draw::ScaleSurface(src, srcrect);
00075 }
00076
00077
00078 if(blend > 0) {
00079 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00080 } else {
00081 SDL_SetAlpha(temp, 0, 0);
00082 }
00083
00084
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
00092
00093 dstrect.SetRect(r.x+w, r.y, r.w-w*2, h);
00094 SDL_SetClipRect(dst, &dstrect);
00095
00096
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
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
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
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
00134
00135 if(w == src->w) {
00136 temp = src;
00137 } else {
00138 temp = PG_Draw::ScaleSurface(src, srcrect);
00139 }
00140
00141
00142 if(blend > 0) {
00143 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00144 } else {
00145 SDL_SetAlpha(temp, 0, 0);
00146 }
00147
00148
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
00156
00157
00158 dstrect.SetRect(r.x,r.y+h,w,r.h-h*2);
00159 SDL_SetClipRect(dst, &dstrect);
00160
00161
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
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
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
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
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
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
00240 SDL_Surface* src_stripe[3];
00241 int h_src_stripe = src->h / 3;
00242
00243
00244 dstrect.SetRect(0, 0, src->w, h_src_stripe);
00245 for(i=0; i<3; i++) {
00246
00247 srcrect.SetRect(0, i*h_src_stripe, src->w, h_src_stripe);
00248
00249
00250 src_stripe[i] = SDL_CreateRGBSurface(
00251 SDL_SWSURFACE,
00252 srcrect.w,
00253 srcrect.h,
00254 32,
00255 0,
00256 0,
00257 0,
00258 0
00259 );
00260
00261
00262 PG_Draw::BlitSurface(src, srcrect, src_stripe[i], dstrect);
00263 }
00264
00265
00266 SDL_Surface* dst_stripe[3];
00267 int h_dst_stripe = src->h / 3;
00268
00269
00270 dstrect.SetRect(0, 0, r.w, h_dst_stripe);
00271 for(i=0; i<3; i++) {
00272
00273 dst_stripe[i] = SDL_CreateRGBSurface(
00274 SDL_SWSURFACE,
00275 dstrect.w,
00276 dstrect.h,
00277 32,
00278 0,
00279 0,
00280 0,
00281 0
00282 );
00283
00284
00285 Draw3TileH(src_stripe[i], dstrect, dst_stripe[i], blend);
00286
00287
00288
00289
00290
00291
00292 }
00293
00294
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
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
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
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
00320 bool bColorKey = false;
00321 PG_Color uColorKey;
00322 Uint32 c;
00323 PG_Rect oldclip;
00324
00325
00326 if (!surface || !r.h || !r.w)
00327 return;
00328
00329
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
00349
00350 SDL_Surface* temp;
00351
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
00366 if ( bkmode == STRETCH && r.w==background->w && r.h == background->h )
00367 bkmode = TILE;
00368
00369 switch(bkmode) {
00370
00371
00372
00373
00374
00375 case TILE:
00376 DrawTileSurface(background, r, surface, blend);
00377 break;
00378
00379
00380
00381
00382
00383 case STRETCH:
00384
00385
00386
00387
00388 temp = PG_Draw::ScaleSurface(background, r);
00389
00390
00391 if(blend > 0) {
00392 SDL_SetAlpha(temp, SDL_SRCALPHA, 255-blend);
00393 } else {
00394 SDL_SetAlpha(temp, 0, 0);
00395 }
00396
00397
00398 SDL_BlitSurface(temp, NULL, surface, (PG_Rect*)&r);
00399
00400
00401 SDL_FreeSurface(temp);
00402 break;
00403
00404
00405
00406
00407
00408 case TILE3H:
00409 Draw3TileH(background, r, surface, blend);
00410 break;
00411
00412
00413
00414
00415
00416 case TILE3V:
00417 Draw3TileV(background, r, surface, blend);
00418 break;
00419
00420
00421
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(( (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 }