1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 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_blit.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 \
40 + (x) * bpp) = (type) color
41
42#define DRAW_FASTSETPIXELXY1(x, y) DRAW_FASTSETPIXELXY(x, y, Uint8, 1, color)
43#define DRAW_FASTSETPIXELXY2(x, y) DRAW_FASTSETPIXELXY(x, y, Uint16, 2, color)
44#define DRAW_FASTSETPIXELXY4(x, y) DRAW_FASTSETPIXELXY(x, y, Uint32, 4, color)
45
46#define DRAW_SETPIXEL(setpixel) \
47do { \
48 unsigned sr = r, sg = g, sb = b, sa = a; (void) sa; \
49 setpixel; \
50} while (0)
51
52#define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
53do { \
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_ADD(getpixel, setpixel) \
64do { \
65 unsigned sr, sg, sb, sa; (void) sa; \
66 getpixel; \
67 sr += r; if (sr > 0xff) sr = 0xff; \
68 sg += g; if (sg > 0xff) sg = 0xff; \
69 sb += b; if (sb > 0xff) sb = 0xff; \
70 setpixel; \
71} while (0)
72
73#define DRAW_SETPIXEL_MOD(getpixel, setpixel) \
74do { \
75 unsigned sr, sg, sb, sa; (void) sa; \
76 getpixel; \
77 sr = DRAW_MUL(sr, r); \
78 sg = DRAW_MUL(sg, g); \
79 sb = DRAW_MUL(sb, b); \
80 setpixel; \
81} while (0)
82
83#define DRAW_SETPIXEL_MUL(getpixel, setpixel) \
84do { \
85 unsigned sr, sg, sb, sa; sa = 0xFF; \
86 getpixel; \
87 sr = DRAW_MUL(sr, r) + DRAW_MUL(inva, sr); if (sr > 0xff) sr = 0xff; \
88 sg = DRAW_MUL(sg, g) + DRAW_MUL(inva, sg); if (sg > 0xff) sg = 0xff; \
89 sb = DRAW_MUL(sb, b) + DRAW_MUL(inva, sb); if (sb > 0xff) sb = 0xff; \
90 sa = DRAW_MUL(sa, a) + DRAW_MUL(inva, sa); if (sa > 0xff) sa = 0xff; \
91 setpixel; \
92} while (0)
93
94#define DRAW_SETPIXELXY(x, y, type, bpp, op) \
95do { \
96 type *pixel = (type *)((Uint8 *)dst->pixels + (y) * dst->pitch \
97 + (x) * bpp); \
98 op; \
99} while (0)
100
101/*
102 * Define draw operators for RGB555
103 */
104
105#define DRAW_SETPIXEL_RGB555 \
106 DRAW_SETPIXEL(RGB555_FROM_RGB(*pixel, sr, sg, sb))
107
108#define DRAW_SETPIXEL_BLEND_RGB555 \
109 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
110 RGB555_FROM_RGB(*pixel, sr, sg, sb))
111
112#define DRAW_SETPIXEL_ADD_RGB555 \
113 DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
114 RGB555_FROM_RGB(*pixel, sr, sg, sb))
115
116#define DRAW_SETPIXEL_MOD_RGB555 \
117 DRAW_SETPIXEL_MOD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
118 RGB555_FROM_RGB(*pixel, sr, sg, sb))
119
120#define DRAW_SETPIXEL_MUL_RGB555 \
121 DRAW_SETPIXEL_MUL(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
122 RGB555_FROM_RGB(*pixel, sr, sg, sb))
123
124#define DRAW_SETPIXELXY_RGB555(x, y) \
125 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB555)
126
127#define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \
128 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB555)
129
130#define DRAW_SETPIXELXY_ADD_RGB555(x, y) \
131 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB555)
132
133#define DRAW_SETPIXELXY_MOD_RGB555(x, y) \
134 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB555)
135
136#define DRAW_SETPIXELXY_MUL_RGB555(x, y) \
137 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB555)
138
139/*
140 * Define draw operators for RGB565
141 */
142
143#define DRAW_SETPIXEL_RGB565 \
144 DRAW_SETPIXEL(RGB565_FROM_RGB(*pixel, sr, sg, sb))
145
146#define DRAW_SETPIXEL_BLEND_RGB565 \
147 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
148 RGB565_FROM_RGB(*pixel, sr, sg, sb))
149
150#define DRAW_SETPIXEL_ADD_RGB565 \
151 DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
152 RGB565_FROM_RGB(*pixel, sr, sg, sb))
153
154#define DRAW_SETPIXEL_MOD_RGB565 \
155 DRAW_SETPIXEL_MOD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
156 RGB565_FROM_RGB(*pixel, sr, sg, sb))
157
158#define DRAW_SETPIXEL_MUL_RGB565 \
159 DRAW_SETPIXEL_MUL(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
160 RGB565_FROM_RGB(*pixel, sr, sg, sb))
161
162#define DRAW_SETPIXELXY_RGB565(x, y) \
163 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB565)
164
165#define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \
166 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB565)
167
168#define DRAW_SETPIXELXY_ADD_RGB565(x, y) \
169 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB565)
170
171#define DRAW_SETPIXELXY_MOD_RGB565(x, y) \
172 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB565)
173
174#define DRAW_SETPIXELXY_MUL_RGB565(x, y) \
175 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB565)
176
177/*
178 * Define draw operators for RGB888
179 */
180
181#define DRAW_SETPIXEL_RGB888 \
182 DRAW_SETPIXEL(RGB888_FROM_RGB(*pixel, sr, sg, sb))
183
184#define DRAW_SETPIXEL_BLEND_RGB888 \
185 DRAW_SETPIXEL_BLEND(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
186 RGB888_FROM_RGB(*pixel, sr, sg, sb))
187
188#define DRAW_SETPIXEL_ADD_RGB888 \
189 DRAW_SETPIXEL_ADD(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
190 RGB888_FROM_RGB(*pixel, sr, sg, sb))
191
192#define DRAW_SETPIXEL_MOD_RGB888 \
193 DRAW_SETPIXEL_MOD(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
194 RGB888_FROM_RGB(*pixel, sr, sg, sb))
195
196#define DRAW_SETPIXEL_MUL_RGB888 \
197 DRAW_SETPIXEL_MUL(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
198 RGB888_FROM_RGB(*pixel, sr, sg, sb))
199
200#define DRAW_SETPIXELXY_RGB888(x, y) \
201 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB888)
202
203#define DRAW_SETPIXELXY_BLEND_RGB888(x, y) \
204 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB888)
205
206#define DRAW_SETPIXELXY_ADD_RGB888(x, y) \
207 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB888)
208
209#define DRAW_SETPIXELXY_MOD_RGB888(x, y) \
210 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGB888)
211
212#define DRAW_SETPIXELXY_MUL_RGB888(x, y) \
213 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGB888)
214
215/*
216 * Define draw operators for ARGB8888
217 */
218
219#define DRAW_SETPIXEL_ARGB8888 \
220 DRAW_SETPIXEL(ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
221
222#define DRAW_SETPIXEL_BLEND_ARGB8888 \
223 DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
224 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
225
226#define DRAW_SETPIXEL_ADD_ARGB8888 \
227 DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
228 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
229
230#define DRAW_SETPIXEL_MOD_ARGB8888 \
231 DRAW_SETPIXEL_MOD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
232 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
233
234#define DRAW_SETPIXEL_MUL_ARGB8888 \
235 DRAW_SETPIXEL_MUL(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
236 ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
237
238#define DRAW_SETPIXELXY_ARGB8888(x, y) \
239 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ARGB8888)
240
241#define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \
242 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_ARGB8888)
243
244#define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \
245 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_ARGB8888)
246
247#define DRAW_SETPIXELXY_MOD_ARGB8888(x, y) \
248 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_ARGB8888)
249
250#define DRAW_SETPIXELXY_MUL_ARGB8888(x, y) \
251 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_ARGB8888)
252
253/*
254 * Define draw operators for general RGB
255 */
256
257#define DRAW_SETPIXEL_RGB \
258 DRAW_SETPIXEL(PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
259
260#define DRAW_SETPIXEL_BLEND_RGB \
261 DRAW_SETPIXEL_BLEND(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
262 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
263
264#define DRAW_SETPIXEL_ADD_RGB \
265 DRAW_SETPIXEL_ADD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
266 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
267
268#define DRAW_SETPIXEL_MOD_RGB \
269 DRAW_SETPIXEL_MOD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
270 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
271
272#define DRAW_SETPIXEL_MUL_RGB \
273 DRAW_SETPIXEL_MUL(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
274 PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
275
276#define DRAW_SETPIXELXY2_RGB(x, y) \
277 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_RGB)
278
279#define DRAW_SETPIXELXY4_RGB(x, y) \
280 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGB)
281
282#define DRAW_SETPIXELXY2_BLEND_RGB(x, y) \
283 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB)
284
285#define DRAW_SETPIXELXY4_BLEND_RGB(x, y) \
286 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB)
287
288#define DRAW_SETPIXELXY2_ADD_RGB(x, y) \
289 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB)
290
291#define DRAW_SETPIXELXY4_ADD_RGB(x, y) \
292 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGB)
293
294#define DRAW_SETPIXELXY2_MOD_RGB(x, y) \
295 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MOD_RGB)
296
297#define DRAW_SETPIXELXY4_MOD_RGB(x, y) \
298 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGB)
299
300#define DRAW_SETPIXELXY2_MUL_RGB(x, y) \
301 DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_MUL_RGB)
302
303#define DRAW_SETPIXELXY4_MUL_RGB(x, y) \
304 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGB)
305
306
307/*
308 * Define draw operators for general RGBA
309 */
310
311#define DRAW_SETPIXEL_RGBA \
312 DRAW_SETPIXEL(PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
313
314#define DRAW_SETPIXEL_BLEND_RGBA \
315 DRAW_SETPIXEL_BLEND(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
316 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
317
318#define DRAW_SETPIXEL_ADD_RGBA \
319 DRAW_SETPIXEL_ADD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
320 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
321
322#define DRAW_SETPIXEL_MOD_RGBA \
323 DRAW_SETPIXEL_MOD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
324 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
325
326#define DRAW_SETPIXEL_MUL_RGBA \
327 DRAW_SETPIXEL_MUL(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
328 PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
329
330#define DRAW_SETPIXELXY4_RGBA(x, y) \
331 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_RGBA)
332
333#define DRAW_SETPIXELXY4_BLEND_RGBA(x, y) \
334 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGBA)
335
336#define DRAW_SETPIXELXY4_ADD_RGBA(x, y) \
337 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGBA)
338
339#define DRAW_SETPIXELXY4_MOD_RGBA(x, y) \
340 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MOD_RGBA)
341
342#define DRAW_SETPIXELXY4_MUL_RGBA(x, y) \
343 DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_MUL_RGBA)
344
345/*
346 * Define line drawing macro
347 */
348
349#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
350
351/* Horizontal line */
352#define HLINE(type, op, draw_end) \
353{ \
354 int length; \
355 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
356 type *pixel; \
357 if (x1 <= x2) { \
358 pixel = (type *)dst->pixels + y1 * pitch + x1; \
359 length = draw_end ? (x2-x1+1) : (x2-x1); \
360 } else { \
361 pixel = (type *)dst->pixels + y1 * pitch + x2; \
362 if (!draw_end) { \
363 ++pixel; \
364 } \
365 length = draw_end ? (x1-x2+1) : (x1-x2); \
366 } \
367 while (length--) { \
368 op; \
369 ++pixel; \
370 } \
371}
372
373/* Vertical line */
374#define VLINE(type, op, draw_end) \
375{ \
376 int length; \
377 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
378 type *pixel; \
379 if (y1 <= y2) { \
380 pixel = (type *)dst->pixels + y1 * pitch + x1; \
381 length = draw_end ? (y2-y1+1) : (y2-y1); \
382 } else { \
383 pixel = (type *)dst->pixels + y2 * pitch + x1; \
384 if (!draw_end) { \
385 pixel += pitch; \
386 } \
387 length = draw_end ? (y1-y2+1) : (y1-y2); \
388 } \
389 while (length--) { \
390 op; \
391 pixel += pitch; \
392 } \
393}
394
395/* Diagonal line */
396#define DLINE(type, op, draw_end) \
397{ \
398 int length; \
399 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
400 type *pixel; \
401 if (y1 <= y2) { \
402 pixel = (type *)dst->pixels + y1 * pitch + x1; \
403 if (x1 <= x2) { \
404 ++pitch; \
405 } else { \
406 --pitch; \
407 } \
408 length = (y2-y1); \
409 } else { \
410 pixel = (type *)dst->pixels + y2 * pitch + x2; \
411 if (x2 <= x1) { \
412 ++pitch; \
413 } else { \
414 --pitch; \
415 } \
416 if (!draw_end) { \
417 pixel += pitch; \
418 } \
419 length = (y1-y2); \
420 } \
421 if (draw_end) { \
422 ++length; \
423 } \
424 while (length--) { \
425 op; \
426 pixel += pitch; \
427 } \
428}
429
430/* Bresenham's line algorithm */
431#define BLINE(x1, y1, x2, y2, op, draw_end) \
432{ \
433 int i, deltax, deltay, numpixels; \
434 int d, dinc1, dinc2; \
435 int x, xinc1, xinc2; \
436 int y, yinc1, yinc2; \
437 \
438 deltax = ABS(x2 - x1); \
439 deltay = ABS(y2 - y1); \
440 \
441 if (deltax >= deltay) { \
442 numpixels = deltax + 1; \
443 d = (2 * deltay) - deltax; \
444 dinc1 = deltay * 2; \
445 dinc2 = (deltay - deltax) * 2; \
446 xinc1 = 1; \
447 xinc2 = 1; \
448 yinc1 = 0; \
449 yinc2 = 1; \
450 } else { \
451 numpixels = deltay + 1; \
452 d = (2 * deltax) - deltay; \
453 dinc1 = deltax * 2; \
454 dinc2 = (deltax - deltay) * 2; \
455 xinc1 = 0; \
456 xinc2 = 1; \
457 yinc1 = 1; \
458 yinc2 = 1; \
459 } \
460 \
461 if (x1 > x2) { \
462 xinc1 = -xinc1; \
463 xinc2 = -xinc2; \
464 } \
465 if (y1 > y2) { \
466 yinc1 = -yinc1; \
467 yinc2 = -yinc2; \
468 } \
469 \
470 x = x1; \
471 y = y1; \
472 \
473 if (!draw_end) { \
474 --numpixels; \
475 } \
476 for (i = 0; i < numpixels; ++i) { \
477 op(x, y); \
478 if (d < 0) { \
479 d += dinc1; \
480 x += xinc1; \
481 y += yinc1; \
482 } else { \
483 d += dinc2; \
484 x += xinc2; \
485 y += yinc2; \
486 } \
487 } \
488}
489
490/* Xiaolin Wu's line algorithm, based on Michael Abrash's implementation */
491#define WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
492{ \
493 Uint16 ErrorAdj, ErrorAcc; \
494 Uint16 ErrorAccTemp, Weighting; \
495 int DeltaX, DeltaY, Temp, XDir; \
496 unsigned r, g, b, a, inva; \
497 \
498 /* Draw the initial pixel, which is always exactly intersected by \
499 the line and so needs no weighting */ \
500 opaque_op(x1, y1); \
501 \
502 /* Draw the final pixel, which is always exactly intersected by the line \
503 and so needs no weighting */ \
504 if (draw_end) { \
505 opaque_op(x2, y2); \
506 } \
507 \
508 /* Make sure the line runs top to bottom */ \
509 if (y1 > y2) { \
510 Temp = y1; y1 = y2; y2 = Temp; \
511 Temp = x1; x1 = x2; x2 = Temp; \
512 } \
513 DeltaY = y2 - y1; \
514 \
515 if ((DeltaX = x2 - x1) >= 0) { \
516 XDir = 1; \
517 } else { \
518 XDir = -1; \
519 DeltaX = -DeltaX; /* make DeltaX positive */ \
520 } \
521 \
522 /* line is not horizontal, diagonal, or vertical */ \
523 ErrorAcc = 0; /* initialize the line error accumulator to 0 */ \
524 \
525 /* Is this an X-major or Y-major line? */ \
526 if (DeltaY > DeltaX) { \
527 /* Y-major line; calculate 16-bit fixed-point fractional part of a \
528 pixel that X advances each time Y advances 1 pixel, truncating the \
529 result so that we won't overrun the endpoint along the X axis */ \
530 ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY; \
531 /* Draw all pixels other than the first and last */ \
532 while (--DeltaY) { \
533 ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ \
534 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
535 if (ErrorAcc <= ErrorAccTemp) { \
536 /* The error accumulator turned over, so advance the X coord */ \
537 x1 += XDir; \
538 } \
539 y1++; /* Y-major, so always advance Y */ \
540 /* The IntensityBits most significant bits of ErrorAcc give us the \
541 intensity weighting for this pixel, and the complement of the \
542 weighting for the paired pixel */ \
543 Weighting = ErrorAcc >> 8; \
544 { \
545 a = DRAW_MUL(_a, (Weighting ^ 255)); \
546 r = DRAW_MUL(_r, a); \
547 g = DRAW_MUL(_g, a); \
548 b = DRAW_MUL(_b, a); \
549 inva = (a ^ 0xFF); \
550 blend_op(x1, y1); \
551 } \
552 { \
553 a = DRAW_MUL(_a, Weighting); \
554 r = DRAW_MUL(_r, a); \
555 g = DRAW_MUL(_g, a); \
556 b = DRAW_MUL(_b, a); \
557 inva = (a ^ 0xFF); \
558 blend_op(x1 + XDir, y1); \
559 } \
560 } \
561 } else { \
562 /* X-major line; calculate 16-bit fixed-point fractional part of a \
563 pixel that Y advances each time X advances 1 pixel, truncating the \
564 result to avoid overrunning the endpoint along the X axis */ \
565 ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX; \
566 /* Draw all pixels other than the first and last */ \
567 while (--DeltaX) { \
568 ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ \
569 ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
570 if (ErrorAcc <= ErrorAccTemp) { \
571 /* The error accumulator turned over, so advance the Y coord */ \
572 y1++; \
573 } \
574 x1 += XDir; /* X-major, so always advance X */ \
575 /* The IntensityBits most significant bits of ErrorAcc give us the \
576 intensity weighting for this pixel, and the complement of the \
577 weighting for the paired pixel */ \
578 Weighting = ErrorAcc >> 8; \
579 { \
580 a = DRAW_MUL(_a, (Weighting ^ 255)); \
581 r = DRAW_MUL(_r, a); \
582 g = DRAW_MUL(_g, a); \
583 b = DRAW_MUL(_b, a); \
584 inva = (a ^ 0xFF); \
585 blend_op(x1, y1); \
586 } \
587 { \
588 a = DRAW_MUL(_a, Weighting); \
589 r = DRAW_MUL(_r, a); \
590 g = DRAW_MUL(_g, a); \
591 b = DRAW_MUL(_b, a); \
592 inva = (a ^ 0xFF); \
593 blend_op(x1, y1 + 1); \
594 } \
595 } \
596 } \
597}
598
599#ifdef AA_LINES
600#define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
601 WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end)
602#else
603#define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
604 BLINE(x1, y1, x2, y2, opaque_op, draw_end)
605#endif
606
607/*
608 * Define fill rect macro
609 */
610
611#define FILLRECT(type, op) \
612do { \
613 int width = rect->w; \
614 int height = rect->h; \
615 int pitch = (dst->pitch / dst->format->BytesPerPixel); \
616 int skip = pitch - width; \
617 type *pixel = (type *)dst->pixels + rect->y * pitch + rect->x; \
618 while (height--) { \
619 { int n = (width+3)/4; \
620 switch (width & 3) { \
621 case 0: do { op; pixel++; /* fallthrough */ \
622 case 3: op; pixel++; /* fallthrough */ \
623 case 2: op; pixel++; /* fallthrough */ \
624 case 1: op; pixel++; /* fallthrough */ \
625 } while ( --n > 0 ); \
626 } \
627 } \
628 pixel += skip; \
629 } \
630} while (0)
631
632/* vi: set ts=4 sw=4 expandtab: */
633