Initial integration, lots of broken stuff
[supertux.git] / src / unison / src / video / sdl / Renderer.cpp
1 //          Copyright Timothy Goya 2007.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5
6 #include "Renderer.hpp"
7 #include "Texture.hpp"
8 #include "Window.hpp"
9 #include <unison/video/Surface.hpp>
10 #include <unison/video/Window.hpp>
11 #include <unison/video/sdl/Blitters.hpp>
12 #include <unison/video/backend/Texture.hpp>
13 #include <unison/vfs/sdl/Utils.hpp>
14
15 #include <assert.h>
16
17 #include "SDL.h"
18 #include "SDL_image.h"
19
20 namespace Unison
21 {
22    namespace Video
23    {
24       namespace SDL
25       {
26          Renderer::Renderer()
27          {
28          }
29
30          Renderer::~Renderer()
31          {
32          }
33
34          void Renderer::init()
35          {
36             SDL_InitSubSystem(SDL_INIT_VIDEO);
37          }
38
39          void Renderer::quit()
40          {
41             SDL_QuitSubSystem(SDL_INIT_VIDEO);
42          }
43
44          std::string Renderer::get_name()
45          {
46             return "sdl";
47          }
48
49          bool Renderer::is_usable()
50          {
51             SDL_InitSubSystem(SDL_INIT_VIDEO);
52
53             if(!SDL_ListModes(0, SDL_SWSURFACE))
54             {
55                SDL_QuitSubSystem(SDL_INIT_VIDEO);
56                return false;
57             }
58
59             /*const SDL_VideoInfo *info = SDL_GetVideoInfo();
60             if(SDL_VideoModeOK(info->current_w, info->current_h, 0, SDL_SWSURFACE | SDL_FULLSCREEN))
61             {
62                SDL_QuitSubSystem(SDL_INIT_VIDEO);
63                return false;
64             }*/
65
66             SDL_QuitSubSystem(SDL_INIT_VIDEO);
67
68             return true;
69          }
70
71          Surface Renderer::load_surface(const std::string &filename)
72          {
73             SDL_Surface *image = IMG_Load_RW(VFS::SDL::Utils::open_physfs_in(filename), 1);
74             assert(image);
75             Surface surface = Surface(Area(image->w, image->h));
76             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
77             assert(sdl_surface);
78             SDL::Blitters::blit_blend_none(image, Rect(), sdl_surface, Point());
79             SDL_FreeSurface(sdl_surface);
80             return surface;
81          }
82
83          Surface Renderer::load_surface(const std::string &filename, const Color &colorkey)
84          {
85             SDL_Surface *image = IMG_Load_RW(VFS::SDL::Utils::open_physfs_in(filename), 1);
86             assert(image);
87             Surface surface = Surface(Area(image->w, image->h));
88             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
89             assert(sdl_surface);
90             SDL_SetColorKey(image, SDL_SRCCOLORKEY, SDL_MapRGB(image->format, colorkey.red, colorkey.blue, colorkey.alpha));
91             SDL::Blitters::blit_blend_none(image, Rect(), sdl_surface, Point());
92             SDL_FreeSurface(sdl_surface);
93             return surface;
94          }
95
96          void Renderer::save_surface(const Surface &surface, const std::string &filename)
97          {
98             SDL_Surface *sdl_surface = SDL::Blitters::create_sdl_surface_from(surface);
99             assert(sdl_surface);
100             SDL_SaveBMP(sdl_surface, filename.c_str());
101             SDL_FreeSurface(sdl_surface);
102          }
103
104          void Renderer::blit(const Surface &src, const Rect &src_rect, Surface &dst, const Point &dst_pos, const RenderOptions &options)
105          {
106             Surface fragment;
107             if(src_rect.pos == Point() && (src_rect.size == Area() || src_rect.size == src.get_size()))
108             {
109                fragment = src;
110             }
111             else
112             {
113                fragment = Surface(src_rect.size);
114                Video::Blitters::blit_blend_none(src, src_rect, fragment, Point());
115             }
116             if(options.h_flip)
117             {
118                fragment = fragment.h_flip();
119             }
120             if(options.v_flip)
121             {
122                fragment = fragment.v_flip();
123             }
124             SDL_Surface *src_surface = Blitters::create_sdl_surface_from(fragment.modulate(options.color).modulate(options.alpha));
125             assert(src_surface);
126
127             SDL_Surface *dst_surface = Blitters::create_sdl_surface_from(dst);
128             assert(dst_surface);
129
130
131             Blitters::blit_blend(src_surface, Rect(Point(), fragment.get_size()), dst_surface, dst_pos, options.blend);
132
133             SDL_FreeSurface(dst_surface);
134             SDL_FreeSurface(src_surface);
135          }
136
137          void Renderer::blit(Backend::Texture *src, const Rect &src_rect, Surface &dst, const Point &dst_pos, const RenderOptions &options)
138          {
139             blit(src->get_surface(), src_rect, dst, dst_pos, options);
140          }
141
142          void Renderer::fill(Surface &dst, const Color &color, const Rect &rect)
143          {
144             SDL_Surface *dst_surface = Blitters::create_sdl_surface_from(dst);
145             assert(dst_surface);
146
147             Uint32 mapped = SDL_MapRGBA(dst_surface->format, color.red, color.green, color.blue, color.alpha);
148             SDL_FillRect(dst_surface, &rect, mapped);
149          }
150
151          void Renderer::fill_blend(Surface &dst, const Color &color, const Rect &rect)
152          {
153             SDL_Surface *dst_surface = Blitters::create_sdl_surface_from(dst);
154             assert(dst_surface);
155
156             Uint32 mapped = SDL_MapRGBA(dst_surface->format, color.red, color.green, color.blue, color.alpha);
157             if(color.alpha == 0xff)
158             {
159                SDL_FillRect(dst_surface, &rect, mapped);
160             }
161             else if(color.alpha != 0x00)
162             {
163                SDL_Surface *temp = SDL_CreateRGBSurface(dst_surface->flags, rect.size.x, rect.size.y, dst_surface->format->BitsPerPixel, dst_surface->format->Rmask, dst_surface->format->Gmask, dst_surface->format->Bmask, dst_surface->format->Amask);
164
165                SDL_FillRect(temp, 0, mapped);
166                SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, color.alpha);
167                SDL_BlitSurface(temp, 0, dst_surface, &rect);
168                SDL_FreeSurface(temp);
169             }
170          }
171
172          Backend::Window *Renderer::create_window(const Area &size, const Area &logical_size, bool fullscreen)
173          {
174             return new Window(size, logical_size, fullscreen);
175          }
176
177          Backend::Texture *Renderer::create_texture(const Surface &surface)
178          {
179             return new Texture(surface);
180          }
181       }
182    }
183 }