src/video/SDL_blendline.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 20 Dec 2008 23:19:20 +0000
changeset 2896 1ef2f1e75ff7
parent 2888 32e8bbba1e94
child 2898 e40448bc7727
permissions -rw-r--r--
Date: Sat, 20 Dec 2008 23:25:19 +0100
From: Couriersud
Subject: 32 & 16 bit versions of blendrect and blendline

attached are 32, 16 and 15 bit versions of the blendrect and blendline
functionality. There was an issue with the bresenham alg. in drawline
which I also fixed.
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@2888
    25
#include "SDL_blit.h"
slouken@2888
    26
slouken@2896
    27
#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
slouken@2896
    28
slouken@2896
    29
#define SWAP(_x, _y) do { int tmp; tmp = _x; _x = _y; _y = tmp; } while (0)
slouken@2896
    30
slouken@2896
    31
#define BRESENHAM(x0, y0, x1, y1, op) \
slouken@2896
    32
{ \
slouken@2896
    33
    int deltax, deltay, steep, error, xstep, ystep, x, y; \
slouken@2896
    34
 \
slouken@2896
    35
    deltax = ABS(x1 - x0); \
slouken@2896
    36
    deltay = ABS(y1 - y0); \
slouken@2896
    37
    steep = (deltay > deltax); \
slouken@2896
    38
    if (steep) { \
slouken@2896
    39
        SWAP(x0, y0); \
slouken@2896
    40
        SWAP(x1, y1); \
slouken@2896
    41
        SWAP(deltax, deltay); \
slouken@2896
    42
    } \
slouken@2896
    43
    error = (x1 - x0) / 2; \
slouken@2896
    44
    y = y0; \
slouken@2896
    45
    if (x0 > x1) { \
slouken@2896
    46
        xstep = -1; \
slouken@2896
    47
    } else { \
slouken@2896
    48
        xstep = 1; \
slouken@2896
    49
    } \
slouken@2896
    50
    if (y0 < y1) { \
slouken@2896
    51
        ystep = 1; \
slouken@2896
    52
    } else { \
slouken@2896
    53
        ystep = -1; \
slouken@2896
    54
    } \
slouken@2896
    55
    if (!steep) { \
slouken@2896
    56
        for (x = x0; x != x1; x += xstep) { \
slouken@2896
    57
            op(x, y); \
slouken@2896
    58
            error -= deltay; \
slouken@2896
    59
            if (error < 0) { \
slouken@2896
    60
                y += ystep; \
slouken@2896
    61
                error += deltax; \
slouken@2896
    62
            } \
slouken@2896
    63
        } \
slouken@2896
    64
    } else { \
slouken@2896
    65
        for (x = x0; x != x1; x += xstep) { \
slouken@2896
    66
            op(y, x); \
slouken@2896
    67
            error -= deltay; \
slouken@2896
    68
            if (error < 0) { \
slouken@2896
    69
                y += ystep; \
slouken@2896
    70
                error += deltax; \
slouken@2896
    71
            } \
slouken@2896
    72
        } \
slouken@2896
    73
    } \
slouken@2896
    74
}
slouken@2896
    75
slouken@2896
    76
#define MUL(_a, _b) (((Uint16)(_a)*(Uint16)(_b))/255)
slouken@2896
    77
#define SHIFTAND(_v, _s, _a) (((_v)>>(_s)) & _a)
slouken@2896
    78
slouken@2896
    79
#define SETPIXEL_MASK(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \
slouken@2896
    80
do { \
slouken@2896
    81
	type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \
slouken@2896
    82
	if (a) { \
slouken@2896
    83
		*pixel = (r<<rshift) | (g<<gshift) | (b<<bshift); \
slouken@2896
    84
	} \
slouken@2896
    85
} while (0)
slouken@2896
    86
slouken@2896
    87
#define SETPIXEL_BLEND(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \
slouken@2896
    88
do { \
slouken@2896
    89
	type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \
slouken@2896
    90
	Uint8 sr = MUL(inva, SHIFTAND(*pixel, rshift, rmask)) + (Uint16) r; \
slouken@2896
    91
	Uint8 sg = MUL(inva, SHIFTAND(*pixel, gshift, gmask)) + (Uint16) g; \
slouken@2896
    92
	Uint8 sb = MUL(inva, SHIFTAND(*pixel, bshift, bmask)) + (Uint16) b; \
slouken@2896
    93
	*pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift);  \
slouken@2896
    94
} while (0)
slouken@2896
    95
slouken@2896
    96
#define SETPIXEL_ADD(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \
slouken@2896
    97
do { \
slouken@2896
    98
	type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \
slouken@2896
    99
	Uint16 sr = SHIFTAND(*pixel, rshift, rmask) + (Uint16) r; \
slouken@2896
   100
	Uint16 sg = SHIFTAND(*pixel, gshift, gmask) + (Uint16) g; \
slouken@2896
   101
	Uint16 sb = SHIFTAND(*pixel, bshift, bmask) + (Uint16) b; \
slouken@2896
   102
	if (sr>rmask) sr = rmask;  \
slouken@2896
   103
	if (sg>gmask) sg = gmask;  \
slouken@2896
   104
	if (sb>bmask) sb = bmask;  \
slouken@2896
   105
	*pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift);  \
slouken@2896
   106
} while (0)
slouken@2896
   107
slouken@2896
   108
#define SETPIXEL_MOD(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \
slouken@2896
   109
do { \
slouken@2896
   110
	type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \
slouken@2896
   111
	Uint8 sr = MUL(SHIFTAND(*pixel, rshift, rmask), r); \
slouken@2896
   112
	Uint8 sg = MUL(SHIFTAND(*pixel, gshift, gmask), g); \
slouken@2896
   113
	Uint8 sb = MUL(SHIFTAND(*pixel, bshift, bmask), b); \
slouken@2896
   114
	*pixel = (sr<<rshift) | (sg<<gshift) | (sb<<bshift);  \
slouken@2896
   115
} while (0)
slouken@2896
   116
slouken@2896
   117
slouken@2896
   118
#define SETPIXEL15_MASK(x, y) SETPIXEL_MASK(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f);
slouken@2896
   119
#define SETPIXEL15_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f);
slouken@2896
   120
#define SETPIXEL15_ADD(x, y) SETPIXEL_ADD(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f);
slouken@2896
   121
#define SETPIXEL15_MOD(x, y) SETPIXEL_MOD(x, y, Uint16, 2, 10, 5, 0, 0x1f, 0x1f, 0x1f);
slouken@2896
   122
slouken@2896
   123
#define SETPIXEL16_MASK(x, y) SETPIXEL_MASK(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f);
slouken@2896
   124
#define SETPIXEL16_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f);
slouken@2896
   125
#define SETPIXEL16_ADD(x, y) SETPIXEL_ADD(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f);
slouken@2896
   126
#define SETPIXEL16_MOD(x, y) SETPIXEL_MOD(x, y, Uint16, 2, 11, 5, 0, 0x1f, 0x3f, 0x1f);
slouken@2896
   127
slouken@2896
   128
#define SETPIXEL32_MASK(x, y) SETPIXEL_MASK(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff);
slouken@2896
   129
#define SETPIXEL32_BLEND(x, y) SETPIXEL_BLEND(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff);
slouken@2896
   130
#define SETPIXEL32_ADD(x, y) SETPIXEL_ADD(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff);
slouken@2896
   131
#define SETPIXEL32_MOD(x, y) SETPIXEL_MOD(x, y, Uint32, 4, 16, 8, 0, 0xff, 0xff, 0xff);
slouken@2888
   132
slouken@2888
   133
int
slouken@2888
   134
SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
slouken@2888
   135
              int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2888
   136
{
slouken@2896
   137
    Uint8 inva = 0xff - a;
slouken@2888
   138
    /* This function doesn't work on surfaces < 8 bpp */
slouken@2888
   139
    if (dst->format->BitsPerPixel < 8) {
slouken@2888
   140
        SDL_SetError("SDL_BlendLine(): Unsupported surface format");
slouken@2888
   141
        return (-1);
slouken@2888
   142
    }
slouken@2888
   143
slouken@2888
   144
    /* Perform clipping */
slouken@2888
   145
    /* FIXME
slouken@2888
   146
       if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
slouken@2888
   147
       return (0);
slouken@2888
   148
       }
slouken@2888
   149
     */
slouken@2888
   150
slouken@2896
   151
    if ((blendMode == SDL_BLENDMODE_BLEND)
slouken@2896
   152
        || (blendMode == SDL_BLENDMODE_ADD)) {
slouken@2896
   153
        r = MUL(r, a);
slouken@2896
   154
        g = MUL(g, a);
slouken@2896
   155
        b = MUL(b, a);
slouken@2896
   156
    }
slouken@2896
   157
    switch (dst->format->BitsPerPixel) {
slouken@2896
   158
    case 15:
slouken@2896
   159
        switch (blendMode) {
slouken@2896
   160
        case SDL_BLENDMODE_MASK:
slouken@2896
   161
            BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MASK);
slouken@2896
   162
            break;
slouken@2896
   163
        case SDL_BLENDMODE_BLEND:
slouken@2896
   164
            BRESENHAM(x1, y1, x2, y2, SETPIXEL15_BLEND);
slouken@2896
   165
            break;
slouken@2896
   166
        case SDL_BLENDMODE_ADD:
slouken@2896
   167
            BRESENHAM(x1, y1, x2, y2, SETPIXEL15_ADD);
slouken@2896
   168
            break;
slouken@2896
   169
        case SDL_BLENDMODE_MOD:
slouken@2896
   170
            BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MOD);
slouken@2896
   171
            break;
slouken@2896
   172
        }
slouken@2896
   173
        break;
slouken@2896
   174
    case 16:
slouken@2896
   175
        switch (blendMode) {
slouken@2896
   176
        case SDL_BLENDMODE_MASK:
slouken@2896
   177
            BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MASK);
slouken@2896
   178
            break;
slouken@2896
   179
        case SDL_BLENDMODE_BLEND:
slouken@2896
   180
            BRESENHAM(x1, y1, x2, y2, SETPIXEL16_BLEND);
slouken@2896
   181
            break;
slouken@2896
   182
        case SDL_BLENDMODE_ADD:
slouken@2896
   183
            BRESENHAM(x1, y1, x2, y2, SETPIXEL16_ADD);
slouken@2896
   184
            break;
slouken@2896
   185
        case SDL_BLENDMODE_MOD:
slouken@2896
   186
            BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MOD);
slouken@2896
   187
            break;
slouken@2896
   188
        }
slouken@2896
   189
        break;
slouken@2896
   190
    case 24:
slouken@2896
   191
    case 32:
slouken@2896
   192
        if (dst->format->BytesPerPixel != 4) {
slouken@2896
   193
            SDL_Unsupported();
slouken@2896
   194
            return -1;
slouken@2896
   195
        }
slouken@2896
   196
        switch (blendMode) {
slouken@2896
   197
        case SDL_BLENDMODE_MASK:
slouken@2896
   198
            BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MASK);
slouken@2896
   199
            break;
slouken@2896
   200
        case SDL_BLENDMODE_BLEND:
slouken@2896
   201
            BRESENHAM(x1, y1, x2, y2, SETPIXEL32_BLEND);
slouken@2896
   202
            break;
slouken@2896
   203
        case SDL_BLENDMODE_ADD:
slouken@2896
   204
            BRESENHAM(x1, y1, x2, y2, SETPIXEL32_ADD);
slouken@2896
   205
            break;
slouken@2896
   206
        case SDL_BLENDMODE_MOD:
slouken@2896
   207
            BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MOD);
slouken@2896
   208
            break;
slouken@2896
   209
        }
slouken@2896
   210
        break;
slouken@2896
   211
    default:
slouken@2896
   212
        SDL_Unsupported();
slouken@2896
   213
        return -1;
slouken@2896
   214
    }
slouken@2896
   215
    return 0;
slouken@2888
   216
}
slouken@2888
   217
slouken@2888
   218
/* vi: set ts=4 sw=4 expandtab: */