1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 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) \
47 do { \
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) \
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_ADD(getpixel, setpixel) \
64 do { \
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) \
74 do { \
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) \
84 do { \
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) \
95 do { \
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) \
612 do { \
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