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; \ } \ } \