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