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