From 7af7eddbaac414fd711f1fae3c8db4e5b49a73fb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 20 Dec 2008 23:19:20 +0000 Subject: [PATCH] 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. --- src/video/SDL_blendline.c | 173 +++++++++++++++++++++++++++++++++++++- src/video/SDL_blendrect.c | 134 ++++++++++++++++++++++++++++- src/video/SDL_drawline.c | 14 +-- 3 files changed, 311 insertions(+), 10 deletions(-) diff --git a/src/video/SDL_blendline.c b/src/video/SDL_blendline.c index 99e3b9386..bc41b2034 100644 --- a/src/video/SDL_blendline.c +++ b/src/video/SDL_blendline.c @@ -24,11 +24,117 @@ #include "SDL_video.h" #include "SDL_blit.h" +#define ABS(_x) ((_x) < 0 ? -(_x) : (_x)) + +#define SWAP(_x, _y) do { int tmp; tmp = _x; _x = _y; _y = tmp; } while (0) + +#define BRESENHAM(x0, y0, x1, y1, op) \ +{ \ + int deltax, deltay, steep, error, xstep, ystep, x, y; \ + \ + deltax = ABS(x1 - x0); \ + deltay = ABS(y1 - y0); \ + steep = (deltay > deltax); \ + if (steep) { \ + SWAP(x0, y0); \ + SWAP(x1, y1); \ + SWAP(deltax, deltay); \ + } \ + error = (x1 - x0) / 2; \ + y = y0; \ + if (x0 > x1) { \ + xstep = -1; \ + } else { \ + xstep = 1; \ + } \ + if (y0 < y1) { \ + ystep = 1; \ + } else { \ + ystep = -1; \ + } \ + if (!steep) { \ + for (x = x0; x != x1; x += xstep) { \ + op(x, y); \ + error -= deltay; \ + if (error < 0) { \ + y += ystep; \ + error += deltax; \ + } \ + } \ + } else { \ + for (x = x0; x != x1; x += xstep) { \ + op(y, x); \ + error -= deltay; \ + if (error < 0) { \ + y += ystep; \ + error += deltax; \ + } \ + } \ + } \ +} + +#define MUL(_a, _b) (((Uint16)(_a)*(Uint16)(_b))/255) +#define SHIFTAND(_v, _s, _a) (((_v)>>(_s)) & _a) + +#define SETPIXEL_MASK(x, y, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ +do { \ + type *pixel = (type *)(dst->pixels + y * dst->pitch + x * bpp); \ + if (a) { \ + *pixel = (r<pixels + y * dst->pitch + x * bpp); \ + Uint8 sr = MUL(inva, SHIFTAND(*pixel, rshift, rmask)) + (Uint16) r; \ + Uint8 sg = MUL(inva, SHIFTAND(*pixel, gshift, gmask)) + (Uint16) g; \ + Uint8 sb = MUL(inva, SHIFTAND(*pixel, bshift, bmask)) + (Uint16) b; \ + *pixel = (sr<pixels + y * dst->pitch + x * bpp); \ + Uint16 sr = SHIFTAND(*pixel, rshift, rmask) + (Uint16) r; \ + Uint16 sg = SHIFTAND(*pixel, gshift, gmask) + (Uint16) g; \ + Uint16 sb = SHIFTAND(*pixel, bshift, bmask) + (Uint16) b; \ + if (sr>rmask) sr = rmask; \ + if (sg>gmask) sg = gmask; \ + if (sb>bmask) sb = bmask; \ + *pixel = (sr<pixels + y * dst->pitch + x * bpp); \ + Uint8 sr = MUL(SHIFTAND(*pixel, rshift, rmask), r); \ + Uint8 sg = MUL(SHIFTAND(*pixel, gshift, gmask), g); \ + Uint8 sb = MUL(SHIFTAND(*pixel, bshift, bmask), b); \ + *pixel = (sr<format->BitsPerPixel < 8) { SDL_SetError("SDL_BlendLine(): Unsupported surface format"); @@ -42,8 +148,71 @@ SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, } */ - SDL_Unsupported(); - return -1; + if ((blendMode == SDL_BLENDMODE_BLEND) + || (blendMode == SDL_BLENDMODE_ADD)) { + r = MUL(r, a); + g = MUL(g, a); + b = MUL(b, a); + } + switch (dst->format->BitsPerPixel) { + case 15: + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MASK); + break; + case SDL_BLENDMODE_BLEND: + BRESENHAM(x1, y1, x2, y2, SETPIXEL15_BLEND); + break; + case SDL_BLENDMODE_ADD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL15_ADD); + break; + case SDL_BLENDMODE_MOD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL15_MOD); + break; + } + break; + case 16: + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MASK); + break; + case SDL_BLENDMODE_BLEND: + BRESENHAM(x1, y1, x2, y2, SETPIXEL16_BLEND); + break; + case SDL_BLENDMODE_ADD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL16_ADD); + break; + case SDL_BLENDMODE_MOD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL16_MOD); + break; + } + break; + case 24: + case 32: + if (dst->format->BytesPerPixel != 4) { + SDL_Unsupported(); + return -1; + } + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MASK); + break; + case SDL_BLENDMODE_BLEND: + BRESENHAM(x1, y1, x2, y2, SETPIXEL32_BLEND); + break; + case SDL_BLENDMODE_ADD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL32_ADD); + break; + case SDL_BLENDMODE_MOD: + BRESENHAM(x1, y1, x2, y2, SETPIXEL32_MOD); + break; + } + break; + default: + SDL_Unsupported(); + return -1; + } + return 0; } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_blendrect.c b/src/video/SDL_blendrect.c index 7ddc387ad..62f295582 100644 --- a/src/video/SDL_blendrect.c +++ b/src/video/SDL_blendrect.c @@ -24,11 +24,79 @@ #include "SDL_video.h" #include "SDL_blit.h" +#define MUL(_a, _b) (((Uint16)(_a)*(Uint16)(_b))/255) +#define SHIFTAND(_v, _s, _a) (((_v)>>(_s)) & (_a)) + +#define SETPIXEL_MASK(p, type, bpp, rshift, gshift, bshift, rmask, gmask, bmask) \ +do { \ + if (a) { \ + p = (r<rmask) sr = rmask; \ + if (sg>gmask) sg = gmask; \ + if (sb>bmask) sb = bmask; \ + p = (sr<y; \ + int h = dstrect->h; \ + while (h--) { \ + type *pixel = (type *)(dst->pixels + y * dst->pitch + dstrect->x * dst->format->BytesPerPixel); \ + int w = dstrect->w; \ + while (w--) { \ + op(*pixel); \ + pixel++; \ + } \ + y++; \ + } \ +} while (0) int SDL_BlendRect(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { + Uint16 inva = 0xff - a; /* This function doesn't work on surfaces < 8 bpp */ if (dst->format->BitsPerPixel < 8) { SDL_SetError("SDL_BlendRect(): Unsupported surface format"); @@ -45,7 +113,71 @@ SDL_BlendRect(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r, dstrect = &dst->clip_rect; } - SDL_Unsupported(); + if ((blendMode == SDL_BLENDMODE_BLEND) + || (blendMode == SDL_BLENDMODE_ADD)) { + r = MUL(r, a); + g = MUL(g, a); + b = MUL(b, a); + } + switch (dst->format->BitsPerPixel) { + case 15: + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BLENDRECT(Uint16, SETPIXEL15_MASK); + break; + case SDL_BLENDMODE_BLEND: + BLENDRECT(Uint16, SETPIXEL15_BLEND); + break; + case SDL_BLENDMODE_ADD: + BLENDRECT(Uint16, SETPIXEL15_ADD); + break; + case SDL_BLENDMODE_MOD: + BLENDRECT(Uint16, SETPIXEL15_MOD); + break; + } + break; + case 16: + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BLENDRECT(Uint16, SETPIXEL16_MASK); + break; + case SDL_BLENDMODE_BLEND: + BLENDRECT(Uint16, SETPIXEL16_BLEND); + break; + case SDL_BLENDMODE_ADD: + BLENDRECT(Uint16, SETPIXEL16_ADD); + break; + case SDL_BLENDMODE_MOD: + BLENDRECT(Uint16, SETPIXEL16_MOD); + break; + } + break; + case 24: + case 32: + if (dst->format->BytesPerPixel != 4) { + SDL_Unsupported(); + return -1; + } + switch (blendMode) { + case SDL_BLENDMODE_MASK: + BLENDRECT(Uint32, SETPIXEL32_MASK); + break; + case SDL_BLENDMODE_BLEND: + BLENDRECT(Uint32, SETPIXEL32_BLEND); + break; + case SDL_BLENDMODE_ADD: + BLENDRECT(Uint32, SETPIXEL32_ADD); + break; + case SDL_BLENDMODE_MOD: + BLENDRECT(Uint32, SETPIXEL32_MOD); + break; + } + break; + default: + SDL_Unsupported(); + return -1; + } + return 0; return -1; } diff --git a/src/video/SDL_drawline.c b/src/video/SDL_drawline.c index 75f8d32ed..d03a8abad 100644 --- a/src/video/SDL_drawline.c +++ b/src/video/SDL_drawline.c @@ -24,9 +24,9 @@ #include "SDL_video.h" #include "SDL_blit.h" -#define ABS(x) (x < 0 ? -x : x) +#define ABS(_x) ((_x) < 0 ? -(_x) : (_x)) -#define SWAP(x, y) (x ^= y ^= x ^= y) +#define SWAP(_x, _y) do { int tmp; tmp = _x; _x = _y; _y = tmp; } while (0) #define BRESENHAM(x0, y0, x1, y1, op, color) \ { \ @@ -34,16 +34,16 @@ \ deltax = ABS(x1 - x0); \ deltay = ABS(y1 - y0); \ - steep = deltay > deltax; \ - error = deltax / 2; \ + steep = (deltay > deltax); \ if (steep) { \ SWAP(x0, y0); \ SWAP(x1, y1); \ + SWAP(deltax, deltay); \ } \ + error = (x1 - x0) / 2; \ y = y0; \ if (x0 > x1) { \ xstep = -1; \ - deltax = -deltax; \ } else { \ xstep = 1; \ } \ @@ -57,7 +57,7 @@ op(x, y, color); \ error -= deltay; \ if (error < 0) { \ - y = y + ystep; \ + y += ystep; \ error += deltax; \ } \ } \ @@ -66,7 +66,7 @@ op(y, x, color); \ error -= deltay; \ if (error < 0) { \ - y = y + ystep; \ + y += ystep; \ error += deltax; \ } \ } \