src/video/SDL_blendfillrect.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 18 Dec 2009 07:03:09 +0000
changeset 3593 b931bcfd94a0
parent 3536 src/video/SDL_blendrect.c@0267b8b1595c
child 3594 c8bed77b0386
permissions -rw-r--r--
In the process of adding rectangle drawing
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@2888
    24
#include "SDL_video.h"
slouken@2898
    25
#include "SDL_draw.h"
slouken@2888
    26
slouken@2898
    27
static int
slouken@3593
    28
SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
    29
                         int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2898
    30
{
slouken@2898
    31
    unsigned inva = 0xff - a;
slouken@2896
    32
slouken@2898
    33
    switch (blendMode) {
slouken@2898
    34
    case SDL_BLENDMODE_BLEND:
slouken@2900
    35
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
slouken@2898
    36
        break;
slouken@2898
    37
    case SDL_BLENDMODE_ADD:
slouken@2900
    38
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
slouken@2898
    39
        break;
slouken@2898
    40
    case SDL_BLENDMODE_MOD:
slouken@2900
    41
        FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555);
slouken@2898
    42
        break;
slouken@2898
    43
    default:
slouken@2900
    44
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
slouken@2898
    45
        break;
slouken@2898
    46
    }
slouken@2898
    47
    return 0;
slouken@2898
    48
}
slouken@2896
    49
slouken@2898
    50
static int
slouken@3593
    51
SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
    52
                         int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2898
    53
{
slouken@2898
    54
    unsigned inva = 0xff - a;
slouken@2896
    55
slouken@2898
    56
    switch (blendMode) {
slouken@2898
    57
    case SDL_BLENDMODE_BLEND:
slouken@2900
    58
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
slouken@2898
    59
        break;
slouken@2898
    60
    case SDL_BLENDMODE_ADD:
slouken@2900
    61
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
slouken@2898
    62
        break;
slouken@2898
    63
    case SDL_BLENDMODE_MOD:
slouken@2900
    64
        FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565);
slouken@2898
    65
        break;
slouken@2898
    66
    default:
slouken@2900
    67
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
slouken@2898
    68
        break;
slouken@2898
    69
    }
slouken@2898
    70
    return 0;
slouken@2898
    71
}
slouken@2896
    72
slouken@2898
    73
static int
slouken@3593
    74
SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
    75
                         int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2898
    76
{
slouken@2898
    77
    unsigned inva = 0xff - a;
slouken@2896
    78
slouken@2898
    79
    switch (blendMode) {
slouken@2898
    80
    case SDL_BLENDMODE_BLEND:
slouken@2900
    81
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB888);
slouken@2898
    82
        break;
slouken@2898
    83
    case SDL_BLENDMODE_ADD:
slouken@2900
    84
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB888);
slouken@2898
    85
        break;
slouken@2898
    86
    case SDL_BLENDMODE_MOD:
slouken@2900
    87
        FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB888);
slouken@2898
    88
        break;
slouken@2898
    89
    default:
slouken@2900
    90
        FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
slouken@2898
    91
        break;
slouken@2898
    92
    }
slouken@2898
    93
    return 0;
slouken@2898
    94
}
slouken@2896
    95
slouken@2898
    96
static int
slouken@3593
    97
SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
    98
                           int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2899
    99
{
slouken@2899
   100
    unsigned inva = 0xff - a;
slouken@2899
   101
slouken@2899
   102
    switch (blendMode) {
slouken@2899
   103
    case SDL_BLENDMODE_BLEND:
slouken@2900
   104
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
slouken@2899
   105
        break;
slouken@2899
   106
    case SDL_BLENDMODE_ADD:
slouken@2900
   107
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
slouken@2899
   108
        break;
slouken@2899
   109
    case SDL_BLENDMODE_MOD:
slouken@2900
   110
        FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888);
slouken@2899
   111
        break;
slouken@2899
   112
    default:
slouken@2900
   113
        FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
slouken@2899
   114
        break;
slouken@2899
   115
    }
slouken@2899
   116
    return 0;
slouken@2899
   117
}
slouken@2899
   118
slouken@2899
   119
static int
slouken@3593
   120
SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
   121
                      int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2898
   122
{
slouken@2898
   123
    SDL_PixelFormat *fmt = dst->format;
slouken@2898
   124
    unsigned inva = 0xff - a;
slouken@2896
   125
slouken@2898
   126
    switch (fmt->BytesPerPixel) {
slouken@2898
   127
    case 2:
slouken@2898
   128
        switch (blendMode) {
slouken@2898
   129
        case SDL_BLENDMODE_BLEND:
slouken@2900
   130
            FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
slouken@2898
   131
            break;
slouken@2898
   132
        case SDL_BLENDMODE_ADD:
slouken@2900
   133
            FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
slouken@2898
   134
            break;
slouken@2898
   135
        case SDL_BLENDMODE_MOD:
slouken@2900
   136
            FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB);
slouken@2898
   137
            break;
slouken@2898
   138
        default:
slouken@2900
   139
            FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
slouken@2898
   140
            break;
slouken@2898
   141
        }
slouken@2898
   142
        return 0;
slouken@2898
   143
    case 4:
slouken@2898
   144
        switch (blendMode) {
slouken@2898
   145
        case SDL_BLENDMODE_BLEND:
slouken@2900
   146
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
slouken@2898
   147
            break;
slouken@2898
   148
        case SDL_BLENDMODE_ADD:
slouken@2900
   149
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
slouken@2898
   150
            break;
slouken@2898
   151
        case SDL_BLENDMODE_MOD:
slouken@2900
   152
            FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB);
slouken@2898
   153
            break;
slouken@2898
   154
        default:
slouken@2900
   155
            FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
slouken@2898
   156
            break;
slouken@2898
   157
        }
slouken@2898
   158
        return 0;
slouken@2898
   159
    default:
slouken@2898
   160
        SDL_Unsupported();
slouken@2898
   161
        return -1;
slouken@2898
   162
    }
slouken@2898
   163
}
slouken@2896
   164
slouken@2898
   165
static int
slouken@3593
   166
SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
   167
                       int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2898
   168
{
slouken@2898
   169
    SDL_PixelFormat *fmt = dst->format;
slouken@2898
   170
    unsigned inva = 0xff - a;
slouken@2896
   171
slouken@2898
   172
    switch (fmt->BytesPerPixel) {
slouken@2898
   173
    case 4:
slouken@2898
   174
        switch (blendMode) {
slouken@2898
   175
        case SDL_BLENDMODE_BLEND:
slouken@2900
   176
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
slouken@2898
   177
            break;
slouken@2898
   178
        case SDL_BLENDMODE_ADD:
slouken@2900
   179
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
slouken@2898
   180
            break;
slouken@2898
   181
        case SDL_BLENDMODE_MOD:
slouken@2900
   182
            FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA);
slouken@2898
   183
            break;
slouken@2898
   184
        default:
slouken@2900
   185
            FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
slouken@2898
   186
            break;
slouken@2898
   187
        }
slouken@2898
   188
        return 0;
slouken@2898
   189
    default:
slouken@2898
   190
        SDL_Unsupported();
slouken@2898
   191
        return -1;
slouken@2898
   192
    }
slouken@2898
   193
}
slouken@2888
   194
slouken@2888
   195
int
slouken@3593
   196
SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3593
   197
                  int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2888
   198
{
slouken@3536
   199
    SDL_Rect clipped;
slouken@3536
   200
slouken@3536
   201
    if (!dst) {
slouken@3536
   202
        SDL_SetError("Passed NULL destination surface");
slouken@3536
   203
        return -1;
slouken@3536
   204
    }
slouken@2898
   205
slouken@3593
   206
    if (blendMode < SDL_BLENDMODE_BLEND) {
slouken@3593
   207
        Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
slouken@3593
   208
        return SDL_FillRect(dst, rect, color);
slouken@3593
   209
    }
slouken@3593
   210
slouken@2888
   211
    /* This function doesn't work on surfaces < 8 bpp */
slouken@3536
   212
    if (dst->format->BitsPerPixel < 8) {
slouken@3593
   213
        SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
slouken@3536
   214
        return -1;
slouken@2888
   215
    }
slouken@2888
   216
slouken@3536
   217
    /* If 'rect' == NULL, then fill the whole surface */
slouken@3536
   218
    if (rect) {
slouken@2888
   219
        /* Perform clipping */
slouken@3536
   220
        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@3536
   221
            return 0;
slouken@2888
   222
        }
slouken@3536
   223
        rect = &clipped;
slouken@2888
   224
    } else {
slouken@3536
   225
        rect = &dst->clip_rect;
slouken@2888
   226
    }
slouken@2888
   227
slouken@3536
   228
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@2898
   229
        r = DRAW_MUL(r, a);
slouken@2898
   230
        g = DRAW_MUL(g, a);
slouken@2898
   231
        b = DRAW_MUL(b, a);
slouken@2896
   232
    }
slouken@2898
   233
slouken@3536
   234
    switch (dst->format->BitsPerPixel) {
slouken@2896
   235
    case 15:
slouken@3536
   236
        switch (dst->format->Rmask) {
slouken@2898
   237
        case 0x7C00:
slouken@3593
   238
            return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a);
slouken@2896
   239
        }
slouken@2896
   240
        break;
slouken@2896
   241
    case 16:
slouken@3536
   242
        switch (dst->format->Rmask) {
slouken@2898
   243
        case 0xF800:
slouken@3593
   244
            return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a);
slouken@2898
   245
        }
slouken@2898
   246
        break;
slouken@2898
   247
    case 32:
slouken@3536
   248
        switch (dst->format->Rmask) {
slouken@2898
   249
        case 0x00FF0000:
slouken@3536
   250
            if (!dst->format->Amask) {
slouken@3593
   251
                return SDL_BlendFillRect_RGB888(dst, rect, blendMode, r, g, b, a);
slouken@2899
   252
            } else {
slouken@3593
   253
                return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
slouken@2898
   254
            }
slouken@2896
   255
            break;
slouken@2896
   256
        }
slouken@3536
   257
        break;
slouken@2898
   258
    default:
slouken@2896
   259
        break;
slouken@2896
   260
    }
slouken@2898
   261
slouken@3536
   262
    if (!dst->format->Amask) {
slouken@3593
   263
        return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a);
slouken@2898
   264
    } else {
slouken@3593
   265
        return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a);
slouken@2898
   266
    }
slouken@2888
   267
}
slouken@2888
   268
slouken@3536
   269
int
slouken@3593
   270
SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
slouken@3593
   271
                   int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@3536
   272
{
slouken@3536
   273
    SDL_Rect clipped;
slouken@3536
   274
    int i;
slouken@3536
   275
    int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
slouken@3536
   276
                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
slouken@3536
   277
    int status = 0;
slouken@3536
   278
slouken@3536
   279
    if (!dst) {
slouken@3536
   280
        SDL_SetError("Passed NULL destination surface");
slouken@3536
   281
        return -1;
slouken@3536
   282
    }
slouken@3536
   283
slouken@3593
   284
    if (blendMode < SDL_BLENDMODE_BLEND) {
slouken@3593
   285
        Uint32 color = SDL_MapRGBA(dst->format, r, g, b, a);
slouken@3593
   286
        return SDL_FillRects(dst, rects, color);
slouken@3593
   287
    }
slouken@3593
   288
slouken@3536
   289
    /* This function doesn't work on surfaces < 8 bpp */
slouken@3536
   290
    if (dst->format->BitsPerPixel < 8) {
slouken@3593
   291
        SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
slouken@3536
   292
        return -1;
slouken@3536
   293
    }
slouken@3536
   294
slouken@3536
   295
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@3536
   296
        r = DRAW_MUL(r, a);
slouken@3536
   297
        g = DRAW_MUL(g, a);
slouken@3536
   298
        b = DRAW_MUL(b, a);
slouken@3536
   299
    }
slouken@3536
   300
slouken@3536
   301
    /* FIXME: Does this function pointer slow things down significantly? */
slouken@3536
   302
    switch (dst->format->BitsPerPixel) {
slouken@3536
   303
    case 15:
slouken@3536
   304
        switch (dst->format->Rmask) {
slouken@3536
   305
        case 0x7C00:
slouken@3593
   306
            func = SDL_BlendFillRect_RGB555;
slouken@3536
   307
        }
slouken@3536
   308
        break;
slouken@3536
   309
    case 16:
slouken@3536
   310
        switch (dst->format->Rmask) {
slouken@3536
   311
        case 0xF800:
slouken@3593
   312
            func = SDL_BlendFillRect_RGB565;
slouken@3536
   313
        }
slouken@3536
   314
        break;
slouken@3536
   315
    case 32:
slouken@3536
   316
        switch (dst->format->Rmask) {
slouken@3536
   317
        case 0x00FF0000:
slouken@3536
   318
            if (!dst->format->Amask) {
slouken@3593
   319
                func = SDL_BlendFillRect_RGB888;
slouken@3536
   320
            } else {
slouken@3593
   321
                func = SDL_BlendFillRect_ARGB8888;
slouken@3536
   322
            }
slouken@3536
   323
            break;
slouken@3536
   324
        }
slouken@3536
   325
        break;
slouken@3536
   326
    default:
slouken@3536
   327
        break;
slouken@3536
   328
    }
slouken@3536
   329
slouken@3536
   330
    if (!func) {
slouken@3536
   331
        if (!dst->format->Amask) {
slouken@3593
   332
            func = SDL_BlendFillRect_RGB;
slouken@3536
   333
        } else {
slouken@3593
   334
            func = SDL_BlendFillRect_RGBA;
slouken@3536
   335
        }
slouken@3536
   336
    }
slouken@3536
   337
slouken@3536
   338
    for (i = 0; i < count; ++i) {
slouken@3536
   339
        const SDL_Rect * rect = rects[i];
slouken@3536
   340
slouken@3536
   341
        /* If 'rect' == NULL, then fill the whole surface */
slouken@3536
   342
        if (rect) {
slouken@3536
   343
            /* Perform clipping */
slouken@3536
   344
            if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@3536
   345
                continue;
slouken@3536
   346
            }
slouken@3536
   347
            rect = &clipped;
slouken@3536
   348
        } else {
slouken@3536
   349
            rect = &dst->clip_rect;
slouken@3536
   350
        }
slouken@3536
   351
slouken@3536
   352
        status = func(dst, rect, blendMode, r, g, b, a);
slouken@3536
   353
    }
slouken@3536
   354
    return status;
slouken@3536
   355
}
slouken@3536
   356
slouken@2888
   357
/* vi: set ts=4 sw=4 expandtab: */