Initial integration, lots of broken stuff
[supertux.git] / src / unison / src / video / sdl / Window.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 "Window.hpp"
7 #include "Texture.hpp"
8 #include <unison/video/Window.hpp>
9 #include <unison/video/Surface.hpp>
10 #include <unison/video/Texture.hpp>
11 #include <unison/video/Renderers.hpp>
12 #include <unison/video/sdl/Blitters.hpp>
13 #include <unison/video/backend/Renderer.hpp>
14 #include <unison/video/backend/Texture.hpp>
15
16 #include <functional>
17 #include <assert.h>
18
19 #include "SDL.h"
20
21 namespace Unison
22 {
23    namespace Video
24    {
25       namespace SDL
26       {
27          Window::Window(const Area &size, const Area &logical_size, bool fullscreen) :
28             scale_numerator(1),
29             scale_denominator(1),
30             offset(),
31             window(0)
32          {
33             assert(size.x);
34             assert(size.y);
35             unsigned int xratio = size.x * logical_size.y;
36             unsigned int yratio = size.y * logical_size.x;
37             if(xratio < yratio)
38             {
39                scale_numerator = size.x;
40                scale_denominator = logical_size.x;
41             }
42             else
43             {
44                scale_numerator = size.y;
45                scale_denominator = logical_size.y;
46             }
47             offset = (size - logical_size * scale_numerator / scale_denominator) / 2;
48             window = SDL_SetVideoMode(size.x, size.y, 0, SDL_ANYFORMAT | SDL_SWSURFACE | (fullscreen ? SDL_FULLSCREEN : 0));
49             assert(window);
50             Uint32 black = SDL_MapRGB(window->format, 0, 0, 0);
51             SDL_FillRect(window, 0, black);
52          }
53
54          Window::~Window()
55          {
56          }
57
58          void Window::take_screenshot(const std::string &filename) const
59          {
60             assert(window);
61             SDL_SaveBMP(window, filename.c_str());
62          }
63
64          void Window::flip()
65          {
66             assert(window);
67             SDL_Flip(window);
68          }
69
70          void Window::set_title(const std::string &title)
71          {
72             SDL_WM_SetCaption(title.c_str(), title.c_str());
73          }
74
75          void Window::set_icon(const Surface &icon)
76          {
77             SDL_Surface *icon_surface = Blitters::create_sdl_surface_from(icon);
78             assert(icon_surface);
79             SDL_WM_SetIcon(icon_surface, 0);
80             SDL_FreeSurface(icon_surface);
81          }
82
83          Area Window::get_size() const
84          {
85             return Area(window->w, window->h);
86          }
87
88          bool Window::is_fullscreen() const
89          {
90             return window->flags & SDL_FULLSCREEN;
91          }
92
93          void Window::blit(const Surface &src, const Point &dst_pos, const Rect &src_rect, const RenderOptions &options)
94          {
95             assert(src.get_pixels());
96             assert(window);
97
98             Surface fragment;
99             if(src_rect.pos == Point() && (src_rect.size == Area() || src_rect.size == src.get_size()))
100             {
101                fragment = src;
102             }
103             else
104             {
105                fragment = Surface(src_rect.size);
106                Video::Blitters::blit_blend_none(src, src_rect, fragment, Point());
107             }
108             fragment = fragment.scale(scale_numerator, scale_denominator);
109             if(options.h_flip)
110             {
111                fragment = fragment.h_flip();
112             }
113             if(options.v_flip)
114             {
115                fragment = fragment.v_flip();
116             }
117             SDL_Surface *src_surface = Blitters::create_sdl_surface_from(fragment.modulate(options.color).modulate(options.alpha));
118             assert(src_surface);
119
120             Point scaled_dst_pos(dst_pos);
121             scaled_dst_pos *= scale_numerator;
122             scaled_dst_pos /= scale_denominator;
123             scaled_dst_pos += offset;
124
125             Blitters::blit_blend(src_surface, Rect(Point(), fragment.get_size()), window, scaled_dst_pos, options.blend);
126
127             SDL_FreeSurface(src_surface);
128          }
129
130          void Window::blit(const Video::Texture &src, const Point &dst_pos, const Rect &src_rect, const RenderOptions &options)
131          {
132             Texture *texture = dynamic_cast<Texture *>(Backend::Texture::get_texture(src.get_id()));
133             assert(texture);
134             assert(window);
135
136             Rect scaled_src_rect(src_rect);
137             /*if(options.h_flip)
138             {
139                scaled_src_rect.pos.x = src.get_size().x - src_rect.pos.x - src_rect.size.x;
140             }
141             if(options.v_flip)
142             {
143                scaled_src_rect.pos.y = src.get_size().y - src_rect.pos.y - src_rect.size.y;
144             }*/
145             if(dst_pos.x < 0)
146             {
147                if(scaled_src_rect.size.x < (unsigned int) -dst_pos.x)
148                {
149                   return;
150                }
151                scaled_src_rect.pos.x += -dst_pos.x;
152                scaled_src_rect.size.x += dst_pos.x;
153             }
154             if(dst_pos.y < 0)
155             {
156                if(scaled_src_rect.size.y < (unsigned int) -dst_pos.y)
157                {
158                   return;
159                }
160                scaled_src_rect.pos.y += -dst_pos.y;
161                scaled_src_rect.size.y += dst_pos.y;
162             }
163             scaled_src_rect.pos *= scale_numerator;
164             scaled_src_rect.pos /= scale_denominator;
165             scaled_src_rect.size *= scale_numerator;
166             scaled_src_rect.size /= scale_denominator;
167
168             Point scaled_dst_pos(dst_pos);
169             if(dst_pos.x < 0)
170             {
171                scaled_dst_pos.x = 0;
172             }
173             if(dst_pos.y < 0)
174             {
175                scaled_dst_pos.y = 0;
176             }
177             scaled_dst_pos *= scale_numerator;
178             scaled_dst_pos /= scale_denominator;
179             scaled_dst_pos += offset;
180
181             Blitters::blit_blend(texture->get_transform(options, scale_numerator, scale_denominator), scaled_src_rect, window, scaled_dst_pos, options.blend);
182          }
183
184          void Window::fill(const Color &color, const Rect &rect)
185          {
186             assert(window);
187
188             Uint32 mapped = SDL_MapRGBA(window->format, color.red, color.green, color.blue, color.alpha);
189
190             Rect scaled_rect(rect);
191             scaled_rect.pos *= scale_numerator;
192             scaled_rect.pos /= scale_denominator;
193             scaled_rect.size *= scale_numerator;
194             scaled_rect.size /= scale_denominator;
195             scaled_rect.pos += offset;
196
197             SDL_FillRect(window, &scaled_rect, mapped);
198          }
199
200          void Window::fill_blend(const Color &color, const Rect &rect)
201          {
202             assert(window);
203
204             Uint32 mapped = SDL_MapRGB(window->format, color.red, color.green, color.blue);
205
206             Rect scaled_rect(rect);
207             scaled_rect.pos *= scale_numerator;
208             scaled_rect.pos /= scale_denominator;
209             scaled_rect.size *= scale_numerator;
210             scaled_rect.size /= scale_denominator;
211             scaled_rect.pos += offset;
212
213             if(color.alpha == 0xff)
214             {
215                SDL_FillRect(window, &scaled_rect, mapped);
216             }
217             else if(color.alpha != 0x00)
218             {
219                SDL_Surface *temp = SDL_CreateRGBSurface(window->flags, scaled_rect.size.x, scaled_rect.size.y, window->format->BitsPerPixel, window->format->Rmask, window->format->Gmask, window->format->Bmask, window->format->Amask);
220
221                SDL_FillRect(temp, 0, mapped);
222                SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, color.alpha);
223                SDL_BlitSurface(temp, 0, window, &scaled_rect);
224                SDL_FreeSurface(temp);
225             }
226          }
227       }
228    }
229 }