cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_drawline.c (6483B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 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#if !SDL_RENDER_DISABLED
     24
     25#include "SDL_draw.h"
     26#include "SDL_drawline.h"
     27#include "SDL_drawpoint.h"
     28
     29
     30static void
     31SDL_DrawLine1(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
     32              SDL_bool draw_end)
     33{
     34    if (y1 == y2) {
     35        int length;
     36        int pitch = (dst->pitch / dst->format->BytesPerPixel);
     37        Uint8 *pixel;
     38        if (x1 <= x2) {
     39            pixel = (Uint8 *)dst->pixels + y1 * pitch + x1;
     40            length = draw_end ? (x2-x1+1) : (x2-x1);
     41        } else {
     42            pixel = (Uint8 *)dst->pixels + y1 * pitch + x2;
     43            if (!draw_end) {
     44                ++pixel;
     45            }
     46            length = draw_end ? (x1-x2+1) : (x1-x2);
     47        }
     48        SDL_memset(pixel, color, length);
     49    } else if (x1 == x2) {
     50        VLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
     51    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
     52        DLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
     53    } else {
     54        BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end);
     55    }
     56}
     57
     58static void
     59SDL_DrawLine2(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
     60              SDL_bool draw_end)
     61{
     62    if (y1 == y2) {
     63        HLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
     64    } else if (x1 == x2) {
     65        VLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
     66    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
     67        DLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
     68    } else {
     69        Uint8 _r, _g, _b, _a;
     70        const SDL_PixelFormat * fmt = dst->format;
     71        SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
     72        if (fmt->Rmask == 0x7C00) {
     73            AALINE(x1, y1, x2, y2,
     74                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB555,
     75                   draw_end);
     76        } else if (fmt->Rmask == 0xF800) {
     77            AALINE(x1, y1, x2, y2,
     78                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565,
     79                   draw_end);
     80        } else {
     81            AALINE(x1, y1, x2, y2,
     82                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY2_BLEND_RGB,
     83                   draw_end);
     84        }
     85    }
     86}
     87
     88static void
     89SDL_DrawLine4(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
     90              SDL_bool draw_end)
     91{
     92    if (y1 == y2) {
     93        HLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
     94    } else if (x1 == x2) {
     95        VLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
     96    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
     97        DLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
     98    } else {
     99        Uint8 _r, _g, _b, _a;
    100        const SDL_PixelFormat * fmt = dst->format;
    101        SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
    102        if (fmt->Rmask == 0x00FF0000) {
    103            if (!fmt->Amask) {
    104                AALINE(x1, y1, x2, y2,
    105                       DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_RGB888,
    106                       draw_end);
    107            } else {
    108                AALINE(x1, y1, x2, y2,
    109                       DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888,
    110                       draw_end);
    111            }
    112        } else {
    113            AALINE(x1, y1, x2, y2,
    114                   DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY4_BLEND_RGB,
    115                   draw_end);
    116        }
    117    }
    118}
    119
    120typedef void (*DrawLineFunc) (SDL_Surface * dst,
    121                              int x1, int y1, int x2, int y2,
    122                              Uint32 color, SDL_bool draw_end);
    123
    124static DrawLineFunc
    125SDL_CalculateDrawLineFunc(const SDL_PixelFormat * fmt)
    126{
    127    switch (fmt->BytesPerPixel) {
    128    case 1:
    129        if (fmt->BitsPerPixel < 8) {
    130            break;
    131        }
    132        return SDL_DrawLine1;
    133    case 2:
    134        return SDL_DrawLine2;
    135    case 4:
    136        return SDL_DrawLine4;
    137    }
    138    return NULL;
    139}
    140
    141int
    142SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
    143{
    144    DrawLineFunc func;
    145
    146    if (!dst) {
    147        return SDL_SetError("SDL_DrawLine(): Passed NULL destination surface");
    148    }
    149
    150    func = SDL_CalculateDrawLineFunc(dst->format);
    151    if (!func) {
    152        return SDL_SetError("SDL_DrawLine(): Unsupported surface format");
    153    }
    154
    155    /* Perform clipping */
    156    /* FIXME: We don't actually want to clip, as it may change line slope */
    157    if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
    158        return 0;
    159    }
    160
    161    func(dst, x1, y1, x2, y2, color, SDL_TRUE);
    162    return 0;
    163}
    164
    165int
    166SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
    167              Uint32 color)
    168{
    169    int i;
    170    int x1, y1;
    171    int x2, y2;
    172    SDL_bool draw_end;
    173    DrawLineFunc func;
    174
    175    if (!dst) {
    176        return SDL_SetError("SDL_DrawLines(): Passed NULL destination surface");
    177    }
    178
    179    func = SDL_CalculateDrawLineFunc(dst->format);
    180    if (!func) {
    181        return SDL_SetError("SDL_DrawLines(): Unsupported surface format");
    182    }
    183
    184    for (i = 1; i < count; ++i) {
    185        x1 = points[i-1].x;
    186        y1 = points[i-1].y;
    187        x2 = points[i].x;
    188        y2 = points[i].y;
    189
    190        /* Perform clipping */
    191        /* FIXME: We don't actually want to clip, as it may change line slope */
    192        if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
    193            continue;
    194        }
    195
    196        /* Draw the end if it was clipped */
    197        draw_end = (x2 != points[i].x || y2 != points[i].y);
    198
    199        func(dst, x1, y1, x2, y2, color, draw_end);
    200    }
    201    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
    202        SDL_DrawPoint(dst, points[count-1].x, points[count-1].y, color);
    203    }
    204    return 0;
    205}
    206
    207#endif /* !SDL_RENDER_DISABLED */
    208
    209/* vi: set ts=4 sw=4 expandtab: */