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