Implemented Tux growing animation.
[supertux.git] / src / texture.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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 Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20
21 #include <assert.h>
22 #include <iostream>
23 #include <algorithm>
24 #include "SDL.h"
25 #include "SDL_image.h"
26 #include "texture.h"
27 #include "globals.h"
28 #include "setup.h"
29
30 Surface::Surfaces Surface::surfaces;
31
32 SurfaceData::SurfaceData(SDL_Surface* temp, int use_alpha_)
33     : type(SURFACE), surface(0), use_alpha(use_alpha_)
34 {
35   // Copy the given surface and make sure that it is not stored in
36   // video memory
37   surface = SDL_CreateRGBSurface(temp->flags & (~SDL_HWSURFACE),
38                                  temp->w, temp->h,
39                                  temp->format->BitsPerPixel,
40                                  temp->format->Rmask,
41                                  temp->format->Gmask,
42                                  temp->format->Bmask,
43                                  temp->format->Amask);
44   if(!surface)
45     st_abort("No memory left.", "");
46   SDL_SetAlpha(temp,0,0);
47   SDL_BlitSurface(temp, NULL, surface, NULL);
48 }
49
50 SurfaceData::SurfaceData(const std::string& file_, int use_alpha_)
51     : type(LOAD), surface(0), file(file_), use_alpha(use_alpha_)
52 {}
53
54 SurfaceData::SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, int use_alpha_)
55     : type(LOAD_PART), surface(0), file(file_), use_alpha(use_alpha_),
56     x(x_), y(y_), w(w_), h(h_)
57 {}
58
59 SurfaceData::~SurfaceData()
60 {
61   SDL_FreeSurface(surface);
62 }
63
64 SurfaceImpl*
65 SurfaceData::create()
66 {
67 #ifndef NOOPENGL
68   if (use_gl)
69     return create_SurfaceOpenGL();
70   else
71     return create_SurfaceSDL();
72 #else
73   return create_SurfaceSDL();
74 #endif
75 }
76
77 SurfaceSDL*
78 SurfaceData::create_SurfaceSDL()
79 {
80   switch(type)
81   {
82   case LOAD:
83     return new SurfaceSDL(file, use_alpha);
84   case LOAD_PART:
85     return new SurfaceSDL(file, x, y, w, h, use_alpha);
86   case SURFACE:
87     return new SurfaceSDL(surface, use_alpha);
88   }
89   assert(0);
90 }
91
92 SurfaceOpenGL*
93 SurfaceData::create_SurfaceOpenGL()
94 {
95 #ifndef NOOPENGL
96   switch(type)
97   {
98   case LOAD:
99     return new SurfaceOpenGL(file, use_alpha);
100   case LOAD_PART:
101     return new SurfaceOpenGL(file, x, y, w, h, use_alpha);
102   case SURFACE:
103     return new SurfaceOpenGL(surface, use_alpha);
104   }
105 #endif
106   assert(0);
107 }
108
109 #ifndef NOOPENGL
110 /* Quick utility function for texture creation */
111 static int power_of_two(int input)
112 {
113   int value = 1;
114
115   while ( value < input )
116   {
117     value <<= 1;
118   }
119   return value;
120 }
121 #endif
122
123 Surface::Surface(SDL_Surface* surf, int use_alpha)
124     : data(surf, use_alpha), w(0), h(0)
125 {
126   impl = data.create();
127   if (impl)
128   {
129     w = impl->w;
130     h = impl->h;
131   }
132   surfaces.push_back(this);
133 }
134
135 Surface::Surface(const std::string& file, int use_alpha)
136     : data(file, use_alpha), w(0), h(0)
137 {
138   impl = data.create();
139   if (impl)
140   {
141     w = impl->w;
142     h = impl->h;
143   }
144   surfaces.push_back(this);
145 }
146
147 Surface::Surface(const std::string& file, int x, int y, int w, int h, int use_alpha)
148     : data(file, x, y, w, h, use_alpha), w(0), h(0)
149 {
150   impl = data.create();
151   if (impl)
152   {
153     w = impl->w;
154     h = impl->h;
155   }
156   surfaces.push_back(this);
157 }
158
159 void
160 Surface::reload()
161 {
162   delete impl;
163   impl = data.create();
164   if (impl)
165   {
166     w = impl->w;
167     h = impl->h;
168   }
169 }
170
171 Surface::~Surface()
172 {
173 #ifdef DEBUG
174   bool found = false;
175   for(std::list<Surface*>::iterator i = surfaces.begin(); i != surfaces.end();
176       ++i)
177   {
178     if(*i == this)
179     {
180       found = true; break;
181     }
182   }
183   if(!found)
184     printf("Error: Surface freed twice!!!\n");
185 #endif
186   surfaces.remove(this);
187   delete impl;
188 }
189
190 void
191 Surface::reload_all()
192 {
193   for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
194   {
195     (*i)->reload();
196   }
197 }
198
199 void
200 Surface::debug_check()
201 {
202   for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
203   {
204     printf("Surface not freed: T:%d F:%s.\n", (*i)->data.type,
205            (*i)->data.file.c_str());
206   }
207 }
208
209 void
210 Surface::draw(float x, float y, Uint8 alpha, bool upside_down, bool update)
211 {
212   if (impl)
213   {
214     if(upside_down)   // FIXME: this should be done by the SDL and OpenGL draw()
215       for(float sy = 0; sy < h; sy++)
216         impl->draw_part(0, sy, x, y+(h-sy), w, 1, alpha, update);
217
218     else if (impl->draw(x, y, alpha, update) == -2)
219       reload();
220   }
221 }
222
223 void
224 Surface::draw_bg(Uint8 alpha, bool update)
225 {
226   if (impl)
227   {
228     if (impl->draw_bg(alpha, update) == -2)
229       reload();
230   }
231 }
232
233 void
234 Surface::draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, bool update)
235 {
236   if (impl)
237   {
238     if (impl->draw_part(sx, sy, x, y, w, h, alpha, update) == -2)
239       reload();
240   }
241 }
242
243 void
244 Surface::draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update)
245 {
246   if (impl)
247   {
248     if (impl->draw_stretched(x, y, w, h, alpha, update) == -2)
249       reload();
250   }
251 }
252
253 void
254 Surface::resize(int w_, int h_)
255 {
256   if (impl)
257   {
258     w = w_;
259     h = h_;
260     if (impl->resize(w_,h_) == -2)
261       reload();
262   }
263 }
264
265 Surface* Surface::CaptureScreen()
266 {
267   Surface *cap_screen;
268
269   if (!(screen->flags & SDL_OPENGL))
270   {
271     cap_screen = new Surface(SDL_GetVideoSurface(),false);
272   }
273
274 #ifndef NOOPENGL
275   if (use_gl)
276   {
277     SDL_Surface *temp;
278     unsigned char *pixels;
279     int i;
280     temp = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, 24,
281 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
282                                 0x000000FF, 0x0000FF00, 0x00FF0000, 0
283 #else
284                                 0x00FF0000, 0x0000FF00, 0x000000FF, 0
285 #endif
286                                );
287     if (temp == NULL)
288       st_abort("Error while trying to capture the screen in OpenGL mode","");
289
290     pixels = (unsigned char*) malloc(3 * screen->w * screen->h);
291     if (pixels == NULL)
292     {
293       SDL_FreeSurface(temp);
294       st_abort("Error while trying to capture the screen in OpenGL mode","");
295     }
296
297     glReadPixels(0, 0, screen->w, screen->h, GL_RGB, GL_UNSIGNED_BYTE, pixels);
298
299     for (i=0; i<screen->h; i++)
300       memcpy(((char *) temp->pixels) + temp->pitch * i, pixels + 3*screen->w * (screen->h-i-1), screen->w*3);
301     free(pixels);
302
303     cap_screen = new Surface(temp,false);
304     SDL_FreeSurface(temp);
305
306   }
307 #endif
308   
309 return cap_screen;
310 }
311
312 SDL_Surface*
313 sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h,  int use_alpha)
314 {
315   SDL_Rect src;
316   SDL_Surface * sdl_surface;
317   SDL_Surface * temp;
318   SDL_Surface * conv;
319
320   temp = IMG_Load(file.c_str());
321
322   if (temp == NULL)
323     st_abort("Can't load", file);
324
325   /* Set source rectangle for conv: */
326
327   src.x = x;
328   src.y = y;
329   src.w = w;
330   src.h = h;
331
332   conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
333                               temp->format->Rmask,
334                               temp->format->Gmask,
335                               temp->format->Bmask,
336                               temp->format->Amask);
337
338   /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
339      0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
340      #else
341
342      0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
343      #endif*/
344
345   SDL_SetAlpha(temp,0,0);
346
347   SDL_BlitSurface(temp, &src, conv, NULL);
348   if(use_alpha == IGNORE_ALPHA && !use_gl)
349     sdl_surface = SDL_DisplayFormat(conv);
350   else
351     sdl_surface = SDL_DisplayFormatAlpha(conv);
352
353   if (sdl_surface == NULL)
354     st_abort("Can't covert to display format", file);
355
356   if (use_alpha == IGNORE_ALPHA && !use_gl)
357     SDL_SetAlpha(sdl_surface, 0, 0);
358
359   SDL_FreeSurface(temp);
360   SDL_FreeSurface(conv);
361
362   return sdl_surface;
363 }
364
365 SDL_Surface*
366 sdl_surface_from_file(const std::string& file, int use_alpha)
367 {
368   SDL_Surface* sdl_surface;
369   SDL_Surface* temp;
370
371   temp = IMG_Load(file.c_str());
372
373   if (temp == NULL)
374     st_abort("Can't load", file);
375
376   if(use_alpha == IGNORE_ALPHA && !use_gl)
377     sdl_surface = SDL_DisplayFormat(temp);
378   else
379     sdl_surface = SDL_DisplayFormatAlpha(temp);
380
381   if (sdl_surface == NULL)
382     st_abort("Can't covert to display format", file);
383
384   if (use_alpha == IGNORE_ALPHA && !use_gl)
385     SDL_SetAlpha(sdl_surface, 0, 0);
386
387   SDL_FreeSurface(temp);
388
389   return sdl_surface;
390 }
391
392 SDL_Surface*
393 sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha)
394 {
395   SDL_Surface* sdl_surface;
396   Uint32 saved_flags;
397   Uint8  saved_alpha;
398
399   /* Save the alpha blending attributes */
400   saved_flags = sdl_surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
401   saved_alpha = sdl_surf->format->alpha;
402   if ( (saved_flags & SDL_SRCALPHA)
403        == SDL_SRCALPHA )
404   {
405     SDL_SetAlpha(sdl_surf, 0, 0);
406   }
407
408   if(use_alpha == IGNORE_ALPHA && !use_gl)
409     sdl_surface = SDL_DisplayFormat(sdl_surf);
410   else
411     sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
412
413   /* Restore the alpha blending attributes */
414   if ( (saved_flags & SDL_SRCALPHA)
415        == SDL_SRCALPHA )
416   {
417     SDL_SetAlpha(sdl_surface, saved_flags, saved_alpha);
418   }
419
420   if (sdl_surface == NULL)
421     st_abort("Can't covert to display format", "SURFACE");
422
423   if (use_alpha == IGNORE_ALPHA && !use_gl)
424     SDL_SetAlpha(sdl_surface, 0, 0);
425
426   return sdl_surface;
427 }
428
429 //---------------------------------------------------------------------------
430
431 SurfaceImpl::SurfaceImpl()
432 {}
433
434 SurfaceImpl::~SurfaceImpl()
435 {
436   SDL_FreeSurface(sdl_surface);
437 }
438
439 SDL_Surface* SurfaceImpl::get_sdl_surface() const
440 {
441   return sdl_surface;
442 }
443
444 int SurfaceImpl::resize(int w_, int h_)
445 {
446   w = w_;
447   h = h_;
448   SDL_Rect dest;
449   dest.x = 0;
450   dest.y = 0;
451   dest.w = w;
452   dest.h = h;
453   int ret = SDL_SoftStretch(sdl_surface, NULL,
454                             sdl_surface, &dest);
455   return ret;
456 }
457
458 #ifndef NOOPENGL
459 SurfaceOpenGL::SurfaceOpenGL(SDL_Surface* surf, int use_alpha)
460 {
461   sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
462   create_gl(sdl_surface,&gl_texture);
463
464   w = sdl_surface->w;
465   h = sdl_surface->h;
466 }
467
468 SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int use_alpha)
469 {
470   sdl_surface = sdl_surface_from_file(file, use_alpha);
471   create_gl(sdl_surface,&gl_texture);
472
473   w = sdl_surface->w;
474   h = sdl_surface->h;
475 }
476
477 SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int x, int y, int w, int h, int use_alpha)
478 {
479   sdl_surface = sdl_surface_part_from_file(file,x,y,w,h,use_alpha);
480   create_gl(sdl_surface, &gl_texture);
481
482   w = sdl_surface->w;
483   h = sdl_surface->h;
484 }
485
486 SurfaceOpenGL::~SurfaceOpenGL()
487 {
488   glDeleteTextures(1, &gl_texture);
489 }
490
491 void
492 SurfaceOpenGL::create_gl(SDL_Surface * surf, GLuint * tex)
493 {
494   Uint32 saved_flags;
495   Uint8  saved_alpha;
496   int w, h;
497   SDL_Surface *conv;
498
499   w = power_of_two(surf->w);
500   h = power_of_two(surf->h),
501
502 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
503       conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
504                                   0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
505 #else
506       conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
507                                   0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
508 #endif
509
510   /* Save the alpha blending attributes */
511   saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
512   saved_alpha = surf->format->alpha;
513   if ( (saved_flags & SDL_SRCALPHA)
514        == SDL_SRCALPHA )
515   {
516     SDL_SetAlpha(surf, 0, 0);
517   }
518
519   SDL_BlitSurface(surf, 0, conv, 0);
520
521   /* Restore the alpha blending attributes */
522   if ( (saved_flags & SDL_SRCALPHA)
523        == SDL_SRCALPHA )
524   {
525     SDL_SetAlpha(surf, saved_flags, saved_alpha);
526   }
527
528   glGenTextures(1, &*tex);
529   glBindTexture(GL_TEXTURE_2D , *tex);
530   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
531   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
532   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
533   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
534   glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
535   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
536   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
537
538   SDL_FreeSurface(conv);
539 }
540
541 int
542 SurfaceOpenGL::draw(float x, float y, Uint8 alpha, bool update)
543 {
544   float pw = power_of_two(w);
545   float ph = power_of_two(h);
546
547   glEnable(GL_TEXTURE_2D);
548   glEnable(GL_BLEND);
549   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
550
551   glColor4ub(alpha, alpha, alpha, alpha);
552
553   glBindTexture(GL_TEXTURE_2D, gl_texture);
554
555   glBegin(GL_QUADS);
556   glTexCoord2f(0, 0);
557   glVertex2f(x, y);
558   glTexCoord2f((float)w / pw, 0);
559   glVertex2f((float)w+x, y);
560   glTexCoord2f((float)w / pw, (float)h / ph);  glVertex2f((float)w+x, (float)h+y);
561   glTexCoord2f(0, (float)h / ph);
562   glVertex2f(x, (float)h+y);
563   glEnd();
564
565   glDisable(GL_TEXTURE_2D);
566   glDisable(GL_BLEND);
567
568   (void) update; // avoid compiler warning
569
570   return 0;
571 }
572
573 int
574 SurfaceOpenGL::draw_bg(Uint8 alpha, bool update)
575 {
576   float pw = power_of_two(w);
577   float ph = power_of_two(h);
578
579   glColor3ub(alpha, alpha, alpha);
580
581   glEnable(GL_TEXTURE_2D);
582   glBindTexture(GL_TEXTURE_2D, gl_texture);
583
584   glBegin(GL_QUADS);
585   glTexCoord2f(0, 0);
586   glVertex2f(0, 0);
587   glTexCoord2f((float)w / pw, 0);
588   glVertex2f(screen->w, 0);
589   glTexCoord2f((float)w / pw, (float)h / ph);
590   glVertex2f(screen->w, screen->h);
591   glTexCoord2f(0, (float)h / ph);
592   glVertex2f(0, screen->h);
593   glEnd();
594
595   glDisable(GL_TEXTURE_2D);
596
597   (void) update; // avoid compiler warning
598
599   return 0;
600 }
601
602 int
603 SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update)
604 {
605   float pw = power_of_two(int(this->w));
606   float ph = power_of_two(int(this->h));
607
608   glBindTexture(GL_TEXTURE_2D, gl_texture);
609
610   glEnable(GL_BLEND);
611   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
612
613   glColor4ub(alpha, alpha, alpha, alpha);
614
615   glEnable(GL_TEXTURE_2D);
616
617
618   glBegin(GL_QUADS);
619   glTexCoord2f(sx / pw, sy / ph);
620   glVertex2f(x, y);
621   glTexCoord2f((float)(sx + w) / pw, sy / ph);
622   glVertex2f(w+x, y);
623   glTexCoord2f((sx+w) / pw, (sy+h) / ph);
624   glVertex2f(w +x, h+y);
625   glTexCoord2f(sx / pw, (float)(sy+h) / ph);
626   glVertex2f(x, h+y);
627   glEnd();
628
629   glDisable(GL_TEXTURE_2D);
630   glDisable(GL_BLEND);
631
632   (void) update; // avoid warnings
633   return 0;
634 }
635
636 int
637 SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool update)
638 {
639   float pw = power_of_two(int(this->w));
640   float ph = power_of_two(int(this->h));
641
642   glBindTexture(GL_TEXTURE_2D, gl_texture);
643
644   glEnable(GL_BLEND);
645   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
646
647   glColor4ub(alpha, alpha, alpha, alpha);
648
649   glEnable(GL_TEXTURE_2D);
650
651
652   glBegin(GL_QUADS);
653   glTexCoord2f(0, 0);
654   glVertex2f(x, y);
655   glTexCoord2f((float)w / pw, 0);
656   glVertex2f(sw+x, y);
657   glTexCoord2f((float)w / pw, (float)h / ph);  glVertex2f((float)sw+x, (float)sh+y);
658   glVertex2f(sw +x, sh+y);
659   glTexCoord2f(0, (float)h / ph);
660   glVertex2f(x, sh+y);
661   glEnd();
662
663   glDisable(GL_TEXTURE_2D);
664   glDisable(GL_BLEND);
665
666   (void) update; // avoid warnings
667   return 0;
668 }
669
670 #endif
671
672 SurfaceSDL::SurfaceSDL(SDL_Surface* surf, int use_alpha)
673 {
674   sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
675   w = sdl_surface->w;
676   h = sdl_surface->h;
677 }
678
679 SurfaceSDL::SurfaceSDL(const std::string& file, int use_alpha)
680 {
681   sdl_surface = sdl_surface_from_file(file, use_alpha);
682   w = sdl_surface->w;
683   h = sdl_surface->h;
684 }
685
686 SurfaceSDL::SurfaceSDL(const std::string& file, int x, int y, int w, int h,  int use_alpha)
687 {
688   sdl_surface = sdl_surface_part_from_file(file, x, y, w, h, use_alpha);
689   w = sdl_surface->w;
690   h = sdl_surface->h;
691 }
692
693 int
694 SurfaceSDL::draw(float x, float y, Uint8 alpha, bool update)
695 {
696   SDL_Rect dest;
697
698   dest.x = (int)x;
699   dest.y = (int)y;
700   dest.w = w;
701   dest.h = h;
702
703   if(alpha != 255)
704     {
705     /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha
706       to temp sur, blit the temp into the screen */
707     /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that
708       already have an alpha mask yet... */
709
710     SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
711                                     sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel,
712                                     sdl_surface->format->Rmask, sdl_surface->format->Gmask,
713                                     sdl_surface->format->Bmask,
714                                     0);
715     int colorkey = SDL_MapRGB(sdl_surface_copy->format, 255, 0, 255);
716     SDL_FillRect(sdl_surface_copy, NULL, colorkey);
717     SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey);
718
719
720     SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
721     SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha);
722
723     int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest);
724
725     if (update == UPDATE)
726       SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
727
728     SDL_FreeSurface (sdl_surface_copy);
729     return ret;
730     }
731
732   int ret = SDL_BlitSurface(sdl_surface, NULL, screen, &dest);
733
734   if (update == UPDATE)
735     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
736
737   return ret;
738 }
739
740 int
741 SurfaceSDL::draw_bg(Uint8 alpha, bool update)
742 {
743   SDL_Rect dest;
744
745   dest.x = 0;
746   dest.y = 0;
747   dest.w = screen->w;
748   dest.h = screen->h;
749
750   if(alpha != 255)
751     {
752     /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha
753       to temp sur, blit the temp into the screen */
754     /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that
755       already have an alpha mask yet... */
756
757     SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
758                                     sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel,
759                                     sdl_surface->format->Rmask, sdl_surface->format->Gmask,
760                                     sdl_surface->format->Bmask,
761                                     0);
762     int colorkey = SDL_MapRGB(sdl_surface_copy->format, 255, 0, 255);
763     SDL_FillRect(sdl_surface_copy, NULL, colorkey);
764     SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey);
765
766
767     SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
768     SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha);
769
770     int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest);
771
772     if (update == UPDATE)
773       SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
774
775     SDL_FreeSurface (sdl_surface_copy);
776     return ret;
777     }
778
779   int ret = SDL_SoftStretch(sdl_surface, NULL, screen, &dest);
780
781   if (update == UPDATE)
782     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
783
784   return ret;
785 }
786
787 int
788 SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update)
789 {
790   SDL_Rect src, dest;
791
792   src.x = (int)sx;
793   src.y = (int)sy;
794   src.w = (int)w;
795   src.h = (int)h;
796
797   dest.x = (int)x;
798   dest.y = (int)y;
799   dest.w = (int)w;
800   dest.h = (int)h;
801
802   if(alpha != 255)
803     {
804     /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha
805       to temp sur, blit the temp into the screen */
806     /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that
807       already have an alpha mask yet... */
808
809     SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
810                                     sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel,
811                                     sdl_surface->format->Rmask, sdl_surface->format->Gmask,
812                                     sdl_surface->format->Bmask,
813                                     0);
814     int colorkey = SDL_MapRGB(sdl_surface_copy->format, 255, 0, 255);
815     SDL_FillRect(sdl_surface_copy, NULL, colorkey);
816     SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey);
817
818
819     SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
820     SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha);
821
822     int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest);
823
824     if (update == UPDATE)
825       SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
826
827     SDL_FreeSurface (sdl_surface_copy);
828     return ret;
829     }
830
831   int ret = SDL_BlitSurface(sdl_surface, &src, screen, &dest);
832
833   if (update == UPDATE)
834     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
835
836   return ret;
837 }
838
839 int
840 SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool update)
841 {
842   SDL_Rect dest;
843
844   dest.x = (int)x;
845   dest.y = (int)y;
846   dest.w = (int)sw;
847   dest.h = (int)sh;
848
849   if(alpha != 255)
850     SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha);
851
852
853   SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
854                                   sw, sh, sdl_surface->format->BitsPerPixel,
855                                   sdl_surface->format->Rmask, sdl_surface->format->Gmask,
856                                   sdl_surface->format->Bmask,
857                                   0);
858
859   SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
860   SDL_SoftStretch(sdl_surface_copy, NULL, sdl_surface_copy, &dest);
861
862   int ret = SDL_BlitSurface(sdl_surface_copy,NULL,screen,&dest);
863   SDL_FreeSurface(sdl_surface_copy);
864
865   if (update == UPDATE)
866     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
867
868   return ret;
869 }
870
871 SurfaceSDL::~SurfaceSDL()
872 {}
873
874 /* EOF */