comparison src/video/SDL_blendfillrect.c @ 3593:b931bcfd94a0

In the process of adding rectangle drawing
author Sam Lantinga <slouken@libsdl.org>
date Fri, 18 Dec 2009 07:03:09 +0000
parents src/video/SDL_blendrect.c@0267b8b1595c
children c8bed77b0386
comparison
equal deleted inserted replaced
3592:25dc4a86132c 3593:b931bcfd94a0
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_video.h"
25 #include "SDL_draw.h"
26
27 static int
28 SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
29 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
30 {
31 unsigned inva = 0xff - a;
32
33 switch (blendMode) {
34 case SDL_BLENDMODE_BLEND:
35 FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
36 break;
37 case SDL_BLENDMODE_ADD:
38 FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
39 break;
40 case SDL_BLENDMODE_MOD:
41 FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555);
42 break;
43 default:
44 FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
45 break;
46 }
47 return 0;
48 }
49
50 static int
51 SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
52 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
53 {
54 unsigned inva = 0xff - a;
55
56 switch (blendMode) {
57 case SDL_BLENDMODE_BLEND:
58 FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
59 break;
60 case SDL_BLENDMODE_ADD:
61 FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
62 break;
63 case SDL_BLENDMODE_MOD:
64 FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565);
65 break;
66 default:
67 FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
68 break;
69 }
70 return 0;
71 }
72
73 static int
74 SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
75 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
76 {
77 unsigned inva = 0xff - a;
78
79 switch (blendMode) {
80 case SDL_BLENDMODE_BLEND:
81 FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB888);
82 break;
83 case SDL_BLENDMODE_ADD:
84 FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB888);
85 break;
86 case SDL_BLENDMODE_MOD:
87 FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB888);
88 break;
89 default:
90 FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
91 break;
92 }
93 return 0;
94 }
95
96 static int
97 SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
98 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
99 {
100 unsigned inva = 0xff - a;
101
102 switch (blendMode) {
103 case SDL_BLENDMODE_BLEND:
104 FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
105 break;
106 case SDL_BLENDMODE_ADD:
107 FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
108 break;
109 case SDL_BLENDMODE_MOD:
110 FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888);
111 break;
112 default:
113 FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
114 break;
115 }
116 return 0;
117 }
118
119 static int
120 SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
121 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
122 {
123 SDL_PixelFormat *fmt = dst->format;
124 unsigned inva = 0xff - a;
125
126 switch (fmt->BytesPerPixel) {
127 case 2:
128 switch (blendMode) {
129 case SDL_BLENDMODE_BLEND:
130 FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
131 break;
132 case SDL_BLENDMODE_ADD:
133 FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
134 break;
135 case SDL_BLENDMODE_MOD:
136 FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB);
137 break;
138 default:
139 FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
140 break;
141 }
142 return 0;
143 case 4:
144 switch (blendMode) {
145 case SDL_BLENDMODE_BLEND:
146 FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
147 break;
148 case SDL_BLENDMODE_ADD:
149 FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
150 break;
151 case SDL_BLENDMODE_MOD:
152 FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB);
153 break;
154 default:
155 FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
156 break;
157 }
158 return 0;
159 default:
160 SDL_Unsupported();
161 return -1;
162 }
163 }
164
165 static int
166 SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
167 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
168 {
169 SDL_PixelFormat *fmt = dst->format;
170 unsigned inva = 0xff - a;
171
172 switch (fmt->BytesPerPixel) {
173 case 4:
174 switch (blendMode) {
175 case SDL_BLENDMODE_BLEND:
176 FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
177 break;
178 case SDL_BLENDMODE_ADD:
179 FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
180 break;
181 case SDL_BLENDMODE_MOD:
182 FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA);
183 break;
184 default:
185 FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
186 break;
187 }
188 return 0;
189 default:
190 SDL_Unsupported();
191 return -1;
192 }
193 }
194
195 int
196 SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
197 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
198 {
199 SDL_Rect clipped;
200
201 if (!dst) {
202 SDL_SetError("Passed NULL destination surface");
203 return -1;
204 }
205
206 if (blendMode < SDL_BLENDMODE_BLEND) {
207 Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
208 return SDL_FillRect(dst, rect, color);
209 }
210
211 /* This function doesn't work on surfaces < 8 bpp */
212 if (dst->format->BitsPerPixel < 8) {
213 SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
214 return -1;
215 }
216
217 /* If 'rect' == NULL, then fill the whole surface */
218 if (rect) {
219 /* Perform clipping */
220 if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
221 return 0;
222 }
223 rect = &clipped;
224 } else {
225 rect = &dst->clip_rect;
226 }
227
228 if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
229 r = DRAW_MUL(r, a);
230 g = DRAW_MUL(g, a);
231 b = DRAW_MUL(b, a);
232 }
233
234 switch (dst->format->BitsPerPixel) {
235 case 15:
236 switch (dst->format->Rmask) {
237 case 0x7C00:
238 return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a);
239 }
240 break;
241 case 16:
242 switch (dst->format->Rmask) {
243 case 0xF800:
244 return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a);
245 }
246 break;
247 case 32:
248 switch (dst->format->Rmask) {
249 case 0x00FF0000:
250 if (!dst->format->Amask) {
251 return SDL_BlendFillRect_RGB888(dst, rect, blendMode, r, g, b, a);
252 } else {
253 return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
254 }
255 break;
256 }
257 break;
258 default:
259 break;
260 }
261
262 if (!dst->format->Amask) {
263 return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a);
264 } else {
265 return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a);
266 }
267 }
268
269 int
270 SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
271 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
272 {
273 SDL_Rect clipped;
274 int i;
275 int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
276 int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
277 int status = 0;
278
279 if (!dst) {
280 SDL_SetError("Passed NULL destination surface");
281 return -1;
282 }
283
284 if (blendMode < SDL_BLENDMODE_BLEND) {
285 Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
286 return SDL_FillRects(dst, rects, color);
287 }
288
289 /* This function doesn't work on surfaces < 8 bpp */
290 if (dst->format->BitsPerPixel < 8) {
291 SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
292 return -1;
293 }
294
295 if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
296 r = DRAW_MUL(r, a);
297 g = DRAW_MUL(g, a);
298 b = DRAW_MUL(b, a);
299 }
300
301 /* FIXME: Does this function pointer slow things down significantly? */
302 switch (dst->format->BitsPerPixel) {
303 case 15:
304 switch (dst->format->Rmask) {
305 case 0x7C00:
306 func = SDL_BlendFillRect_RGB555;
307 }
308 break;
309 case 16:
310 switch (dst->format->Rmask) {
311 case 0xF800:
312 func = SDL_BlendFillRect_RGB565;
313 }
314 break;
315 case 32:
316 switch (dst->format->Rmask) {
317 case 0x00FF0000:
318 if (!dst->format->Amask) {
319 func = SDL_BlendFillRect_RGB888;
320 } else {
321 func = SDL_BlendFillRect_ARGB8888;
322 }
323 break;
324 }
325 break;
326 default:
327 break;
328 }
329
330 if (!func) {
331 if (!dst->format->Amask) {
332 func = SDL_BlendFillRect_RGB;
333 } else {
334 func = SDL_BlendFillRect_RGBA;
335 }
336 }
337
338 for (i = 0; i < count; ++i) {
339 const SDL_Rect * rect = rects[i];
340
341 /* If 'rect' == NULL, then fill the whole surface */
342 if (rect) {
343 /* Perform clipping */
344 if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
345 continue;
346 }
347 rect = &clipped;
348 } else {
349 rect = &dst->clip_rect;
350 }
351
352 status = func(dst, rect, blendMode, r, g, b, a);
353 }
354 return status;
355 }
356
357 /* vi: set ts=4 sw=4 expandtab: */