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