1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#include "../../video/SDL_surface_c.h"
24
25/* This code assumes that r, g, b, a are the source color,
26 * and in the blend and add case, the RGB values are premultiplied by a.
27 */
28
29#define DRAW_MUL(_a, _b) (((unsigned)(_a) * (_b)) / 255)
30
31#define DRAW_FASTSETPIXEL(type) \
32 *pixel = (type)color
33
34#define DRAW_FASTSETPIXEL1 DRAW_FASTSETPIXEL(Uint8)
35#define DRAW_FASTSETPIXEL2 DRAW_FASTSETPIXEL(Uint16)
36#define DRAW_FASTSETPIXEL4 DRAW_FASTSETPIXEL(Uint32)
37
38#define DRAW_FASTSETPIXELXY(x, y, type, bpp, color) \
39 *(type *)((Uint8 *)dst->pixels + (y)*dst->pitch + (x)*bpp) = (type)color
40
41#define DRAW_FASTSETPIXELXY1(x, y) DRAW_FASTSETPIXELXY(x, y, Uint8, 1, color)
42#define DRAW_FASTSETPIXELXY2(x, y) DRAW_FASTSETPIXELXY(x, y, Uint16, 2, color)
43#define DRAW_FASTSETPIXELXY4(x, y) DRAW_FASTSETPIXELXY(x, y, Uint32, 4, color)
44
45#define DRAW_SETPIXEL(setpixel) \
46 do { \
47 unsigned sr = r, sg = g, sb = b, sa = a; \
48 (void)sa; \
49 setpixel; \
50 } while (0)
51
52#define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
53 do { \
54 unsigned sr, sg, sb, sa = 0xFF; \
55 getpixel; \
56 sr = DRAW_MUL(inva, sr) + r; \
57 sg = DRAW_MUL(inva, sg) + g; \
58 sb = DRAW_MUL(inva, sb) + b; \
59 sa = DRAW_MUL(inva, sa) + a; \
60 setpixel; \
61 } while (0)
62
63#define DRAW_SETPIXEL_BLEND_CLAMPED(getpixel, setpixel) \
64 do { \
65 unsigned sr, sg, sb, sa = 0xFF; \
66 getpixel; \
67 sr = DRAW_MUL(inva, sr) + r; \
68 if (sr > 0xff) \
69 sr = 0xff; \
70 sg = DRAW_MUL(inva, sg) + g; \
71 if (sg > 0xff) \
72 sg = 0xff; \
73 sb = DRAW_MUL(inva, sb) + b; \
74 if (sb > 0xff) \
75 sb = 0xff; \
76 sa = DRAW_MUL(inva, sa) + a; \
77 if (sa > 0xff) \
78 sa = 0xff; \
79 setpixel; \
80 } while (0)
81
82#define DRAW_SETPIXEL_ADD(getpixel, setpixel) \
83 do { \
84 unsigned sr, sg, sb, sa; \
85 (void)sa; \
86 getpixel; \
87 sr += r; \
88 if (sr > 0xff) \
89 sr = 0xff; \
90 sg += g; \
91 if (sg > 0xff) \
92 sg = 0xff; \
93 sb += b; \
94 if (sb > 0xff) \
95 sb = 0xff; \
96 setpixel; \
97 } while (0)
98
99#define DRAW_SETPIXEL_MOD(getpixel, setpixel) \
100 do { \
101 unsigned sr, sg, sb, sa; \
102 (void)sa; \
103 getpixel; \
104 sr = DRAW_MUL(sr, r); \
105 sg = DRAW_MUL(sg, g); \
106 sb = DRAW_MUL(sb, b); \
107 setpixel; \
108 } while (0)
109
110#define DRAW_SETPIXEL_MUL(getpixel, setpixel) \
111 do { \
112 unsigned sr, sg, sb, sa; \
113 (void)sa; \
114 getpixel; \
115 sr = DRAW_MUL(sr, r) + DRAW_MUL(inva, sr); \
116 if (sr > 0xff) \
117 sr = 0xff; \
118 sg = DRAW_MUL(sg, g) + DRAW_MUL(inva, sg); \
119 if (sg > 0xff) \
120 sg = 0xff; \
121 sb = DRAW_MUL(sb, b) + DRAW_MUL(inva, sb); \
122 if (sb > 0xff) \
123 sb = 0xff; \
124 setpixel; \
125 } while (0)
126
127#define DRAW_SETPIXELXY(x, y, type, bpp, op) \
128 do { \
129 type *pixel = (type *)((Uint8 *)dst->pixels + (y)*dst->pitch + (x)*bpp); \
130 op; \
131 } while (0)
132
133/*
134 * Define draw operators for RGB555
135 */
136
137#define DRAW_SETPIXEL_RGB555 \
138 DRAW_SETPIXEL(RGB555_FROM_RGB(*pixel, sr, sg, sb))
139
140#define DRAW_SETPIXEL_BLEND_RGB555 \
141 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
142 RGB555_FROM_RGB(*pixel, sr, sg, sb))
143
144#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB555 \
145 DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
146 RGB555_FROM_RGB(*pixel, sr, sg, sb))
147
148#define DRAW_SETPIXEL_ADD_RGB555 \
149 DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
150 RGB555_FROM_RGB(*pixel, sr, sg, sb))
151
152#define DRAW_SETPIXEL_MOD_RGB555 \
153 DRAW_SETPIXEL_MOD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
154 RGB555_FROM_RGB(*pixel, sr, sg, sb))
155
156#define DRAW_SETPIXEL_MUL_RGB555 \
157 DRAW_SETPIXEL_MUL(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
158 RGB555_FROM_RGB(*pixel, sr, sg, sb))
159
160#define DRAW_SETPIXELXY_RGB555(x, y) \
161 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB555)
162
163#define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \
164 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB555)
165
166#define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555(x, y) \
167 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555)
168
169#define DRAW_SETPIXELXY_ADD_RGB555(x, y) \
170 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB555)
171
172#define DRAW_SETPIXELXY_MOD_RGB555(x, y) \
173 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB555)
174
175#define DRAW_SETPIXELXY_MUL_RGB555(x, y) \
176 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB555)
177
178/*
179 * Define draw operators for RGB565
180 */
181
182#define DRAW_SETPIXEL_RGB565 \
183 DRAW_SETPIXEL(RGB565_FROM_RGB(*pixel, sr, sg, sb))
184
185#define DRAW_SETPIXEL_BLEND_RGB565 \
186 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
187 RGB565_FROM_RGB(*pixel, sr, sg, sb))
188
189#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB565 \
190 DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
191 RGB565_FROM_RGB(*pixel, sr, sg, sb))
192
193#define DRAW_SETPIXEL_ADD_RGB565 \
194 DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
195 RGB565_FROM_RGB(*pixel, sr, sg, sb))
196
197#define DRAW_SETPIXEL_MOD_RGB565 \
198 DRAW_SETPIXEL_MOD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
199 RGB565_FROM_RGB(*pixel, sr, sg, sb))
200
201#define DRAW_SETPIXEL_MUL_RGB565 \
202 DRAW_SETPIXEL_MUL(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
203 RGB565_FROM_RGB(*pixel, sr, sg, sb))
204
205#define DRAW_SETPIXELXY_RGB565(x, y) \
206 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB565)
207
208#define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \
209 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB565)
210
211#define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565(x, y) \
212 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565)
213
214#define DRAW_SETPIXELXY_ADD_RGB565(x, y) \
215 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB565)
216
217#define DRAW_SETPIXELXY_MOD_RGB565(x, y) \
218 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB565)
219
220#define DRAW_SETPIXELXY_MUL_RGB565(x, y) \
221 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB565)
222
223/*
224 * Define draw operators for RGB888
225 */
226
227#define DRAW_SETPIXEL_XRGB8888 \
228 DRAW_SETPIXEL(XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
229
230#define DRAW_SETPIXEL_BLEND_XRGB8888 \
231 DRAW_SETPIXEL_BLEND(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
232 XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
233
234#define DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888 \
235 DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
236 XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
237
238#define DRAW_SETPIXEL_ADD_XRGB8888 \
239 DRAW_SETPIXEL_ADD(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
240 XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
241
242#define DRAW_SETPIXEL_MOD_XRGB8888 \
243 DRAW_SETPIXEL_MOD(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
244 XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
245
246#define DRAW_SETPIXEL_MUL_XRGB8888 \
247 DRAW_SETPIXEL_MUL(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
248 XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
249
250#define DRAW_SETPIXELXY_XRGB8888(x, y) \
251 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_XRGB8888)
252
253#define DRAW_SETPIXELXY_BLEND_XRGB8888(x, y) \
254 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_XRGB8888)
255
256#define DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888(x, y) \
257 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888)
258
259#define DRAW_SETPIXELXY_ADD_XRGB8888(x, y) \
260 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_XRGB8888)
261
262#define DRAW_SETPIXELXY_MOD_XRGB8888(x, y) \
263 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_XRGB8888)
264
265#define DRAW_SETPIXELXY_MUL_XRGB8888(x, y) \
266 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_XRGB8888)
267
268/*
269 * Define draw operators for ARGB8888
270 */
271
272#define DRAW_SETPIXEL_ARGB8888 \
273 DRAW_SETPIXEL(ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
274
275#define DRAW_SETPIXEL_BLEND_ARGB8888 \
276 DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
277 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
278
279#define DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888 \
280 DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
281 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
282
283#define DRAW_SETPIXEL_ADD_ARGB8888 \
284 DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
285 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
286
287#define DRAW_SETPIXEL_MOD_ARGB8888 \
288 DRAW_SETPIXEL_MOD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
289 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
290
291#define DRAW_SETPIXEL_MUL_ARGB8888 \
292 DRAW_SETPIXEL_MUL(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
293 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
294
295#define DRAW_SETPIXELXY_ARGB8888(x, y) \
296 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ARGB8888)
297
298#define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \
299 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_ARGB8888)
300
301#define DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888(x, y) \
302 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888)
303
304#define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \
305 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_ARGB8888)
306
307#define DRAW_SETPIXELXY_MOD_ARGB8888(x, y) \
308 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_ARGB8888)
309
310#define DRAW_SETPIXELXY_MUL_ARGB8888(x, y) \
311 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_ARGB8888)
312
313/*
314 * Define draw operators for general RGB
315 */
316
317#define DRAW_SETPIXEL_RGB \
318 DRAW_SETPIXEL(PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
319
320#define DRAW_SETPIXEL_BLEND_RGB \
321 DRAW_SETPIXEL_BLEND(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
322 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
323
324#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB \
325 DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
326 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
327
328#define DRAW_SETPIXEL_ADD_RGB \
329 DRAW_SETPIXEL_ADD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
330 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
331
332#define DRAW_SETPIXEL_MOD_RGB \
333 DRAW_SETPIXEL_MOD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
334 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
335
336#define DRAW_SETPIXEL_MUL_RGB \
337 DRAW_SETPIXEL_MUL(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
338 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
339
340#define DRAW_SETPIXELXY2_RGB(x, y) \
341 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB)
342
343#define DRAW_SETPIXELXY4_RGB(x, y) \
344 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB)
345
346#define DRAW_SETPIXELXY2_BLEND_RGB(x, y) \
347 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB)
348
349#define DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB(x, y) \
350 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB)
351
352#define DRAW_SETPIXELXY4_BLEND_RGB(x, y) \
353 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB)
354
355#define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB(x, y) \
356 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGB)
357
358#define DRAW_SETPIXELXY2_ADD_RGB(x, y) \
359 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB)
360
361#define DRAW_SETPIXELXY4_ADD_RGB(x, y) \
362 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB)
363
364#define DRAW_SETPIXELXY2_MOD_RGB(x, y) \
365 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB)
366
367#define DRAW_SETPIXELXY4_MOD_RGB(x, y) \
368 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGB)
369
370#define DRAW_SETPIXELXY2_MUL_RGB(x, y) \
371 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB)
372
373#define DRAW_SETPIXELXY4_MUL_RGB(x, y) \
374 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGB)
375
376/*
377 * Define draw operators for general RGBA
378 */
379
380#define DRAW_SETPIXEL_RGBA \
381 DRAW_SETPIXEL(PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
382
383#define DRAW_SETPIXEL_BLEND_RGBA \
384 DRAW_SETPIXEL_BLEND(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
385 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
386
387#define DRAW_SETPIXEL_BLEND_CLAMPED_RGBA \
388 DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
389 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
390
391#define DRAW_SETPIXEL_ADD_RGBA \
392 DRAW_SETPIXEL_ADD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
393 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
394
395#define DRAW_SETPIXEL_MOD_RGBA \
396 DRAW_SETPIXEL_MOD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
397 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
398
399#define DRAW_SETPIXEL_MUL_RGBA \
400 DRAW_SETPIXEL_MUL(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
401 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
402
403#define DRAW_SETPIXELXY4_RGBA(x, y) \
404 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGBA)
405
406#define DRAW_SETPIXELXY4_BLEND_RGBA(x, y) \
407 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGBA)
408
409#define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA(x, y) \
410 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA)
411
412#define DRAW_SETPIXELXY4_ADD_RGBA(x, y) \
413 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGBA)
414
415#define DRAW_SETPIXELXY4_MOD_RGBA(x, y) \
416 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGBA)
417
418#define DRAW_SETPIXELXY4_MUL_RGBA(x, y) \
419 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGBA)
420
421/*
422 * Define line drawing macro
423 */
424
425#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
426
427// Horizontal line
428#define HLINE(type, op, draw_end) \
429 { \
430 int length; \
431 int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \
432 type *pixel; \
433 if (x1 <= x2) { \
434 pixel = (type *)dst->pixels + y1 * pitch + x1; \
435 length = draw_end ? (x2 - x1 + 1) : (x2 - x1); \
436 } else { \
437 pixel = (type *)dst->pixels + y1 * pitch + x2; \
438 if (!draw_end) { \
439 ++pixel; \
440 } \
441 length = draw_end ? (x1 - x2 + 1) : (x1 - x2); \
442 } \
443 while (length--) { \
444 op; \
445 ++pixel; \
446 } \
447 }
448
449// Vertical line
450#define VLINE(type, op, draw_end) \
451 { \
452 int length; \
453 int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \
454 type *pixel; \
455 if (y1 <= y2) { \
456 pixel = (type *)dst->pixels + y1 * pitch + x1; \
457 length = draw_end ? (y2 - y1 + 1) : (y2 - y1); \
458 } else { \
459 pixel = (type *)dst->pixels + y2 * pitch + x1; \
460 if (!draw_end) { \
461 pixel += pitch; \
462 } \
463 length = draw_end ? (y1 - y2 + 1) : (y1 - y2); \
464 } \
465 while (length--) { \
466 op; \
467 pixel += pitch; \
468 } \
469 }
470
471// Diagonal line
472#define DLINE(type, op, draw_end) \
473 { \
474 int length; \
475 int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \
476 type *pixel; \
477 if (y1 <= y2) { \
478 pixel = (type *)dst->pixels + y1 * pitch + x1; \
479 if (x1 <= x2) { \
480 ++pitch; \
481 } else { \
482 --pitch; \
483 } \
484 length = (y2 - y1); \
485 } else { \
486 pixel = (type *)dst->pixels + y2 * pitch + x2; \
487 if (x2 <= x1) { \
488 ++pitch; \
489 } else { \
490 --pitch; \
491 } \
492 if (!draw_end) { \
493 pixel += pitch; \
494 } \
495 length = (y1 - y2); \
496 } \
497 if (draw_end) { \
498 ++length; \
499 } \
500 while (length--) { \
501 op; \
502 pixel += pitch; \
503 } \
504 }
505
506// Bresenham's line algorithm
507#define BLINE(x1, y1, x2, y2, op, draw_end) \
508 { \
509 int i, deltax, deltay, numpixels; \
510 int d, dinc1, dinc2; \
511 int x, xinc1, xinc2; \
512 int y, yinc1, yinc2; \
513 \
514 deltax = ABS(x2 - x1); \
515 deltay = ABS(y2 - y1); \
516 \
517 if (deltax >= deltay) { \
518 numpixels = deltax + 1; \
519 d = (2 * deltay) - deltax; \
520 dinc1 = deltay * 2; \
521 dinc2 = (deltay - deltax) * 2; \
522 xinc1 = 1; \
523 xinc2 = 1; \
524 yinc1 = 0; \
525 yinc2 = 1; \
526 } else { \
527 numpixels = deltay + 1; \
528 d = (2 * deltax) - deltay; \
529 dinc1 = deltax * 2; \
530 dinc2 = (deltax - deltay) * 2; \
531 xinc1 = 0; \
532 xinc2 = 1; \
533 yinc1 = 1; \
534 yinc2 = 1; \
535 } \
536 \
537 if (x1 > x2) { \
538 xinc1 = -xinc1; \
539 xinc2 = -xinc2; \
540 } \
541 if (y1 > y2) { \
542 yinc1 = -yinc1; \
543 yinc2 = -yinc2; \
544 } \
545 \
546 x = x1; \
547 y = y1; \
548 \
549 if (!draw_end) { \
550 --numpixels; \
551 } \
552 for (i = 0; i < numpixels; ++i) { \
553 op(x, y); \
554 if (d < 0) { \
555 d += dinc1; \
556 x += xinc1; \
557 y += yinc1; \
558 } else { \
559 d += dinc2; \
560 x += xinc2; \
561 y += yinc2; \
562 } \
563 } \
564 }
565
566// Xiaolin Wu's line algorithm, based on Michael Abrash's implementation
567#define WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
568 { \
569 Uint16 ErrorAdj, ErrorAcc; \
570 Uint16 ErrorAccTemp, Weighting; \
571 int DeltaX, DeltaY, Temp, XDir; \
572 unsigned r, g, b, a, inva; \
573 \
574 /* Draw the initial pixel, which is always exactly intersected by \
575 the line and so needs no weighting */ \
576 opaque_op(x1, y1); \
577 \
578 /* Draw the final pixel, which is always exactly intersected by the line \
579 and so needs no weighting */ \
580 if (draw_end) { \
581 opaque_op(x2, y2); \
582 } \
583 \
584 /* Make sure the line runs top to bottom */ \
585 if (y1 > y2) { \
586 Temp = y1; \
587 y1 = y2; \
588 y2 = Temp; \
589 Temp = x1; \
590 x1 = x2; \
591 x2 = Temp; \
592 } \
593 DeltaY = y2 - y1; \
594 \
595 if ((DeltaX = x2 - x1) >= 0) { \
596 XDir = 1; \
597 } else { \
598 XDir = -1; \
599 DeltaX = -DeltaX; /* make DeltaX positive */ \
600 } \
601 \
602 /* line is not horizontal, diagonal, or vertical */ \
603 ErrorAcc = 0; /* initialize the line error accumulator to 0 */ \
604 \
605 /* Is this an X-major or Y-major line? */ \
606 if (DeltaY > DeltaX) { \
607 /* Y-major line; calculate 16-bit fixed-point fractional part of a \
608 pixel that X advances each time Y advances 1 pixel, truncating the \
609 result so that we won't overrun the endpoint along the X axis */ \
610 ErrorAdj = ((unsigned long)DeltaX << 16) / (unsigned long)DeltaY; \
611 /* Draw all pixels other than the first and last */ \
612 while (--DeltaY) { \
613 ErrorAccTemp = ErrorAcc; /* remember current accumulated error */ \
614 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
615 if (ErrorAcc <= ErrorAccTemp) { \
616 /* The error accumulator turned over, so advance the X coord */ \
617 x1 += XDir; \
618 } \
619 y1++; /* Y-major, so always advance Y */ \
620 /* The IntensityBits most significant bits of ErrorAcc give us the \
621 intensity weighting for this pixel, and the complement of the \
622 weighting for the paired pixel */ \
623 Weighting = ErrorAcc >> 8; \
624 { \
625 a = DRAW_MUL(_a, (Weighting ^ 255)); \
626 r = DRAW_MUL(_r, a); \
627 g = DRAW_MUL(_g, a); \
628 b = DRAW_MUL(_b, a); \
629 inva = (a ^ 0xFF); \
630 blend_op(x1, y1); \
631 } \
632 { \
633 a = DRAW_MUL(_a, Weighting); \
634 r = DRAW_MUL(_r, a); \
635 g = DRAW_MUL(_g, a); \
636 b = DRAW_MUL(_b, a); \
637 inva = (a ^ 0xFF); \
638 blend_op(x1 + XDir, y1); \
639 } \
640 } \
641 } else { \
642 /* X-major line; calculate 16-bit fixed-point fractional part of a \
643 pixel that Y advances each time X advances 1 pixel, truncating the \
644 result to avoid overrunning the endpoint along the X axis */ \
645 ErrorAdj = ((unsigned long)DeltaY << 16) / (unsigned long)DeltaX; \
646 /* Draw all pixels other than the first and last */ \
647 while (--DeltaX) { \
648 ErrorAccTemp = ErrorAcc; /* remember current accumulated error */ \
649 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
650 if (ErrorAcc <= ErrorAccTemp) { \
651 /* The error accumulator turned over, so advance the Y coord */ \
652 y1++; \
653 } \
654 x1 += XDir; /* X-major, so always advance X */ \
655 /* The IntensityBits most significant bits of ErrorAcc give us the \
656 intensity weighting for this pixel, and the complement of the \
657 weighting for the paired pixel */ \
658 Weighting = ErrorAcc >> 8; \
659 { \
660 a = DRAW_MUL(_a, (Weighting ^ 255)); \
661 r = DRAW_MUL(_r, a); \
662 g = DRAW_MUL(_g, a); \
663 b = DRAW_MUL(_b, a); \
664 inva = (a ^ 0xFF); \
665 blend_op(x1, y1); \
666 } \
667 { \
668 a = DRAW_MUL(_a, Weighting); \
669 r = DRAW_MUL(_r, a); \
670 g = DRAW_MUL(_g, a); \
671 b = DRAW_MUL(_b, a); \
672 inva = (a ^ 0xFF); \
673 blend_op(x1, y1 + 1); \
674 } \
675 } \
676 } \
677 }
678
679#ifdef AA_LINES
680#define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
681 WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end)
682#else
683#define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
684 BLINE(x1, y1, x2, y2, opaque_op, draw_end)
685#endif
686
687/*
688 * Define fill rect macro
689 */
690
691#define FILLRECT(type, op) \
692 do { \
693 int width = rect->w; \
694 int height = rect->h; \
695 int pitch = (dst->pitch / dst->fmt->bytes_per_pixel); \
696 int skip = pitch - width; \
697 type *pixel = (type *)dst->pixels + rect->y * pitch + rect->x; \
698 while (height--) { \
699 { \
700 int n = (width + 3) / 4; \
701 switch (width & 3) { \
702 case 0: \
703 do { \
704 op; \
705 pixel++; \
706 SDL_FALLTHROUGH; \
707 case 3: \
708 op; \
709 pixel++; \
710 SDL_FALLTHROUGH; \
711 case 2: \
712 op; \
713 pixel++; \
714 SDL_FALLTHROUGH; \
715 case 1: \
716 op; \
717 pixel++; \
718 } while (--n > 0); \
719 } \
720 } \
721 pixel += skip; \
722 } \
723 } while (0)
724