sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_draw.h (20528B)


      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: */