src/render/software/SDL_draw.h
author Sam Lantinga <slouken@libsdl.org>
Mon, 25 May 2020 14:10:51 -0700
changeset 13847 a8f431812db7
parent 13422 fd6a12de91c7
permissions -rw-r--r--
Fixed creating a metal renderer without specifying a metal window
     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: */