Mercurial > fife-parpg
comparison engine/core/video/sdl/sdlimage.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 90005975cdbb |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*************************************************************************** | |
2 * Copyright (C) 2005-2008 by the FIFE team * | |
3 * http://www.fifengine.de * | |
4 * This file is part of FIFE. * | |
5 * * | |
6 * FIFE is free software; you can redistribute it and/or modify * | |
7 * it under the terms of the GNU General Public License as published by * | |
8 * the Free Software Foundation; either version 2 of the License, or * | |
9 * (at your option) any later version. * | |
10 * * | |
11 * This program is distributed in the hope that it will be useful, * | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
14 * GNU General Public License for more details. * | |
15 * * | |
16 * You should have received a copy of the GNU General Public License * | |
17 * along with this program; if not, write to the * | |
18 * Free Software Foundation, Inc., * | |
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | |
20 ***************************************************************************/ | |
21 | |
22 // Standard C++ library includes | |
23 #include <cassert> | |
24 #include <iostream> | |
25 | |
26 // 3rd party library includes | |
27 | |
28 // FIFE includes | |
29 // These includes are split up in two parts, separated by one empty line | |
30 // First block: files included from the FIFE root src directory | |
31 // Second block: files included from the same folder | |
32 #include "util/log/logger.h" | |
33 #include "util/structures/rect.h" | |
34 | |
35 #include "renderbackendsdl.h" | |
36 #include "sdlblendingfunctions.h" | |
37 #include "sdlimage.h" | |
38 | |
39 namespace FIFE { | |
40 static Logger _log(LM_VIDEO); | |
41 | |
42 SDLImage::SDLImage(SDL_Surface* surface): | |
43 Image(surface) { | |
44 resetSdlimage(); | |
45 } | |
46 | |
47 SDLImage::SDLImage(const uint8_t* data, unsigned int width, unsigned int height): | |
48 Image(data, width, height) { | |
49 resetSdlimage(); | |
50 } | |
51 | |
52 void SDLImage::resetSdlimage() { | |
53 m_last_alpha = 255; | |
54 m_finalized = false; | |
55 m_isalphaoptimized = false; | |
56 } | |
57 | |
58 SDLImage::~SDLImage() { } | |
59 | |
60 | |
61 void SDL_BlitSurfaceWithAlpha( const SDL_Surface* src, const SDL_Rect* srcRect, | |
62 SDL_Surface* dst, SDL_Rect* dstRect, unsigned char alpha ) { | |
63 if( 0 == alpha ) { | |
64 return; | |
65 } | |
66 | |
67 int screenX, screenY; | |
68 if( dstRect ) { | |
69 screenX = dstRect->x; | |
70 screenY = dstRect->y; | |
71 } else { | |
72 screenX = dst->clip_rect.x; | |
73 screenY = dst->clip_rect.y; | |
74 } | |
75 | |
76 int width, height, tX, tY; | |
77 if( srcRect ) { | |
78 tX = srcRect->x; | |
79 tY = srcRect->y; | |
80 width = srcRect->w; | |
81 height = srcRect->h; | |
82 } else { | |
83 tX = src->clip_rect.x; | |
84 tY = src->clip_rect.y; | |
85 width = src->clip_rect.w; | |
86 height = src->clip_rect.h; | |
87 } | |
88 | |
89 // Clipping. | |
90 if( ( screenX >= ( dst->clip_rect.x + dst->clip_rect.w ) ) || | |
91 ( screenY >= ( dst->clip_rect.y + dst->clip_rect.h ) ) || | |
92 ( ( screenX + width ) <= dst->clip_rect.x ) || | |
93 ( ( screenY + height ) <= dst->clip_rect.y ) ) { | |
94 return; | |
95 } | |
96 | |
97 if( screenX < dst->clip_rect.x ) { | |
98 int dX = dst->clip_rect.x - screenX; | |
99 screenX += dX; | |
100 width -= dX; | |
101 tX += dX; | |
102 } | |
103 | |
104 if( ( screenX + width ) > ( dst->clip_rect.x + dst->clip_rect.w ) ) { | |
105 int dX = ( screenX + width ) - ( dst->clip_rect.x + dst->clip_rect.w ); | |
106 width -= dX; | |
107 } | |
108 | |
109 if( screenY < dst->clip_rect.y ) { | |
110 int dY = dst->clip_rect.y - screenY; | |
111 screenY += dY; | |
112 height -= dY; | |
113 tY += dY; | |
114 } | |
115 | |
116 if( ( screenY + height ) > ( dst->clip_rect.y + dst->clip_rect.h ) ) { | |
117 int dY = ( screenY + height ) - ( dst->clip_rect.y + dst->clip_rect.h ); | |
118 height -= dY; | |
119 } | |
120 | |
121 if( ( 0 >= height ) || ( 0 >= width ) ) { | |
122 return; | |
123 } | |
124 | |
125 SDL_LockSurface( dst ); | |
126 | |
127 unsigned char* srcData = reinterpret_cast< unsigned char* > ( src->pixels ); | |
128 unsigned char* dstData = reinterpret_cast< unsigned char* > ( dst->pixels ); | |
129 | |
130 // move data pointers to the start of the pixels we're copying | |
131 srcData += tY * src->pitch + tX * src->format->BytesPerPixel; | |
132 dstData += screenY * dst->pitch + screenX * dst->format->BytesPerPixel; | |
133 | |
134 switch( src->format->BitsPerPixel ) { | |
135 case 32: { | |
136 switch( dst->format->BitsPerPixel ) { | |
137 case 16: { | |
138 if( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) { | |
139 for( int y = height; y > 0; --y ) { | |
140 SDL_BlendRow_RGBA8_to_RGB565( srcData, dstData, alpha, width ); | |
141 srcData += src->pitch; | |
142 dstData += dst->pitch; | |
143 } | |
144 } | |
145 } | |
146 break; | |
147 | |
148 case 24: { | |
149 for( int y = height; y > 0; --y ) { | |
150 SDL_BlendRow_RGBA8_to_RGB8( srcData, dstData, alpha, width ); | |
151 srcData += src->pitch; | |
152 dstData += dst->pitch; | |
153 } | |
154 } | |
155 break; | |
156 | |
157 case 32: { | |
158 for( int y = height; y > 0; --y ) { | |
159 SDL_BlendRow_RGBA8_to_RGBA8( srcData, dstData, alpha, width ); | |
160 srcData += src->pitch; | |
161 dstData += dst->pitch; | |
162 } | |
163 } | |
164 break; | |
165 | |
166 default: | |
167 break; | |
168 } ///< switch( dst->format->BitsPerPixel ) | |
169 } | |
170 break; | |
171 | |
172 case 16: { | |
173 if( 0x000F == src->format->Amask ) { | |
174 if( ( 16 == dst->format->BitsPerPixel ) && | |
175 ( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) ) { | |
176 for( int y = height; y > 0; --y ) { | |
177 SDL_BlendRow_RGBA4_to_RGB565( srcData, dstData, alpha, width ); | |
178 srcData += src->pitch; | |
179 dstData += dst->pitch; | |
180 } | |
181 } | |
182 } | |
183 } | |
184 break; | |
185 | |
186 default: | |
187 break; | |
188 } ///< switch( src->format->BitsPerPixel ) | |
189 | |
190 SDL_UnlockSurface( dst ); | |
191 } | |
192 | |
193 void SDLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) { | |
194 if (alpha == 0) { | |
195 return; | |
196 } | |
197 | |
198 if (rect.right() < 0 || rect.x > static_cast<int>(screen->w) || rect.bottom() < 0 || rect.y > static_cast<int>(screen->h)) { | |
199 return; | |
200 } | |
201 finalize(); | |
202 | |
203 SDL_Surface* surface = screen; | |
204 SDL_Rect r; | |
205 r.x = rect.x; | |
206 r.y = rect.y; | |
207 r.w = rect.w; | |
208 r.h = rect.h; | |
209 | |
210 if (m_surface->format->Amask == 0) { | |
211 // Image has no alpha channel. This allows us to use the per-surface alpha. | |
212 if (m_last_alpha != alpha) { | |
213 m_last_alpha = alpha; | |
214 SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, alpha); | |
215 } | |
216 SDL_BlitSurface(m_surface, 0, surface, &r); | |
217 } else { | |
218 if( 255 != alpha ) { | |
219 // Special blitting routine with alpha blending: | |
220 // dst.rgb = ( src.rgb * src.a * alpha ) + ( dst.rgb * (255 - ( src.a * alpha ) ) ); | |
221 SDL_BlitSurfaceWithAlpha( m_surface, 0, surface, &r, alpha ); | |
222 } else { | |
223 SDL_BlitSurface(m_surface, 0, surface, &r); | |
224 } | |
225 } | |
226 } | |
227 | |
228 void SDLImage::finalize() { | |
229 if( m_finalized ) { | |
230 return; | |
231 } | |
232 m_finalized = true; | |
233 SDL_Surface *old_surface = m_surface; | |
234 | |
235 if (m_surface->format->Amask == 0) { | |
236 SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, 255); | |
237 m_surface = SDL_DisplayFormat(m_surface); | |
238 } else { | |
239 RenderBackendSDL* be = static_cast<RenderBackendSDL*>(RenderBackend::instance()); | |
240 m_isalphaoptimized &= be->isAlphaOptimizerEnabled(); | |
241 if( m_isalphaoptimized ) { | |
242 m_surface = optimize(m_surface); | |
243 } else { | |
244 SDL_SetAlpha(m_surface, SDL_SRCALPHA, 255); | |
245 m_surface = SDL_DisplayFormatAlpha(m_surface); | |
246 } | |
247 } | |
248 SDL_FreeSurface(old_surface); | |
249 } | |
250 | |
251 SDL_Surface* SDLImage::optimize(SDL_Surface* src) { | |
252 // The algorithm is originally by "Tim Goya" <tuxdev103@gmail.com> | |
253 // Few modifications and adaptions by the FIFE team. | |
254 // | |
255 // It tries to determine whether an image with a alpha channel | |
256 // actually uses that. Often PNGs contains an alpha channels | |
257 // as they don't provide a colorkey feature(?) - so to speed | |
258 // up SDL rendering we try to remove the alpha channel. | |
259 | |
260 // As a reminder: src->format->Amask != 0 here | |
261 | |
262 int transparent = 0; | |
263 int opaque = 0; | |
264 int semitransparent = 0; | |
265 int alphasum = 0; | |
266 int alphasquaresum = 0; | |
267 bool colors[(1 << 12)]; | |
268 memset(colors, 0, (1 << 12) * sizeof(bool)); | |
269 | |
270 int bpp = src->format->BytesPerPixel; | |
271 if(SDL_MUSTLOCK(src)) { | |
272 SDL_LockSurface(src); | |
273 } | |
274 /* In the first pass through we calculate avg(alpha), avg(alpha^2) | |
275 and the number of semitransparent pixels. | |
276 We also try to find a useable color. | |
277 */ | |
278 for(int y = 0;y < src->h;y++) { | |
279 for(int x = 0;x < src->w;x++) { | |
280 Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; | |
281 Uint32 mapped = 0; | |
282 switch(bpp) { | |
283 case 1: | |
284 mapped = *pixel; | |
285 break; | |
286 case 2: | |
287 mapped = *(Uint16 *)pixel; | |
288 break; | |
289 case 3: | |
290 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | |
291 mapped |= pixel[0] << 16; | |
292 mapped |= pixel[1] << 8; | |
293 mapped |= pixel[2] << 0; | |
294 #else | |
295 mapped |= pixel[0] << 0; | |
296 mapped |= pixel[1] << 8; | |
297 mapped |= pixel[2] << 16; | |
298 #endif | |
299 break; | |
300 case 4: | |
301 mapped = *(Uint32 *)pixel; | |
302 break; | |
303 } | |
304 Uint8 red, green, blue, alpha; | |
305 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); | |
306 if(alpha < 16) { | |
307 transparent++; | |
308 } else if (alpha > 240) { | |
309 opaque++; | |
310 alphasum += alpha; | |
311 alphasquaresum += alpha*alpha; | |
312 } else { | |
313 semitransparent++; | |
314 alphasum += alpha; | |
315 alphasquaresum += alpha*alpha; | |
316 } | |
317 // mark the color as used. | |
318 if( alpha != 0 ) { | |
319 colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true; | |
320 } | |
321 } | |
322 } | |
323 int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0; | |
324 int alphavariance = 0; | |
325 | |
326 if(SDL_MUSTLOCK(src)) { | |
327 SDL_UnlockSurface(src); | |
328 } | |
329 alphasquaresum /= (opaque + semitransparent) ? (opaque + semitransparent) : 1; | |
330 alphavariance = alphasquaresum - avgalpha*avgalpha; | |
331 if(semitransparent > ((transparent + opaque + semitransparent) / 8) | |
332 && alphavariance > 16) { | |
333 FL_DBG(_log, LMsg("sdlimage") | |
334 << "Trying to alpha-optimize image. FAILED: real alpha usage. " | |
335 << " alphavariance=" << alphavariance | |
336 << " total=" << (transparent + opaque + semitransparent) | |
337 << " semitransparent=" << semitransparent | |
338 << "(" << (float(semitransparent)/(transparent + opaque + semitransparent)) | |
339 << ")"); | |
340 return SDL_DisplayFormatAlpha(src); | |
341 } | |
342 | |
343 // check availability of a suitable color as colorkey | |
344 int keycolor = -1; | |
345 for(int i = 0;i < (1 << 12);i++) { | |
346 if(!colors[i]) { | |
347 keycolor = i; | |
348 break; | |
349 } | |
350 } | |
351 if(keycolor == -1) { | |
352 FL_DBG(_log, LMsg("sdlimage") << "Trying to alpha-optimize image. FAILED: no free color"); | |
353 return SDL_DisplayFormatAlpha(src); | |
354 } | |
355 | |
356 SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA) | SDL_SWSURFACE, | |
357 src->w, src->h, | |
358 src->format->BitsPerPixel, | |
359 src->format->Rmask, src->format->Gmask, | |
360 src->format->Bmask, 0); | |
361 bpp = dst->format->BytesPerPixel; | |
362 Uint32 key = SDL_MapRGB(dst->format, | |
363 (((keycolor & 0xf00) >> 4) | 0xf), | |
364 ((keycolor & 0xf0) | 0xf), | |
365 (((keycolor & 0xf) << 4) | 0xf)); | |
366 if(SDL_MUSTLOCK(src)) { | |
367 SDL_LockSurface(src); | |
368 } | |
369 if(SDL_MUSTLOCK(dst)) { | |
370 SDL_LockSurface(dst); | |
371 } | |
372 for(int y = 0;y < dst->h;y++) { | |
373 for(int x = 0;x < dst->w;x++) { | |
374 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; | |
375 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; | |
376 Uint32 mapped = 0; | |
377 switch(bpp) { | |
378 case 1: | |
379 mapped = *srcpixel; | |
380 break; | |
381 case 2: | |
382 mapped = *(Uint16 *)srcpixel; | |
383 break; | |
384 case 3: | |
385 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | |
386 mapped |= srcpixel[0] << 16; | |
387 mapped |= srcpixel[1] << 8; | |
388 mapped |= srcpixel[2] << 0; | |
389 #else | |
390 mapped |= srcpixel[0] << 0; | |
391 mapped |= srcpixel[1] << 8; | |
392 mapped |= srcpixel[2] << 16; | |
393 #endif | |
394 break; | |
395 case 4: | |
396 mapped = *(Uint32 *)srcpixel; | |
397 break; | |
398 } | |
399 Uint8 red, green, blue, alpha; | |
400 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); | |
401 if(alpha < (avgalpha / 4)) { | |
402 mapped = key; | |
403 } else { | |
404 mapped = SDL_MapRGB(dst->format, red, green, blue); | |
405 } | |
406 switch(bpp) { | |
407 case 1: | |
408 *dstpixel = mapped; | |
409 break; | |
410 case 2: | |
411 *(Uint16 *)dstpixel = mapped; | |
412 break; | |
413 case 3: | |
414 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | |
415 dstpixel[0] = (mapped >> 16) & 0xff; | |
416 dstpixel[1] = (mapped >> 8) & 0xff; | |
417 dstpixel[2] = (mapped >> 0) & 0xff; | |
418 #else | |
419 dstpixel[0] = (mapped >> 0) & 0xff; | |
420 dstpixel[1] = (mapped >> 8) & 0xff; | |
421 dstpixel[2] = (mapped >> 16) & 0xff; | |
422 #endif | |
423 break; | |
424 case 4: | |
425 *(Uint32 *)dstpixel = mapped; | |
426 break; | |
427 } | |
428 } | |
429 } | |
430 if(SDL_MUSTLOCK(dst)) { | |
431 SDL_UnlockSurface(dst); | |
432 } | |
433 if(SDL_MUSTLOCK(src)) { | |
434 SDL_UnlockSurface(src); | |
435 } | |
436 // Using the per surface alpha value does not | |
437 // work out for mostly transparent pixels. | |
438 // Thus disabling the part here - this needs a | |
439 // more complex refactoring. | |
440 // if(avgalpha < 240) { | |
441 // SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha); | |
442 //} | |
443 SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key); | |
444 SDL_Surface *convert = SDL_DisplayFormat(dst); | |
445 SDL_FreeSurface(dst); | |
446 FL_DBG(_log, LMsg("sdlimage ") | |
447 << "Trying to alpha-optimize image. SUCCESS: colorkey is " << key); | |
448 return convert; | |
449 } // end optimize | |
450 | |
451 bool SDLImage::putPixel(int x, int y, int r, int g, int b) { | |
452 if ((x < 0) || (x >= m_surface->w) || (y < 0) || (y >= m_surface->h)) { | |
453 return false; | |
454 } | |
455 | |
456 int bpp = m_surface->format->BytesPerPixel; | |
457 SDL_LockSurface(m_surface); | |
458 Uint8* p = (Uint8*)m_surface->pixels + y * m_surface->pitch + x * bpp; | |
459 Uint32 pixel = SDL_MapRGB(m_surface->format, r, g, b); | |
460 switch(bpp) | |
461 { | |
462 case 1: | |
463 *p = pixel; | |
464 break; | |
465 | |
466 case 2: | |
467 *(Uint16 *)p = pixel; | |
468 break; | |
469 | |
470 case 3: | |
471 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { | |
472 p[0] = (pixel >> 16) & 0xff; | |
473 p[1] = (pixel >> 8) & 0xff; | |
474 p[2] = pixel & 0xff; | |
475 } | |
476 else { | |
477 p[0] = pixel & 0xff; | |
478 p[1] = (pixel >> 8) & 0xff; | |
479 p[2] = (pixel >> 16) & 0xff; | |
480 } | |
481 break; | |
482 | |
483 case 4: | |
484 *(Uint32 *)p = pixel; | |
485 break; | |
486 } | |
487 SDL_UnlockSurface(m_surface); | |
488 return true; | |
489 } | |
490 | |
491 void SDLImage::drawLine(const Point& p1, const Point& p2, int r, int g, int b) { | |
492 // Draw a line with Bresenham, imitated from guichan | |
493 int x1 = p1.x; | |
494 int x2 = p2.x; | |
495 int y1 = p1.y; | |
496 int y2 = p2.y; | |
497 int dx = ABS(x2 - x1); | |
498 int dy = ABS(y2 - y1); | |
499 | |
500 if (dx > dy) { | |
501 if (x1 > x2) { | |
502 // swap x1, x2 | |
503 x1 ^= x2; | |
504 x2 ^= x1; | |
505 x1 ^= x2; | |
506 | |
507 // swap y1, y2 | |
508 y1 ^= y2; | |
509 y2 ^= y1; | |
510 y1 ^= y2; | |
511 } | |
512 | |
513 if (y1 < y2) { | |
514 int y = y1; | |
515 int p = 0; | |
516 | |
517 for (int x = x1; x <= x2; x++) { | |
518 putPixel(x, y, r, g, b); | |
519 p += dy; | |
520 if (p * 2 >= dx) { | |
521 y++; | |
522 p -= dx; | |
523 } | |
524 } | |
525 } | |
526 else { | |
527 int y = y1; | |
528 int p = 0; | |
529 | |
530 for (int x = x1; x <= x2; x++) { | |
531 putPixel(x, y, r, g, b); | |
532 | |
533 p += dy; | |
534 if (p * 2 >= dx) { | |
535 y--; | |
536 p -= dx; | |
537 } | |
538 } | |
539 } | |
540 } | |
541 else { | |
542 if (y1 > y2) { | |
543 // swap y1, y2 | |
544 y1 ^= y2; | |
545 y2 ^= y1; | |
546 y1 ^= y2; | |
547 | |
548 // swap x1, x2 | |
549 x1 ^= x2; | |
550 x2 ^= x1; | |
551 x1 ^= x2; | |
552 } | |
553 | |
554 if (x1 < x2) { | |
555 int x = x1; | |
556 int p = 0; | |
557 | |
558 for (int y = y1; y <= y2; y++) { | |
559 putPixel(x, y, r, g, b); | |
560 p += dx; | |
561 if (p * 2 >= dy) { | |
562 x++; | |
563 p -= dy; | |
564 } | |
565 } | |
566 } | |
567 else { | |
568 int x = x1; | |
569 int p = 0; | |
570 | |
571 for (int y = y1; y <= y2; y++) { | |
572 putPixel(x, y, r, g, b); | |
573 p += dx; | |
574 if (p * 2 >= dy) { | |
575 x--; | |
576 p -= dy; | |
577 } | |
578 } | |
579 } | |
580 } | |
581 } | |
582 | |
583 void SDLImage::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b) { | |
584 drawLine(p1, p2, r, g, b); | |
585 drawLine(p2, p3, r, g, b); | |
586 drawLine(p3, p4, r, g, b); | |
587 drawLine(p4, p1, r, g, b); | |
588 } | |
589 | |
590 void SDLImage::saveImage(const std::string& filename) { | |
591 if(m_surface) { | |
592 const unsigned int swidth = getWidth(); | |
593 const unsigned int sheight = getHeight(); | |
594 Uint32 rmask, gmask, bmask, amask; | |
595 SDL_Surface *surface = NULL; | |
596 | |
597 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | |
598 rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; | |
599 #else | |
600 rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; | |
601 #endif | |
602 | |
603 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, | |
604 sheight, 24, | |
605 rmask, gmask, bmask, 0); | |
606 | |
607 if(surface == NULL) { | |
608 return; | |
609 } | |
610 | |
611 SDL_BlitSurface(m_surface, NULL, surface, NULL); | |
612 | |
613 saveAsPng(filename, *surface); | |
614 SDL_FreeSurface(surface); | |
615 } | |
616 } | |
617 | |
618 void SDLImage::setClipArea(const Rect& cliparea, bool clear) { | |
619 SDL_Rect rect; | |
620 rect.x = cliparea.x; | |
621 rect.y = cliparea.y; | |
622 rect.w = cliparea.w; | |
623 rect.h = cliparea.h; | |
624 SDL_SetClipRect(m_surface, &rect); | |
625 if (clear) { | |
626 SDL_FillRect(m_surface, &rect, 0x00); | |
627 } | |
628 } | |
629 } |