This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_blendline.c
348 lines (315 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
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"
24
#include "SDL_draw.h"
25
26
27
static int
SDL_BlendLine_RGB555(SDL_Surface * dst, int x1, int y1, int x2, int y2,
28
29
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
30
31
{
unsigned inva = 0xff - a;
32
33
34
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
35
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB555, draw_end);
36
37
break;
case SDL_BLENDMODE_ADD:
38
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB555, draw_end);
39
40
break;
case SDL_BLENDMODE_MOD:
41
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB555, draw_end);
42
43
break;
default:
44
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB555, draw_end);
45
46
47
48
49
50
51
break;
}
return 0;
}
static int
SDL_BlendLine_RGB565(SDL_Surface * dst, int x1, int y1, int x2, int y2,
52
53
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
54
{
55
56
57
58
unsigned inva = 0xff - a;
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
59
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB565, draw_end);
60
61
break;
case SDL_BLENDMODE_ADD:
62
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB565, draw_end);
63
64
break;
case SDL_BLENDMODE_MOD:
65
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB565, draw_end);
66
67
break;
default:
68
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB565, draw_end);
69
break;
70
}
71
72
return 0;
}
73
74
75
static int
SDL_BlendLine_RGB888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
76
77
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
78
79
{
unsigned inva = 0xff - a;
80
81
82
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
83
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB888, draw_end);
84
85
break;
case SDL_BLENDMODE_ADD:
86
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB888, draw_end);
87
88
break;
case SDL_BLENDMODE_MOD:
89
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB888, draw_end);
90
91
break;
default:
92
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB888, draw_end);
93
break;
94
}
95
96
97
return 0;
}
98
99
static int
SDL_BlendLine_ARGB8888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
100
101
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
102
103
104
105
106
{
unsigned inva = 0xff - a;
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
107
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_ARGB8888, draw_end);
108
109
break;
case SDL_BLENDMODE_ADD:
110
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_ARGB8888, draw_end);
111
112
break;
case SDL_BLENDMODE_MOD:
113
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_ARGB8888, draw_end);
114
115
break;
default:
116
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ARGB8888, draw_end);
117
118
119
120
121
break;
}
return 0;
}
122
123
static int
SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,
124
125
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
126
127
128
129
130
131
{
SDL_PixelFormat *fmt = dst->format;
unsigned inva = 0xff - a;
switch (fmt->BytesPerPixel) {
case 2:
132
133
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
134
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_BLEND_RGB, draw_end);
135
136
break;
case SDL_BLENDMODE_ADD:
137
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_ADD_RGB, draw_end);
138
139
break;
case SDL_BLENDMODE_MOD:
140
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_MOD_RGB, draw_end);
141
142
break;
default:
143
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_RGB, draw_end);
144
145
break;
}
146
147
return 0;
case 4:
148
149
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
150
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGB, draw_end);
151
152
break;
case SDL_BLENDMODE_ADD:
153
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGB, draw_end);
154
155
break;
case SDL_BLENDMODE_MOD:
156
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGB, draw_end);
157
158
break;
default:
159
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGB, draw_end);
160
161
break;
}
162
163
164
165
166
167
168
169
170
return 0;
default:
SDL_Unsupported();
return -1;
}
}
static int
SDL_BlendLine_RGBA(SDL_Surface * dst, int x1, int y1, int x2, int y2,
171
172
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end)
173
174
175
176
177
178
{
SDL_PixelFormat *fmt = dst->format;
unsigned inva = 0xff - a;
switch (fmt->BytesPerPixel) {
case 4:
179
180
switch (blendMode) {
case SDL_BLENDMODE_BLEND:
181
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGBA, draw_end);
182
183
break;
case SDL_BLENDMODE_ADD:
184
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGBA, draw_end);
185
186
break;
case SDL_BLENDMODE_MOD:
187
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGBA, draw_end);
188
189
break;
default:
190
DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGBA, draw_end);
191
192
break;
}
193
return 0;
194
195
196
197
default:
SDL_Unsupported();
return -1;
}
198
199
200
201
202
203
204
205
206
207
208
209
210
}
int
SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
/* This function doesn't work on surfaces < 8 bpp */
if (dst->format->BitsPerPixel < 8) {
SDL_SetError("SDL_BlendLine(): Unsupported surface format");
return (-1);
}
/* Perform clipping */
211
if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
212
213
214
return (0);
}
215
216
if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
217
218
219
220
221
r = DRAW_MUL(r, a);
g = DRAW_MUL(g, a);
b = DRAW_MUL(b, a);
}
222
switch (dst->format->BitsPerPixel) {
223
case 15:
224
switch (dst->format->Rmask) {
225
226
case 0x7C00:
return SDL_BlendLine_RGB555(dst, x1, y1, x2, y2, blendMode, r, g,
227
b, a, SDL_TRUE);
228
229
230
}
break;
case 16:
231
switch (dst->format->Rmask) {
232
233
case 0xF800:
return SDL_BlendLine_RGB565(dst, x1, y1, x2, y2, blendMode, r, g,
234
b, a, SDL_TRUE);
235
236
237
}
break;
case 32:
238
switch (dst->format->Rmask) {
239
case 0x00FF0000:
240
if (!dst->format->Amask) {
241
return SDL_BlendLine_RGB888(dst, x1, y1, x2, y2, blendMode, r,
242
g, b, a, SDL_TRUE);
243
244
} else {
return SDL_BlendLine_ARGB8888(dst, x1, y1, x2, y2, blendMode,
245
r, g, b, a, SDL_TRUE);
246
247
248
}
break;
}
249
break;
250
251
252
253
default:
break;
}
254
if (!dst->format->Amask) {
255
256
return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode,
r, g, b, a, SDL_TRUE);
257
} else {
258
259
return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode,
r, g, b, a, SDL_TRUE);
260
}
261
262
}
263
264
265
266
267
268
269
270
int
SDL_BlendLines(SDL_Surface * dst, const SDL_Point * points, int count,
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
int i;
int x1, y1;
int x2, y2;
int (*func)(SDL_Surface * dst, int x1, int y1, int x2, int y2,
271
272
int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
SDL_bool draw_end) = NULL;
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
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_BlendLines(): 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_BlendLine_RGB555;
}
break;
case 16:
switch (dst->format->Rmask) {
case 0xF800:
func = SDL_BlendLine_RGB565;
}
break;
case 32:
switch (dst->format->Rmask) {
case 0x00FF0000:
if (!dst->format->Amask) {
func = SDL_BlendLine_RGB888;
} else {
func = SDL_BlendLine_ARGB8888;
}
break;
}
default:
break;
}
if (!func) {
if (!dst->format->Amask) {
func = SDL_BlendLine_RGB;
} else {
func = SDL_BlendLine_RGBA;
}
}
for (i = 1; i < count; ++i) {
x1 = points[i-1].x;
y1 = points[i-1].y;
x2 = points[i].x;
y2 = points[i].y;
/* Perform clipping */
/* FIXME: We don't actually want to clip, as it may change line slope */
if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
continue;
}
340
341
342
343
status = func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, SDL_FALSE);
}
if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
SDL_BlendPoint(dst, points[count-1].x, points[count-1].y, r, g, b, a);
344
345
346
347
}
return status;
}
348
/* vi: set ts=4 sw=4 expandtab: */