src/render/software/SDL_drawline.c
author Sam Lantinga
Tue, 08 Feb 2011 10:04:09 -0800
changeset 5226 710d00cb3a6a
parent 5166 4d39eeaad00b
child 5262 b530ef003506
permissions -rw-r--r--
Made it possible to disable the rendering subsystem with configure --disable-render
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #if !SDL_RENDER_DISABLED
    25 
    26 #include "SDL_draw.h"
    27 #include "SDL_drawline.h"
    28 #include "SDL_drawpoint.h"
    29 
    30 
    31 static void
    32 SDL_DrawLine1(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
    33               SDL_bool draw_end)
    34 {
    35     if (y1 == y2) {
    36         //HLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
    37         int length;
    38         int pitch = (dst->pitch / dst->format->BytesPerPixel);
    39         Uint8 *pixel;
    40         if (x1 <= x2) {
    41             pixel = (Uint8 *)dst->pixels + y1 * pitch + x1;
    42             length = draw_end ? (x2-x1+1) : (x2-x1);
    43         } else {
    44             pixel = (Uint8 *)dst->pixels + y1 * pitch + x2;
    45             if (!draw_end) {
    46                 ++pixel;
    47             }
    48             length = draw_end ? (x1-x2+1) : (x1-x2);
    49         }
    50         SDL_memset(pixel, color, length);
    51     } else if (x1 == x2) {
    52         VLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
    53     } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
    54         DLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
    55     } else {
    56         BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end);
    57     }
    58 }
    59 
    60 static void
    61 SDL_DrawLine2(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
    62               SDL_bool draw_end)
    63 {
    64     if (y1 == y2) {
    65         HLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
    66     } else if (x1 == x2) {
    67         VLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
    68     } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
    69         DLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
    70     } else {
    71         Uint8 _r, _g, _b, _a;
    72         const SDL_PixelFormat * fmt = dst->format;
    73         SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
    74         if (fmt->Rmask == 0x7C00) {
    75             AALINE(x1, y1, x2, y2,
    76                    DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB555,
    77                    draw_end);
    78         } else if (fmt->Rmask == 0xF800) {
    79             AALINE(x1, y1, x2, y2,
    80                    DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565,
    81                    draw_end);
    82         } else {
    83             AALINE(x1, y1, x2, y2,
    84                    DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY2_BLEND_RGB,
    85                    draw_end);
    86         }
    87     }
    88 }
    89 
    90 static void
    91 SDL_DrawLine4(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
    92               SDL_bool draw_end)
    93 {
    94     if (y1 == y2) {
    95         HLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
    96     } else if (x1 == x2) {
    97         VLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
    98     } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
    99         DLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
   100     } else {
   101         Uint8 _r, _g, _b, _a;
   102         const SDL_PixelFormat * fmt = dst->format;
   103         SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
   104         if (fmt->Rmask == 0x00FF0000) {
   105             if (!fmt->Amask) {
   106                 AALINE(x1, y1, x2, y2,
   107                        DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_RGB888,
   108                        draw_end);
   109             } else {
   110                 AALINE(x1, y1, x2, y2,
   111                        DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888,
   112                        draw_end);
   113             }
   114         } else {
   115             AALINE(x1, y1, x2, y2,
   116                    DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY4_BLEND_RGB,
   117                    draw_end);
   118         }
   119     }
   120 }
   121 
   122 typedef void (*DrawLineFunc) (SDL_Surface * dst,
   123                               int x1, int y1, int x2, int y2,
   124                               Uint32 color, SDL_bool draw_end);
   125 
   126 static DrawLineFunc
   127 SDL_CalculateDrawLineFunc(const SDL_PixelFormat * fmt)
   128 {
   129     switch (fmt->BytesPerPixel) {
   130     case 1:
   131         if (fmt->BitsPerPixel < 8) {
   132             break;
   133         }
   134         return SDL_DrawLine1;
   135     case 2:
   136         return SDL_DrawLine2;
   137     case 4:
   138         return SDL_DrawLine4;
   139     }
   140     return NULL;
   141 }
   142 
   143 int
   144 SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
   145 {
   146     DrawLineFunc func;
   147 
   148     if (!dst) {
   149         SDL_SetError("SDL_DrawLine(): Passed NULL destination surface");
   150         return -1;
   151     }
   152 
   153     func = SDL_CalculateDrawLineFunc(dst->format);
   154     if (!func) {
   155         SDL_SetError("SDL_DrawLine(): Unsupported surface format");
   156         return -1;
   157     }
   158 
   159     /* Perform clipping */
   160     /* FIXME: We don't actually want to clip, as it may change line slope */
   161     if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
   162         return 0;
   163     }
   164 
   165     func(dst, x1, y1, x2, y2, color, SDL_TRUE);
   166     return 0;
   167 }
   168 
   169 int
   170 SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
   171               Uint32 color)
   172 {
   173     int i;
   174     int x1, y1;
   175     int x2, y2;
   176     SDL_bool draw_end;
   177     DrawLineFunc func;
   178 
   179     if (!dst) {
   180         SDL_SetError("SDL_DrawLines(): Passed NULL destination surface");
   181         return -1;
   182     }
   183 
   184     func = SDL_CalculateDrawLineFunc(dst->format);
   185     if (!func) {
   186         SDL_SetError("SDL_DrawLines(): Unsupported surface format");
   187         return -1;
   188     }
   189 
   190     for (i = 1; i < count; ++i) {
   191         x1 = points[i-1].x;
   192         y1 = points[i-1].y;
   193         x2 = points[i].x;
   194         y2 = points[i].y;
   195 
   196         /* Perform clipping */
   197         /* FIXME: We don't actually want to clip, as it may change line slope */
   198         if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
   199             continue;
   200         }
   201 
   202         /* Draw the end if it was clipped */
   203         draw_end = (x2 != points[i].x || y2 != points[i].y);
   204 
   205         func(dst, x1, y1, x2, y2, color, draw_end);
   206     }
   207     if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
   208         SDL_DrawPoint(dst, points[count-1].x, points[count-1].y, color);
   209     }
   210     return 0;
   211 }
   212 
   213 #endif /* !SDL_RENDER_DISABLED */
   214 
   215 /* vi: set ts=4 sw=4 expandtab: */