sdl/sdl_{renderer,texture}.cpp: Do no access (SDL_Surface *)->format->alpha directly.
[supertux.git] / src / video / sdl / sdl_texture.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include <config.h>
18
19 #include "supertux/gameconfig.hpp"
20 #include "supertux/globals.hpp"
21 #include "video/color.hpp"
22 #include "video/sdl/sdl_texture.hpp"
23
24 #include <assert.h>
25
26 #include <SDL.h>
27
28 namespace {
29 #define BILINEAR
30
31 #ifdef NAIVE
32 SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
33 {
34   if(numerator == denominator)
35   {
36     src->refcount++;
37     return src;
38   }
39   else
40   {
41     SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
42     int bpp = dst->format->BytesPerPixel;
43     if(SDL_MUSTLOCK(src))
44     {
45       SDL_LockSurface(src);
46     }
47     if(SDL_MUSTLOCK(dst))
48     {
49       SDL_LockSurface(dst);
50     }
51     for(int y = 0;y < dst->h;y++) {
52       for(int x = 0;x < dst->w;x++) {
53         Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp;
54         Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
55         switch(bpp) {
56           case 4:
57             dstpixel[3] = srcpixel[3];
58           case 3:
59             dstpixel[2] = srcpixel[2];
60           case 2:
61             dstpixel[1] = srcpixel[1];
62           case 1:
63             dstpixel[0] = srcpixel[0];
64         }
65       }
66     }
67     if(SDL_MUSTLOCK(dst))
68     {
69       SDL_UnlockSurface(dst);
70     }
71     if(SDL_MUSTLOCK(src))
72     {
73       SDL_UnlockSurface(src);
74     }
75     if(!src->format->Amask)
76     {
77       if(src->flags & SDL_SRCALPHA)
78       {
79         SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
80       }
81       if(src->flags & SDL_SRCCOLORKEY)
82       {
83         SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
84       }
85     }
86     return dst;
87   }
88 } // namespace
89 #endif
90
91 static void surface_copy_alpha (SDL_Surface *dst, SDL_Surface *src)
92 {
93 #if SDL_VERSION_ATLEAST(1,3,0)
94   Uint8 alpha;
95   int status;
96
97   alpha = 255;
98   status = SDL_GetSurfaceAlphaMod (src, &alpha);
99   if (status == 0)
100     SDL_SetSurfaceAlphaMod (dst, alpha);
101 #else
102   SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha);
103 #endif
104 }
105
106 static void surface_copy_colorkey (SDL_Surface *dst, SDL_Surface *src)
107 {
108 #if SDL_VERSION_ATLEAST(1,3,0)
109   Uint32 colorkey;
110   int status;
111
112   colorkey = 0;
113   /* Returns non-zero if color key is disabled. */
114   status = SDL_GetColorKey (src, &colorkey);
115   if (status == 0)
116     SDL_SetColorKey (dst, /* enabled = */ 1, colorkey);
117 #else
118   SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey);
119 #endif
120 }
121
122 #ifdef BILINEAR
123 void getpixel(SDL_Surface *src, int srcx, int srcy, Uint8 color[4])
124 {
125   int bpp = src->format->BytesPerPixel;
126   if(srcx == src->w)
127   {
128     srcx--;
129   }
130   if(srcy == src->h)
131   {
132     srcy--;
133   }
134   Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp;
135   Uint32 mapped = 0;
136   switch(bpp) {
137     case 1:
138       mapped = *srcpixel;
139       break;
140     case 2:
141       mapped = *(Uint16 *)srcpixel;
142       break;
143     case 3:
144 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
145       mapped |= srcpixel[0] << 16;
146       mapped |= srcpixel[1] << 8;
147       mapped |= srcpixel[2] << 0;
148 #else
149       mapped |= srcpixel[0] << 0;
150       mapped |= srcpixel[1] << 8;
151       mapped |= srcpixel[2] << 16;
152 #endif
153       break;
154     case 4:
155       mapped = *(Uint32 *)srcpixel;
156       break;
157   }
158   SDL_GetRGBA(mapped, src->format, &color[0], &color[1], &color[2], &color[3]);
159 }
160
161 void merge(Uint8 color[4], Uint8 color0[4], Uint8 color1[4], int rem, int total)
162 {
163   color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total;
164   color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total;
165   color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total;
166   color[3] = (color0[3] * (total - rem) + color1[3] * rem) / total;
167 }
168
169 SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator)
170 {
171   if(numerator == denominator)
172   {
173     src->refcount++;
174     return src;
175   }
176   else
177   {
178     SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
179     int bpp = dst->format->BytesPerPixel;
180     if(SDL_MUSTLOCK(src))
181     {
182       SDL_LockSurface(src);
183     }
184     if(SDL_MUSTLOCK(dst))
185     {
186       SDL_LockSurface(dst);
187     }
188     for(int y = 0;y < dst->h;y++) {
189       for(int x = 0;x < dst->w;x++) {
190         int srcx = x * denominator / numerator;
191         int srcy = y * denominator / numerator;
192         Uint8 color00[4], color01[4], color10[4], color11[4];
193         getpixel(src, srcx, srcy, color00);
194         getpixel(src, srcx + 1, srcy, color01);
195         getpixel(src, srcx, srcy + 1, color10);
196         getpixel(src, srcx + 1, srcy + 1, color11);
197         Uint8 color0[4], color1[4], color[4];
198         int remx = x * denominator % numerator;
199         merge(color0, color00, color01, remx, numerator);
200         merge(color1, color10, color11, remx, numerator);
201         int remy = y * denominator % numerator;
202         merge(color, color0, color1, remy, numerator);
203         Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
204         Uint32 mapped = SDL_MapRGBA(dst->format, color[0], color[1], color[2], color[3]);
205         switch(bpp) {
206           case 1:
207             *dstpixel = mapped;
208             break;
209           case 2:
210             *(Uint16 *)dstpixel = mapped;
211             break;
212           case 3:
213 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
214             dstpixel[0] = (mapped >> 16) & 0xff;
215             dstpixel[1] = (mapped >> 8) & 0xff;
216             dstpixel[2] = (mapped >> 0) & 0xff;
217 #else
218             dstpixel[0] = (mapped >> 0) & 0xff;
219             dstpixel[1] = (mapped >> 8) & 0xff;
220             dstpixel[2] = (mapped >> 16) & 0xff;
221 #endif
222             break;
223           case 4:
224             *(Uint32 *)dstpixel = mapped;
225             break;
226         }
227       }
228     }
229     if(SDL_MUSTLOCK(dst))
230     {
231       SDL_UnlockSurface(dst);
232     }
233     if(SDL_MUSTLOCK(src))
234     {
235       SDL_UnlockSurface(src);
236     }
237     if(!src->format->Amask)
238     {
239       if(src->flags & SDL_SRCALPHA)
240       {
241         surface_copy_alpha (dst, src);
242       }
243       if(src->flags & SDL_SRCCOLORKEY)
244       {
245         surface_copy_colorkey (dst, src);
246       }
247     }
248     return dst;
249   }
250 }
251 #endif /* BILINEAR */
252
253 SDL_Surface *horz_flip(SDL_Surface *src)
254 {
255   SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
256   int bpp = dst->format->BytesPerPixel;
257   if(SDL_MUSTLOCK(src))
258   {
259     SDL_LockSurface(src);
260   }
261   if(SDL_MUSTLOCK(dst))
262   {
263     SDL_LockSurface(dst);
264   }
265   for(int y = 0;y < dst->h;y++) {
266     for(int x = 0;x < dst->w;x++) {
267       Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
268       Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + (dst->w - x - 1) * bpp;
269       switch(bpp) {
270         case 4:
271           dstpixel[3] = srcpixel[3];
272         case 3:
273           dstpixel[2] = srcpixel[2];
274         case 2:
275           dstpixel[1] = srcpixel[1];
276         case 1:
277           dstpixel[0] = srcpixel[0];
278       }
279     }
280   }
281   if(SDL_MUSTLOCK(dst))
282   {
283     SDL_UnlockSurface(dst);
284   }
285   if(SDL_MUSTLOCK(src))
286   {
287     SDL_UnlockSurface(src);
288   }
289   if(!src->format->Amask)
290   {
291     if(src->flags & SDL_SRCALPHA)
292     {
293       surface_copy_alpha (dst, src);
294     }
295     if(src->flags & SDL_SRCCOLORKEY)
296     {
297       surface_copy_colorkey (dst, src);
298     }
299   }
300   return dst;
301 }
302
303 SDL_Surface *vert_flip(SDL_Surface *src)
304 {
305   SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
306   int bpp = dst->format->BytesPerPixel;
307   if(SDL_MUSTLOCK(src))
308   {
309     SDL_LockSurface(src);
310   }
311   if(SDL_MUSTLOCK(dst))
312   {
313     SDL_LockSurface(dst);
314   }
315   for(int y = 0;y < dst->h;y++) {
316     for(int x = 0;x < dst->w;x++) {
317       Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
318       Uint8 *dstpixel = (Uint8 *) dst->pixels + (dst->h - y - 1) * dst->pitch + x * bpp;
319       switch(bpp) {
320         case 4:
321           dstpixel[3] = srcpixel[3];
322         case 3:
323           dstpixel[2] = srcpixel[2];
324         case 2:
325           dstpixel[1] = srcpixel[1];
326         case 1:
327           dstpixel[0] = srcpixel[0];
328       }
329     }
330   }
331   if(SDL_MUSTLOCK(dst))
332   {
333     SDL_UnlockSurface(dst);
334   }
335   if(SDL_MUSTLOCK(src))
336   {
337     SDL_UnlockSurface(src);
338   }
339   if(!src->format->Amask)
340   {
341     if(src->flags & SDL_SRCALPHA)
342     {
343       surface_copy_alpha (dst, src);
344     }
345     if(src->flags & SDL_SRCCOLORKEY)
346     {
347       surface_copy_colorkey (dst, src);
348     }
349   }
350   return dst;
351 }
352
353 SDL_Surface *colorize(SDL_Surface *src, const Color &color)
354 {
355   SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, src->format->Amask);
356 #if SDL_VERSION_ATLEAST(1,3,0)
357   assert ((color.red >= 0) && (color.red <= 1.0));
358   assert ((color.green >= 0) && (color.green <= 1.0));
359   assert ((color.blue >= 0) && (color.blue <= 1.0));
360   assert(color.red != 1.0 || color.green != 1.0 || color.blue != 1.0);
361   Uint8 red   = (Uint8) (color.red   * 255.0);
362   Uint8 green = (Uint8) (color.green * 255.0);
363   Uint8 blue  = (Uint8) (color.blue  * 255.0);
364   
365   SDL_SetSurfaceColorMod (dst, red, green, blue);
366 #else
367   // FIXME: This is really slow
368   assert(color.red != 1.0 || color.green != 1.0 || color.blue != 1.0);
369   int red = (int) (color.red * 256);
370   int green = (int) (color.green * 256);
371   int blue = (int) (color.blue * 256);
372   int bpp = dst->format->BytesPerPixel;
373   if(SDL_MUSTLOCK(src))
374   {
375     SDL_LockSurface(src);
376   }
377   if(SDL_MUSTLOCK(dst))
378   {
379     SDL_LockSurface(dst);
380   }
381   for(int y = 0;y < dst->h;y++) {
382     for(int x = 0;x < dst->w;x++) {
383       Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
384       Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
385       Uint32 mapped = 0;
386       switch(bpp) {
387         case 1:
388           mapped = *srcpixel;
389           break;
390         case 2:
391           mapped = *(Uint16 *)srcpixel;
392           break;
393         case 3:
394 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
395           mapped |= srcpixel[0] << 16;
396           mapped |= srcpixel[1] << 8;
397           mapped |= srcpixel[2] << 0;
398 #else
399           mapped |= srcpixel[0] << 0;
400           mapped |= srcpixel[1] << 8;
401           mapped |= srcpixel[2] << 16;
402 #endif
403           break;
404         case 4:
405           mapped = *(Uint32 *)srcpixel;
406           break;
407       }
408       if(src->format->Amask || !(src->flags & SDL_SRCCOLORKEY) || mapped != src->format->colorkey)
409       {
410         Uint8 r, g, b, a;
411         SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a);
412         mapped = SDL_MapRGBA(dst->format, (r * red) >> 8, (g * green) >> 8, (b * blue) >> 8, a);
413       }
414       switch(bpp) {
415         case 1:
416           *dstpixel = mapped;
417           break;
418         case 2:
419           *(Uint16 *)dstpixel = mapped;
420           break;
421         case 3:
422 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
423           dstpixel[0] = (mapped >> 16) & 0xff;
424           dstpixel[1] = (mapped >> 8) & 0xff;
425           dstpixel[2] = (mapped >> 0) & 0xff;
426 #else
427           dstpixel[0] = (mapped >> 0) & 0xff;
428           dstpixel[1] = (mapped >> 8) & 0xff;
429           dstpixel[2] = (mapped >> 16) & 0xff;
430 #endif
431           break;
432         case 4:
433           *(Uint32 *)dstpixel = mapped;
434           break;
435       }
436     }
437   }
438 #endif /* SDL version < 1.3.0 */
439   if(SDL_MUSTLOCK(dst))
440   {
441     SDL_UnlockSurface(dst);
442   }
443   if(SDL_MUSTLOCK(src))
444   {
445     SDL_UnlockSurface(src);
446   }
447   if(!src->format->Amask)
448   {
449     if(src->flags & SDL_SRCALPHA)
450     {
451       surface_copy_alpha (dst, src);
452     }
453     if(src->flags & SDL_SRCCOLORKEY)
454     {
455       surface_copy_colorkey (dst, src);
456     }
457   }
458   return dst;
459 }
460
461 SDL_Surface *optimize(SDL_Surface *src)
462 {
463   if(!src->format->Amask)
464   {
465     return SDL_DisplayFormat(src);
466   }
467   else
468   {
469     int bpp;
470     bool colors[(1 << 12)];
471     memset(colors, 0, (1 << 12) * sizeof(bool));
472 #if 0
473     int transparent = 0;
474     int opaque = 0;
475     int semitransparent = 0;
476     int alphasum = 0;
477     int squaredalphasum = 0;
478
479     int bpp = src->format->BytesPerPixel;
480     if(SDL_MUSTLOCK(src))
481     {
482       SDL_LockSurface(src);
483     }
484     for(int y = 0;y < src->h;y++) {
485       for(int x = 0;x < src->w;x++) {
486         Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
487         Uint32 mapped = 0;
488         switch(bpp) {
489           case 1:
490             mapped = *pixel;
491             break;
492           case 2:
493             mapped = *(Uint16 *)pixel;
494             break;
495           case 3:
496 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
497             mapped |= pixel[0] << 16;
498             mapped |= pixel[1] << 8;
499             mapped |= pixel[2] << 0;
500 #else
501             mapped |= pixel[0] << 0;
502             mapped |= pixel[1] << 8;
503             mapped |= pixel[2] << 16;
504 #endif
505             break;
506           case 4:
507             mapped = *(Uint32 *)pixel;
508             break;
509         }
510         Uint8 red, green, blue, alpha;
511         SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
512         if(alpha < 16)
513         {
514           transparent++;
515         }
516         else if (alpha > 240)
517         {
518           opaque++;
519           alphasum += alpha;
520           squaredalphasum += alpha * alpha;
521         }
522         else
523         {
524           semitransparent++;
525           squaredalphasum += alpha * alpha;
526         }
527         if(alpha != 0)
528         {
529           colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true;
530         }
531       }
532     }
533     if(SDL_MUSTLOCK(src))
534     {
535       SDL_UnlockSurface(src);
536     }
537     int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0;
538     int avgsquaredalpha = (opaque + semitransparent) ? squaredalphasum / (opaque + semitransparent) : 0;
539     int alphavariance = avgsquaredalpha - avgalpha * avgalpha;
540     if(semitransparent > ((transparent + opaque + semitransparent) / 8) && alphavariance > 16)
541     {
542       return SDL_DisplayFormatAlpha(src);
543     }
544 #endif
545     int keycolor = -1;
546     for(int i = 0;i < (1 << 12);i++)
547     {
548       if(!colors[i])
549       {
550         keycolor = i;
551       }
552     }
553     if(keycolor == -1)
554     {
555       return SDL_DisplayFormatAlpha(src);
556     }
557     SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA), src->w, src->h, src->format->BitsPerPixel, src->format->Rmask,  src->format->Gmask, src->format->Bmask, 0);
558     bpp = dst->format->BytesPerPixel;
559     Uint32 key = SDL_MapRGB(dst->format, (((keycolor & 0xf00) >> 4) | 0xf), ((keycolor & 0xf0) | 0xf), (((keycolor & 0xf) << 4) | 0xf));
560     if(SDL_MUSTLOCK(src))
561     {
562       SDL_LockSurface(src);
563     }
564     if(SDL_MUSTLOCK(dst))
565     {
566       SDL_LockSurface(dst);
567     }
568     for(int y = 0;y < dst->h;y++) {
569       for(int x = 0;x < dst->w;x++) {
570         Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
571         Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
572         Uint32 mapped = 0;
573         switch(bpp) {
574           case 1:
575             mapped = *srcpixel;
576             break;
577           case 2:
578             mapped = *(Uint16 *)srcpixel;
579             break;
580           case 3:
581 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
582             mapped |= srcpixel[0] << 16;
583             mapped |= srcpixel[1] << 8;
584             mapped |= srcpixel[2] << 0;
585 #else
586             mapped |= srcpixel[0] << 0;
587             mapped |= srcpixel[1] << 8;
588             mapped |= srcpixel[2] << 16;
589 #endif
590             break;
591           case 4:
592             mapped = *(Uint32 *)srcpixel;
593             break;
594         }
595         Uint8 red, green, blue, alpha;
596         SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
597         //if(alpha < (avgalpha / 4))
598         if(alpha < 8)
599         {
600           mapped = key;
601         }
602         else
603         {
604           mapped = SDL_MapRGB(dst->format, red, green, blue);
605         }
606         switch(bpp) {
607           case 1:
608             *dstpixel = mapped;
609             break;
610           case 2:
611             *(Uint16 *)dstpixel = mapped;
612             break;
613           case 3:
614 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
615             dstpixel[0] = (mapped >> 16) & 0xff;
616             dstpixel[1] = (mapped >> 8) & 0xff;
617             dstpixel[2] = (mapped >> 0) & 0xff;
618 #else
619             dstpixel[0] = (mapped >> 0) & 0xff;
620             dstpixel[1] = (mapped >> 8) & 0xff;
621             dstpixel[2] = (mapped >> 16) & 0xff;
622 #endif
623             break;
624           case 4:
625             *(Uint32 *)dstpixel = mapped;
626             break;
627         }
628       }
629     }
630     if(SDL_MUSTLOCK(dst))
631     {
632       SDL_UnlockSurface(dst);
633     }
634     if(SDL_MUSTLOCK(src))
635     {
636       SDL_UnlockSurface(src);
637     }
638     /*
639     if(avgalpha < 240)
640     {
641       SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha);
642     }
643     */
644     SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key);
645     SDL_Surface *convert = SDL_DisplayFormat(dst);
646     SDL_FreeSurface(dst);
647     return convert;
648   }
649 }
650 }
651
652 SDLTexture::SDLTexture(SDL_Surface* image) :
653   texture()
654 {
655   texture = optimize(image);
656   //width = texture->w;
657   //height = texture->h;
658   int numerator   = 1;
659   int denominator = 1;
660   //FIXME: float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
661   //FIXME: float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
662   /* FIXME: 
663      if(xfactor < yfactor)
664      {
665      numerator = config->screenwidth;
666      denominator = SCREEN_WIDTH;
667      }
668      else
669      {
670      numerator = config->screenheight;
671      denominator = SCREEN_HEIGHT;
672      }
673   */
674   cache[NO_EFFECT][Color::WHITE] = scale(texture, numerator, denominator);
675 }
676
677 SDLTexture::~SDLTexture()
678 {
679   SDL_FreeSurface(texture);
680 }
681
682 SDL_Surface*
683 SDLTexture::get_transform(const Color &color, DrawingEffect effect)
684 {
685   if(cache[NO_EFFECT][color] == 0) {
686     assert(cache[NO_EFFECT][Color::WHITE]);
687     cache[NO_EFFECT][color] = colorize(cache[NO_EFFECT][Color::WHITE], color);
688   }
689   if(cache[effect][color] == 0) {
690     assert(cache[NO_EFFECT][color]);
691     switch(effect) {
692       case NO_EFFECT:
693         break;
694       case HORIZONTAL_FLIP:
695         cache[HORIZONTAL_FLIP][color] = horz_flip(cache[NO_EFFECT][color]);
696         break;
697       case VERTICAL_FLIP:
698         cache[VERTICAL_FLIP][color] = vert_flip(cache[NO_EFFECT][color]);
699         break;
700       default:
701         return 0;
702     }
703   }
704   return cache[effect][color];
705 }
706
707 /* EOF */