2 // Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
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.
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.
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/>.
17 #include "video/sdl/sdl_painter.hpp"
21 #include "video/drawing_request.hpp"
22 #include "video/sdl/sdl_texture.hpp"
25 SDLPainter::draw_surface(SDL_Renderer* renderer, const DrawingRequest& request)
27 //FIXME: support parameters request.angle, request.blend
28 const Surface* surface = (const Surface*) request.request_data;
29 boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
32 dst_rect.x = request.pos.x;
33 dst_rect.y = request.pos.y;
34 dst_rect.w = sdltexture->get_image_width();
35 dst_rect.h = sdltexture->get_image_height();
37 Uint8 r = static_cast<Uint8>(request.color.red * 255);
38 Uint8 g = static_cast<Uint8>(request.color.green * 255);
39 Uint8 b = static_cast<Uint8>(request.color.blue * 255);
40 Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
41 SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
42 SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
44 if (surface->get_flipx())
46 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
50 switch(request.drawing_effect)
53 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
57 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
62 SDL_RenderCopy(renderer, sdltexture->get_texture(), NULL, &dst_rect);
69 SDLPainter::draw_surface_part(SDL_Renderer* renderer, const DrawingRequest& request)
71 //FIXME: support parameters request.angle, request.blend
72 const SurfacePartRequest* surface = (const SurfacePartRequest*) request.request_data;
73 const SurfacePartRequest* surfacepartrequest = (SurfacePartRequest*) request.request_data;
75 boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->surface->get_texture());
78 src_rect.x = surfacepartrequest->source.x;
79 src_rect.y = surfacepartrequest->source.y;
80 src_rect.w = surfacepartrequest->size.x;
81 src_rect.h = surfacepartrequest->size.y;
84 dst_rect.x = request.pos.x;
85 dst_rect.y = request.pos.y;
86 dst_rect.w = surfacepartrequest->size.x;
87 dst_rect.h = surfacepartrequest->size.y;
89 Uint8 r = static_cast<Uint8>(request.color.red * 255);
90 Uint8 g = static_cast<Uint8>(request.color.green * 255);
91 Uint8 b = static_cast<Uint8>(request.color.blue * 255);
92 Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
93 SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
94 SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
96 if (surface->surface->get_flipx())
98 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
102 switch(request.drawing_effect)
105 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
108 case HORIZONTAL_FLIP:
109 SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
114 SDL_RenderCopy(renderer, sdltexture->get_texture(), &src_rect, &dst_rect);
121 SDLPainter::draw_gradient(SDL_Renderer* renderer, const DrawingRequest& request)
123 const GradientRequest* gradientrequest
124 = (GradientRequest*) request.request_data;
125 const Color& top = gradientrequest->top;
126 const Color& bottom = gradientrequest->bottom;
129 SDL_RenderGetViewport(renderer, &viewport);
131 // calculate the maximum number of steps needed for the gradient
132 int n = static_cast<int>(std::max(std::max(fabsf(top.red - bottom.red),
133 fabsf(top.green - bottom.green)),
134 std::max(fabsf(top.blue - bottom.blue),
135 fabsf(top.alpha - bottom.alpha))) * 255);
136 for(int i = 0; i < n; ++i)
140 rect.y = viewport.h * i / n;
142 rect.h = (viewport.h * (i+1) / n) - rect.y;
144 float p = static_cast<float>(i+1) / static_cast<float>(n);
145 Uint8 r = static_cast<Uint8>(((1.0f - p) * top.red + p * bottom.red) * 255);
146 Uint8 g = static_cast<Uint8>(((1.0f - p) * top.green + p * bottom.green) * 255);
147 Uint8 b = static_cast<Uint8>(((1.0f - p) * top.blue + p * bottom.blue) * 255);
148 Uint8 a = static_cast<Uint8>(((1.0f - p) * top.alpha + p * bottom.alpha) * 255);
150 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
151 SDL_SetRenderDrawColor(renderer, r, g, b, a);
152 SDL_RenderFillRect(renderer, &rect);
157 SDLPainter::draw_filled_rect(SDL_Renderer* renderer, const DrawingRequest& request)
159 const FillRectRequest* fillrectrequest
160 = (FillRectRequest*) request.request_data;
163 rect.x = request.pos.x;
164 rect.y = request.pos.y;
165 rect.w = fillrectrequest->size.x;
166 rect.h = fillrectrequest->size.y;
168 Uint8 r = static_cast<Uint8>(fillrectrequest->color.red * 255);
169 Uint8 g = static_cast<Uint8>(fillrectrequest->color.green * 255);
170 Uint8 b = static_cast<Uint8>(fillrectrequest->color.blue * 255);
171 Uint8 a = static_cast<Uint8>(fillrectrequest->color.alpha * 255);
173 int radius = std::min(std::min(rect.h / 2, rect.w / 2),
174 static_cast<int>(fillrectrequest->radius));
180 // rounded top and bottom parts
181 std::vector<SDL_Rect> rects;
182 rects.reserve(2*slices + 1);
183 for(int i = 0; i < slices; ++i)
185 float p = (static_cast<float>(i) + 0.5f) / static_cast<float>(slices);
186 int xoff = radius - static_cast<int>(sqrtf(1.0f - p*p) * radius);
189 tmp.x = rect.x + xoff;
190 tmp.y = rect.y + (radius - i);
191 tmp.w = rect.w - 2*(xoff);
193 rects.push_back(tmp);
196 tmp2.x = rect.x + xoff;
197 tmp2.y = rect.y + rect.h - radius + i;
198 tmp2.w = rect.w - 2*xoff;
203 rects.push_back(tmp2);
207 if (2*radius < rect.h)
212 tmp.y = rect.y + radius + 1;
214 tmp.h = rect.h - 2*radius - 1;
215 rects.push_back(tmp);
218 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
219 SDL_SetRenderDrawColor(renderer, r, g, b, a);
220 SDL_RenderFillRects(renderer, &*rects.begin(), rects.size());
224 if((rect.w != 0) && (rect.h != 0))
226 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
227 SDL_SetRenderDrawColor(renderer, r, g, b, a);
228 SDL_RenderFillRect(renderer, &rect);
234 SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& request)
236 const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data;
239 SDL_RenderGetViewport(renderer, &viewport);
241 float x = request.pos.x;
242 float w = ellipse->size.x;
243 float h = ellipse->size.y;
245 int top = request.pos.y - (h / 2);
247 const int max_slices = 256;
248 SDL_Rect rects[2*max_slices+2];
249 int slices = std::min(static_cast<int>(ellipse->size.y), max_slices);
250 for(int i = 0; i < slices; ++i)
252 float p = ((static_cast<float>(i) + 0.5f) / static_cast<float>(slices)) * 2.0f - 1.0f;
253 int xoff = static_cast<int>(sqrtf(1.0f - p*p) * w / 2);
255 SDL_Rect& left = rects[2*i+0];
256 SDL_Rect& right = rects[2*i+1];
259 left.y = top + (i * h / slices);
261 left.h = (top + ((i+1) * h / slices)) - left.y;
265 right.w = viewport.w - right.x;
269 SDL_Rect& top_rect = rects[2*slices+0];
270 SDL_Rect& bottom_rect = rects[2*slices+1];
274 top_rect.w = viewport.w;
278 bottom_rect.y = top + h;
279 bottom_rect.w = viewport.w;
280 bottom_rect.h = viewport.h - bottom_rect.y;
282 Uint8 r = static_cast<Uint8>(ellipse->color.red * 255);
283 Uint8 g = static_cast<Uint8>(ellipse->color.green * 255);
284 Uint8 b = static_cast<Uint8>(ellipse->color.blue * 255);
285 Uint8 a = static_cast<Uint8>(ellipse->color.alpha * 255);
287 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
288 SDL_SetRenderDrawColor(renderer, r, g, b, a);
289 SDL_RenderFillRects(renderer, rects, 2*slices+2);