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