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