src/video/SDL_blendline.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 18 Dec 2009 07:41:59 +0000
changeset 3594 c8bed77b0386
parent 3536 0267b8b1595c
child 3596 f638ded38b8a
permissions -rw-r--r--
Added SDL_DrawRect(), SDL_DrawRects(), SDL_BlendRect() and SDL_BlendRects()
Fixed line drawing so when blending a sequence of lines there are no overlapping pixels drawn.
slouken@2888
     1
/*
slouken@2888
     2
    SDL - Simple DirectMedia Layer
slouken@2888
     3
    Copyright (C) 1997-2009 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@2898
    25
slouken@2898
    26
static int
slouken@2898
    27
SDL_BlendLine_RGB555(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
    28
                     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
    29
                     SDL_bool draw_end)
slouken@2898
    30
{
slouken@2898
    31
    unsigned inva = 0xff - a;
slouken@2888
    32
slouken@2898
    33
    switch (blendMode) {
slouken@2898
    34
    case SDL_BLENDMODE_BLEND:
slouken@3594
    35
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB555, draw_end);
slouken@2898
    36
        break;
slouken@2898
    37
    case SDL_BLENDMODE_ADD:
slouken@3594
    38
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB555, draw_end);
slouken@2898
    39
        break;
slouken@2898
    40
    case SDL_BLENDMODE_MOD:
slouken@3594
    41
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB555, draw_end);
slouken@2898
    42
        break;
slouken@2898
    43
    default:
slouken@3594
    44
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB555, draw_end);
slouken@2898
    45
        break;
slouken@2898
    46
    }
slouken@2898
    47
    return 0;
slouken@2898
    48
}
slouken@2896
    49
slouken@2898
    50
static int
slouken@2898
    51
SDL_BlendLine_RGB565(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
    52
                     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
    53
                     SDL_bool draw_end)
slouken@2898
    54
{
slouken@2898
    55
    unsigned inva = 0xff - a;
slouken@2896
    56
slouken@2898
    57
    switch (blendMode) {
slouken@2898
    58
    case SDL_BLENDMODE_BLEND:
slouken@3594
    59
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB565, draw_end);
slouken@2898
    60
        break;
slouken@2898
    61
    case SDL_BLENDMODE_ADD:
slouken@3594
    62
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB565, draw_end);
slouken@2898
    63
        break;
slouken@2898
    64
    case SDL_BLENDMODE_MOD:
slouken@3594
    65
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB565, draw_end);
slouken@2898
    66
        break;
slouken@2898
    67
    default:
slouken@3594
    68
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB565, draw_end);
slouken@2898
    69
        break;
slouken@2898
    70
    }
slouken@2898
    71
    return 0;
slouken@2898
    72
}
slouken@2898
    73
slouken@2898
    74
static int
slouken@2898
    75
SDL_BlendLine_RGB888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
    76
                     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
    77
                     SDL_bool draw_end)
slouken@2898
    78
{
slouken@2898
    79
    unsigned inva = 0xff - a;
slouken@2898
    80
slouken@2898
    81
    switch (blendMode) {
slouken@2898
    82
    case SDL_BLENDMODE_BLEND:
slouken@3594
    83
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_RGB888, draw_end);
slouken@2898
    84
        break;
slouken@2898
    85
    case SDL_BLENDMODE_ADD:
slouken@3594
    86
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_RGB888, draw_end);
slouken@2898
    87
        break;
slouken@2898
    88
    case SDL_BLENDMODE_MOD:
slouken@3594
    89
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_RGB888, draw_end);
slouken@2898
    90
        break;
slouken@2898
    91
    default:
slouken@3594
    92
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_RGB888, draw_end);
slouken@2898
    93
        break;
slouken@2898
    94
    }
slouken@2898
    95
    return 0;
slouken@2896
    96
}
slouken@2896
    97
slouken@2898
    98
static int
slouken@2899
    99
SDL_BlendLine_ARGB8888(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
   100
                       int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
   101
                       SDL_bool draw_end)
slouken@2899
   102
{
slouken@2899
   103
    unsigned inva = 0xff - a;
slouken@2899
   104
slouken@2899
   105
    switch (blendMode) {
slouken@2899
   106
    case SDL_BLENDMODE_BLEND:
slouken@3594
   107
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_BLEND_ARGB8888, draw_end);
slouken@2899
   108
        break;
slouken@2899
   109
    case SDL_BLENDMODE_ADD:
slouken@3594
   110
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ADD_ARGB8888, draw_end);
slouken@2899
   111
        break;
slouken@2899
   112
    case SDL_BLENDMODE_MOD:
slouken@3594
   113
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_MOD_ARGB8888, draw_end);
slouken@2899
   114
        break;
slouken@2899
   115
    default:
slouken@3594
   116
        DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY_ARGB8888, draw_end);
slouken@2899
   117
        break;
slouken@2899
   118
    }
slouken@2899
   119
    return 0;
slouken@2899
   120
}
slouken@2899
   121
slouken@2899
   122
static int
slouken@2898
   123
SDL_BlendLine_RGB(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
   124
                  int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
   125
                  SDL_bool draw_end)
slouken@2898
   126
{
slouken@2898
   127
    SDL_PixelFormat *fmt = dst->format;
slouken@2898
   128
    unsigned inva = 0xff - a;
slouken@2896
   129
slouken@2898
   130
    switch (fmt->BytesPerPixel) {
slouken@2898
   131
    case 2:
slouken@2898
   132
        switch (blendMode) {
slouken@2898
   133
        case SDL_BLENDMODE_BLEND:
slouken@3594
   134
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_BLEND_RGB, draw_end);
slouken@2898
   135
            break;
slouken@2898
   136
        case SDL_BLENDMODE_ADD:
slouken@3594
   137
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_ADD_RGB, draw_end);
slouken@2898
   138
            break;
slouken@2898
   139
        case SDL_BLENDMODE_MOD:
slouken@3594
   140
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_MOD_RGB, draw_end);
slouken@2898
   141
            break;
slouken@2898
   142
        default:
slouken@3594
   143
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY2_RGB, draw_end);
slouken@2898
   144
            break;
slouken@2898
   145
        }
slouken@2898
   146
        return 0;
slouken@2898
   147
    case 4:
slouken@2898
   148
        switch (blendMode) {
slouken@2898
   149
        case SDL_BLENDMODE_BLEND:
slouken@3594
   150
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGB, draw_end);
slouken@2898
   151
            break;
slouken@2898
   152
        case SDL_BLENDMODE_ADD:
slouken@3594
   153
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGB, draw_end);
slouken@2898
   154
            break;
slouken@2898
   155
        case SDL_BLENDMODE_MOD:
slouken@3594
   156
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGB, draw_end);
slouken@2898
   157
            break;
slouken@2898
   158
        default:
slouken@3594
   159
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGB, draw_end);
slouken@2898
   160
            break;
slouken@2898
   161
        }
slouken@2898
   162
        return 0;
slouken@2898
   163
    default:
slouken@2898
   164
        SDL_Unsupported();
slouken@2898
   165
        return -1;
slouken@2898
   166
    }
slouken@2898
   167
}
slouken@2896
   168
slouken@2898
   169
static int
slouken@2898
   170
SDL_BlendLine_RGBA(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
   171
                   int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
   172
                   SDL_bool draw_end)
slouken@2898
   173
{
slouken@2898
   174
    SDL_PixelFormat *fmt = dst->format;
slouken@2898
   175
    unsigned inva = 0xff - a;
slouken@2896
   176
slouken@2898
   177
    switch (fmt->BytesPerPixel) {
slouken@2898
   178
    case 4:
slouken@2898
   179
        switch (blendMode) {
slouken@2898
   180
        case SDL_BLENDMODE_BLEND:
slouken@3594
   181
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_BLEND_RGBA, draw_end);
slouken@2898
   182
            break;
slouken@2898
   183
        case SDL_BLENDMODE_ADD:
slouken@3594
   184
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_ADD_RGBA, draw_end);
slouken@2898
   185
            break;
slouken@2898
   186
        case SDL_BLENDMODE_MOD:
slouken@3594
   187
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_MOD_RGBA, draw_end);
slouken@2898
   188
            break;
slouken@2898
   189
        default:
slouken@3594
   190
            DRAWLINE(x1, y1, x2, y2, DRAW_SETPIXELXY4_RGBA, draw_end);
slouken@2898
   191
            break;
slouken@2898
   192
        }
slouken@2898
   193
        return 0;
slouken@2898
   194
    default:
slouken@2898
   195
        SDL_Unsupported();
slouken@2898
   196
        return -1;
slouken@2898
   197
    }
slouken@2898
   198
}
slouken@2888
   199
slouken@2888
   200
int
slouken@2888
   201
SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@2888
   202
              int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2888
   203
{
slouken@2888
   204
    /* This function doesn't work on surfaces < 8 bpp */
slouken@2888
   205
    if (dst->format->BitsPerPixel < 8) {
slouken@2888
   206
        SDL_SetError("SDL_BlendLine(): Unsupported surface format");
slouken@2888
   207
        return (-1);
slouken@2888
   208
    }
slouken@2888
   209
slouken@2888
   210
    /* Perform clipping */
slouken@2910
   211
    if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
slouken@2909
   212
        return (0);
slouken@2909
   213
    }
slouken@2909
   214
slouken@2888
   215
slouken@3536
   216
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@2898
   217
        r = DRAW_MUL(r, a);
slouken@2898
   218
        g = DRAW_MUL(g, a);
slouken@2898
   219
        b = DRAW_MUL(b, a);
slouken@2896
   220
    }
slouken@2898
   221
slouken@3536
   222
    switch (dst->format->BitsPerPixel) {
slouken@2896
   223
    case 15:
slouken@3536
   224
        switch (dst->format->Rmask) {
slouken@2898
   225
        case 0x7C00:
slouken@2898
   226
            return SDL_BlendLine_RGB555(dst, x1, y1, x2, y2, blendMode, r, g,
slouken@3594
   227
                                        b, a, SDL_TRUE);
slouken@2896
   228
        }
slouken@2896
   229
        break;
slouken@2896
   230
    case 16:
slouken@3536
   231
        switch (dst->format->Rmask) {
slouken@2898
   232
        case 0xF800:
slouken@2898
   233
            return SDL_BlendLine_RGB565(dst, x1, y1, x2, y2, blendMode, r, g,
slouken@3594
   234
                                        b, a, SDL_TRUE);
slouken@2896
   235
        }
slouken@2896
   236
        break;
slouken@2896
   237
    case 32:
slouken@3536
   238
        switch (dst->format->Rmask) {
slouken@2898
   239
        case 0x00FF0000:
slouken@3536
   240
            if (!dst->format->Amask) {
slouken@2898
   241
                return SDL_BlendLine_RGB888(dst, x1, y1, x2, y2, blendMode, r,
slouken@3594
   242
                                            g, b, a, SDL_TRUE);
slouken@2899
   243
            } else {
slouken@2899
   244
                return SDL_BlendLine_ARGB8888(dst, x1, y1, x2, y2, blendMode,
slouken@3594
   245
                                              r, g, b, a, SDL_TRUE);
slouken@2898
   246
            }
slouken@2896
   247
            break;
slouken@2896
   248
        }
slouken@3536
   249
        break;
slouken@2898
   250
    default:
slouken@2896
   251
        break;
slouken@2896
   252
    }
slouken@2898
   253
slouken@3536
   254
    if (!dst->format->Amask) {
slouken@3594
   255
        return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode,
slouken@3594
   256
                                 r, g, b, a, SDL_TRUE);
slouken@2898
   257
    } else {
slouken@3594
   258
        return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode,
slouken@3594
   259
                                  r, g, b, a, SDL_TRUE);
slouken@2898
   260
    }
slouken@2888
   261
}
slouken@2888
   262
slouken@3536
   263
int
slouken@3536
   264
SDL_BlendLines(SDL_Surface * dst, const SDL_Point * points, int count,
slouken@3536
   265
               int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@3536
   266
{
slouken@3536
   267
    int i;
slouken@3536
   268
    int x1, y1;
slouken@3536
   269
    int x2, y2;
slouken@3536
   270
    int (*func)(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@3594
   271
                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
slouken@3594
   272
                SDL_bool draw_end) = NULL;
slouken@3536
   273
    int status = 0;
slouken@3536
   274
slouken@3536
   275
    if (!dst) {
slouken@3536
   276
        SDL_SetError("Passed NULL destination surface");
slouken@3536
   277
        return -1;
slouken@3536
   278
    }
slouken@3536
   279
slouken@3536
   280
    /* This function doesn't work on surfaces < 8 bpp */
slouken@3536
   281
    if (dst->format->BitsPerPixel < 8) {
slouken@3536
   282
        SDL_SetError("SDL_BlendLines(): Unsupported surface format");
slouken@3536
   283
        return -1;
slouken@3536
   284
    }
slouken@3536
   285
slouken@3536
   286
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@3536
   287
        r = DRAW_MUL(r, a);
slouken@3536
   288
        g = DRAW_MUL(g, a);
slouken@3536
   289
        b = DRAW_MUL(b, a);
slouken@3536
   290
    }
slouken@3536
   291
slouken@3536
   292
    /* FIXME: Does this function pointer slow things down significantly? */
slouken@3536
   293
    switch (dst->format->BitsPerPixel) {
slouken@3536
   294
    case 15:
slouken@3536
   295
        switch (dst->format->Rmask) {
slouken@3536
   296
        case 0x7C00:
slouken@3536
   297
            func = SDL_BlendLine_RGB555;
slouken@3536
   298
        }
slouken@3536
   299
        break;
slouken@3536
   300
    case 16:
slouken@3536
   301
        switch (dst->format->Rmask) {
slouken@3536
   302
        case 0xF800:
slouken@3536
   303
            func = SDL_BlendLine_RGB565;
slouken@3536
   304
        }
slouken@3536
   305
        break;
slouken@3536
   306
    case 32:
slouken@3536
   307
        switch (dst->format->Rmask) {
slouken@3536
   308
        case 0x00FF0000:
slouken@3536
   309
            if (!dst->format->Amask) {
slouken@3536
   310
                func = SDL_BlendLine_RGB888;
slouken@3536
   311
            } else {
slouken@3536
   312
                func = SDL_BlendLine_ARGB8888;
slouken@3536
   313
            }
slouken@3536
   314
            break;
slouken@3536
   315
        }
slouken@3536
   316
    default:
slouken@3536
   317
        break;
slouken@3536
   318
    }
slouken@3536
   319
slouken@3536
   320
    if (!func) {
slouken@3536
   321
        if (!dst->format->Amask) {
slouken@3536
   322
            func = SDL_BlendLine_RGB;
slouken@3536
   323
        } else {
slouken@3536
   324
            func = SDL_BlendLine_RGBA;
slouken@3536
   325
        }
slouken@3536
   326
    }
slouken@3536
   327
slouken@3536
   328
    for (i = 1; i < count; ++i) {
slouken@3536
   329
        x1 = points[i-1].x;
slouken@3536
   330
        y1 = points[i-1].y;
slouken@3536
   331
        x2 = points[i].x;
slouken@3536
   332
        y2 = points[i].y;
slouken@3536
   333
slouken@3536
   334
        /* Perform clipping */
slouken@3536
   335
        /* FIXME: We don't actually want to clip, as it may change line slope */
slouken@3536
   336
        if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
slouken@3536
   337
            continue;
slouken@3536
   338
        }
slouken@3536
   339
slouken@3594
   340
        status = func(dst, x1, y1, x2, y2, blendMode, r, g, b, a, SDL_FALSE);
slouken@3594
   341
    }
slouken@3594
   342
    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@3594
   343
        SDL_BlendPoint(dst, points[count-1].x, points[count-1].y, r, g, b, a);
slouken@3536
   344
    }
slouken@3536
   345
    return status;
slouken@3536
   346
}
slouken@3536
   347
slouken@2888
   348
/* vi: set ts=4 sw=4 expandtab: */