SDL  2.0
SDL_draw.h
Go to the documentation of this file.
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: */