diff options
author | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2009-07-30 20:34:23 +0000 |
---|---|---|
committer | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2009-07-30 20:34:23 +0000 |
commit | d72782347c2ba802cd030feeb23f7eacc4ae8a23 (patch) | |
tree | a729476323d0d551c2031b3a666193923ceb08a4 /graphics/sdl/raster.c | |
parent | c297ef7f5928b0407ab67b9a76ccf166d0a1d3e0 (diff) | |
parent | 3b8435d744c504a88493f272068453023585837e (diff) | |
download | navit-svn-wince.tar.gz |
Updated wince branch to current versionwince
git-svn-id: http://svn.code.sf.net/p/navit/code/branches/wince/navit@2430 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'graphics/sdl/raster.c')
-rw-r--r-- | graphics/sdl/raster.c | 2022 |
1 files changed, 2022 insertions, 0 deletions
diff --git a/graphics/sdl/raster.c b/graphics/sdl/raster.c new file mode 100644 index 00000000..dd54cd4a --- /dev/null +++ b/graphics/sdl/raster.c @@ -0,0 +1,2022 @@ +/* raster.c -- line/rect/circle/poly rasterization + + copyright (c) 2008 bryan rittmeyer <bryanr@bryanr.org> + license: LGPLv2 + + based on SDL_gfx (c) A. Schiffler + and SGE (c)1999-2003 Anders Lindström + + + added filled anti-aliased polygons + + fixed some bugs and improved performance + + revision history + 2008-07-05 initial + 2008-07-06 aacircle +*/ + + +#include <math.h> + +#include "raster.h" + +#undef DEBUG +#undef PARANOID + + +/* raster_rect */ + +static inline void raster_rect_inline(SDL_Surface *dst, int16_t x1, int16_t y1, int16_t w, int16_t h, uint32_t color) +{ + /* sge */ + SDL_Rect rect; + +#if 1 + if((w <= 0) || (h <= 0)) + { + return; + } + +#if 0 + if(x1 < 0) + { + if((x1 + w) < 0) + { + return; + } + else + { + w = w + x1; + x1 = 0; + } + } + if(y1 < 0) + { + if((y1 + h) < 0) + { + return; + } + else + { + h = h + y1; + y1 = 0; + } + } + + if(x1 + w >= dst->w) + { + w = dst->w - x1; + } + if(y1 + h >= dst->h) + { + h = dst->h - y1; + } +#endif + + rect.x = x1; + rect.y = y1; + rect.w = w; + rect.h = h; + + /* will clip internally */ + SDL_FillRect(dst, &rect, color); + +#else + + x2 = x1 + w; + y2 = y1 + h; + + /* + * Order coordinates to ensure that + * x1<=x2 and y1<=y2 + */ + if (x1 > x2) { + tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) { + tmp = y1; + y1 = y2; + y2 = tmp; + } + + /* + * Get clipping boundary and + * check visibility + */ + left = dst->clip_rect.x; + if (x2<left) { + return(0); + } + right = dst->clip_rect.x + dst->clip_rect.w - 1; + if (x1>right) { + return(0); + } + top = dst->clip_rect.y; + if (y2<top) { + return(0); + } + bottom = dst->clip_rect.y + dst->clip_rect.h - 1; + if (y1>bottom) { + return(0); + } + + /* Clip all points */ + if (x1<left) { + x1=left; + } else if (x1>right) { + x1=right; + } + if (x2<left) { + x2=left; + } else if (x2>right) { + x2=right; + } + if (y1<top) { + y1=top; + } else if (y1>bottom) { + y1=bottom; + } + if (y2<top) { + y2=top; + } else if (y2>bottom) { + y2=bottom; + } + +#if 0 + /* + * Test for special cases of straight line or single point + */ + if (x1 == x2) { + if (y1 == y2) { + return (pixelColor(dst, x1, y1, color)); + } else { + return (vlineColor(dst, x1, y1, y2, color)); + } + } + if (y1 == y2) { + return (hlineColor(dst, x1, x2, y1, color)); + } +#endif + + /* + * Calculate width&height + */ + w = x2 - x1; + h = y2 - y1; + + /* + * No alpha-blending required + */ + +#if 0 + /* + * Setup color + */ + colorptr = (Uint8 *) & color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } +#endif + + /* + * Lock surface + */ + SDL_LockSurface(dst); + + /* + * More variable setup + */ + dx = w; + dy = h; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1; + pixellast = pixel + pixx * dx + pixy * dy; + dx++; + + /* + * Draw + */ + switch (dst->format->BytesPerPixel) { + case 1: + for (; pixel <= pixellast; pixel += pixy) { + memset(pixel, (Uint8) color, dx); + } + break; + case 2: + pixy -= (pixx * dx); + for (; pixel <= pixellast; pixel += pixy) { + for (x = 0; x < dx; x++) { + *(Uint16*) pixel = color; + pixel += pixx; + } + } + break; + case 3: + pixy -= (pixx * dx); + for (; pixel <= pixellast; pixel += pixy) { + for (x = 0; x < dx; x++) { + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + pixel += pixx; + } + } + break; + default: /* case 4 */ + pixy -= (pixx * dx); + for (; pixel <= pixellast; pixel += pixy) { + for (x = 0; x < dx; x++) { + *(Uint32 *) pixel = color; + pixel += pixx; + } + } + break; + } + + /* + * Unlock surface + */ + SDL_UnlockSurface(dst); + +#endif +} + +void raster_rect(SDL_Surface *s, int16_t x, int16_t y, int16_t w, int16_t h, uint32_t col) +{ + raster_rect_inline(s, x, y, w, h, col); +} + +#define raster_rect_inline raster_rect + + +/* raster :: pixel */ + +#define MODIFIED_ALPHA_PIXEL_ROUTINE + + +#define clip_xmin(surface) surface->clip_rect.x +#define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1 +#define clip_ymin(surface) surface->clip_rect.y +#define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1 + + +static void raster_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + if(x>=clip_xmin(surface) && x<=clip_xmax(surface) && y>=clip_ymin(surface) && y<=clip_ymax(surface)){ + switch (surface->format->BytesPerPixel) { + case 1: { /* Assuming 8-bpp */ + *((Uint8 *)surface->pixels + y*surface->pitch + x) = color; + } + break; + + case 2: { /* Probably 15-bpp or 16-bpp */ + *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color; + } + break; + + case 3: { /* Slow 24-bpp mode, usually not used */ + Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; + + /* Gack - slow, but endian correct */ + *(pix+surface->format->Rshift/8) = color>>surface->format->Rshift; + *(pix+surface->format->Gshift/8) = color>>surface->format->Gshift; + *(pix+surface->format->Bshift/8) = color>>surface->format->Bshift; + *(pix+surface->format->Ashift/8) = color>>surface->format->Ashift; + } + break; + + case 4: { /* Probably 32-bpp */ + *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color; + } + break; + } + } +} + +/* PutPixel routine with alpha blending, input color in destination format */ + +/* New, faster routine - default blending pixel */ + +static void raster_PutPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) +{ + /* sdl-gfx */ + Uint32 Rmask = surface->format->Rmask, Gmask = + surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask; + Uint32 R = 0, G = 0, B = 0, A = 0; + + if (x >= clip_xmin(surface) && x <= clip_xmax(surface) + && y >= clip_ymin(surface) && y <= clip_ymax(surface)) { + + switch (surface->format->BytesPerPixel) { + case 1:{ /* Assuming 8-bpp */ + if (alpha == 255) { + *((Uint8 *) surface->pixels + y * surface->pitch + x) = color; + } else { + Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x; + + Uint8 dR = surface->format->palette->colors[*pixel].r; + Uint8 dG = surface->format->palette->colors[*pixel].g; + Uint8 dB = surface->format->palette->colors[*pixel].b; + Uint8 sR = surface->format->palette->colors[color].r; + Uint8 sG = surface->format->palette->colors[color].g; + Uint8 sB = surface->format->palette->colors[color].b; + + dR = dR + ((sR - dR) * alpha >> 8); + dG = dG + ((sG - dG) * alpha >> 8); + dB = dB + ((sB - dB) * alpha >> 8); + + *pixel = SDL_MapRGB(surface->format, dR, dG, dB); + } + } + break; + + case 2:{ /* Probably 15-bpp or 16-bpp */ + if (alpha == 255) { + *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color; + } else { + Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x; + Uint32 dc = *pixel; + + R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask; + G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask; + B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask; + if (Amask) + A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask; + + *pixel = R | G | B | A; + } + } + break; + + case 3:{ /* Slow 24-bpp mode, usually not used */ + Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3; + Uint8 rshift8 = surface->format->Rshift / 8; + Uint8 gshift8 = surface->format->Gshift / 8; + Uint8 bshift8 = surface->format->Bshift / 8; + Uint8 ashift8 = surface->format->Ashift / 8; + + + if (alpha == 255) { + *(pix + rshift8) = color >> surface->format->Rshift; + *(pix + gshift8) = color >> surface->format->Gshift; + *(pix + bshift8) = color >> surface->format->Bshift; + *(pix + ashift8) = color >> surface->format->Ashift; + } else { + Uint8 dR, dG, dB, dA = 0; + Uint8 sR, sG, sB, sA = 0; + + pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3; + + dR = *((pix) + rshift8); + dG = *((pix) + gshift8); + dB = *((pix) + bshift8); + dA = *((pix) + ashift8); + + sR = (color >> surface->format->Rshift) & 0xff; + sG = (color >> surface->format->Gshift) & 0xff; + sB = (color >> surface->format->Bshift) & 0xff; + sA = (color >> surface->format->Ashift) & 0xff; + + dR = dR + ((sR - dR) * alpha >> 8); + dG = dG + ((sG - dG) * alpha >> 8); + dB = dB + ((sB - dB) * alpha >> 8); + dA = dA + ((sA - dA) * alpha >> 8); + + *((pix) + rshift8) = dR; + *((pix) + gshift8) = dG; + *((pix) + bshift8) = dB; + *((pix) + ashift8) = dA; + } + } + break; + +#ifdef ORIGINAL_ALPHA_PIXEL_ROUTINE + + case 4:{ /* Probably :-) 32-bpp */ + if (alpha == 255) { + *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color; + } else { + Uint32 Rshift, Gshift, Bshift, Ashift; + Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x; + Uint32 dc = *pixel; + + Rshift = surface->format->Rshift; + Gshift = surface->format->Gshift; + Bshift = surface->format->Bshift; + Ashift = surface->format->Ashift; + + R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask; + G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask; + B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask; + if (Amask) + A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask; + + *pixel = R | G | B | A; + } + } + break; +#endif + +#ifdef MODIFIED_ALPHA_PIXEL_ROUTINE + + case 4:{ /* Probably :-) 32-bpp */ + if (alpha == 255) { + *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color; + } else { + Uint32 Rshift, Gshift, Bshift, Ashift; + Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x; + Uint32 dc = *pixel; + Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask); + Uint32 surfaceAlpha, preMultR, preMultG, preMultB; + Uint32 aTmp; + + Rshift = surface->format->Rshift; + Gshift = surface->format->Gshift; + Bshift = surface->format->Bshift; + Ashift = surface->format->Ashift; + + preMultR = (alpha * (dR>>Rshift)); + preMultG = (alpha * (dG>>Gshift)); + preMultB = (alpha * (dB>>Bshift)); + + surfaceAlpha = ((dc & Amask) >> Ashift); + aTmp = (255 - alpha); + if ((A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 ))) { + aTmp *= surfaceAlpha; + R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; + G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; + B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; + } + *pixel = R | G | B | (A << Ashift & Amask); + + } + } + break; +#endif + } + } +} + + +/* FIXME: eliminate these 2 functions */ + +static int raster_pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) +{ + int result = 0; + +#if 0 + /* + * Setup color + */ + alpha = color & 0x000000ff; + mcolor = + SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, + (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); +#endif + + /* + * Draw + */ + raster_PutPixel(dst, x, y, color); + + return (result); +} + + +/* Pixel - using alpha weight on color for AA-drawing - no locking */ + +static int raster_pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) +{ +#if 0 + Uint32 a; + + /* + * Get alpha + */ + a = (color & (Uint32) 0x000000ff); + + /* + * Modify Alpha by weight + */ + a = ((a * weight) >> 8); +#endif + + raster_PutPixelAlpha(dst, x, y, color, weight); + + return 0; +} + + +/* raster :: line */ + + + +static inline void raster_hline(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) +{ +#if 1 + SDL_Rect l; + + /* sge */ + if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;} + + l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1; + + SDL_FillRect(dst, &l, color); + +#else + /* sdl_gfx */ + Sint16 left, right, top, bottom; + Uint8 *pixel, *pixellast; + int dx; + int pixx, pixy; + Sint16 w; + Sint16 xtmp; + int result = -1; +#if 0 + int i; + union + { + double d; + uint16_t col[4]; + } doub; + + for(i = 0; i < 4; i++) + { + doub.col[i] = color; + } +#endif + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return(0); + } + + /* + * Swap x1, x2 if required to ensure x1<=x2 + */ + if (x1 > x2) { + xtmp = x1; + x1 = x2; + x2 = xtmp; + } + + /* + * Get clipping boundary and + * check visibility of hline + */ + left = dst->clip_rect.x; + if (x2<left) { + return(0); + } + right = dst->clip_rect.x + dst->clip_rect.w - 1; + if (x1>right) { + return(0); + } + top = dst->clip_rect.y; + bottom = dst->clip_rect.y + dst->clip_rect.h - 1; + if ((y<top) || (y>bottom)) { + return (0); + } + + /* + * Clip x + */ + if (x1 < left) { + x1 = left; + } + if (x2 > right) { + x2 = right; + } + + /* + * Calculate width + */ + w = x2 - x1; + +#if 0 + printf("raster_hline %d %d %d %d\n", x1, x2, y, w); +#endif + + /* + * Lock surface + */ + if (SDL_MUSTLOCK(dst)) { + SDL_LockSurface(dst); + } + + /* + * More variable setup + */ + dx = w; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; + + /* + * Draw + */ + switch (dst->format->BytesPerPixel) { + case 1: + memset(pixel, color, dx); + break; + case 2: + pixellast = pixel + dx + dx; +#if 0 + for (; (pixel+3) <= pixellast; pixel += 4*pixx) + { + *(double *)pixel = doub.d; + } +#endif + for (; pixel <= pixellast; pixel += pixx) { + *(Uint16 *) pixel = color; + } + break; + case 3: + pixellast = pixel + dx + dx + dx; + for (; pixel <= pixellast; pixel += pixx) { + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + } + break; + default: /* case 4 */ + dx = dx + dx; + pixellast = pixel + dx + dx; + for (; pixel <= pixellast; pixel += pixx) { + *(Uint32 *) pixel = color; + } + break; + } + + /* + * Unlock surface + */ + if (SDL_MUSTLOCK(dst)) { + SDL_UnlockSurface(dst); + } + + /* + * Set result code + */ + result = 0; + + return (result); +#endif +} + +static void raster_vline(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) +{ + SDL_Rect l; + + if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;} + + l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1; + + SDL_FillRect(dst, &l, color); +} + + + +/* raster_line */ +#define CLIP_LEFT_EDGE 0x1 +#define CLIP_RIGHT_EDGE 0x2 +#define CLIP_BOTTOM_EDGE 0x4 +#define CLIP_TOP_EDGE 0x8 +#define CLIP_INSIDE(a) (!a) +#define CLIP_REJECT(a,b) (a&b) +#define CLIP_ACCEPT(a,b) (!(a|b)) + +static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) +{ + int code = 0; + + if (x < left) { + code |= CLIP_LEFT_EDGE; + } else if (x > right) { + code |= CLIP_RIGHT_EDGE; + } + if (y < top) { + code |= CLIP_TOP_EDGE; + } else if (y > bottom) { + code |= CLIP_BOTTOM_EDGE; + } + return code; +} + +static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2) +{ + Sint16 left, right, top, bottom; + int code1, code2; + int draw = 0; + Sint16 swaptmp; + float m; + + /* + * Get clipping boundary + */ + left = dst->clip_rect.x; + right = dst->clip_rect.x + dst->clip_rect.w - 1; + top = dst->clip_rect.y; + bottom = dst->clip_rect.y + dst->clip_rect.h - 1; + + while (1) { + code1 = clipEncode(*x1, *y1, left, top, right, bottom); + code2 = clipEncode(*x2, *y2, left, top, right, bottom); + if (CLIP_ACCEPT(code1, code2)) { + draw = 1; + break; + } else if (CLIP_REJECT(code1, code2)) + break; + else { + if (CLIP_INSIDE(code1)) { + swaptmp = *x2; + *x2 = *x1; + *x1 = swaptmp; + swaptmp = *y2; + *y2 = *y1; + *y1 = swaptmp; + swaptmp = code2; + code2 = code1; + code1 = swaptmp; + } + if (*x2 != *x1) { + m = (*y2 - *y1) / (float) (*x2 - *x1); + } else { + m = 1.0f; + } + if (code1 & CLIP_LEFT_EDGE) { + *y1 += (Sint16) ((left - *x1) * m); + *x1 = left; + } else if (code1 & CLIP_RIGHT_EDGE) { + *y1 += (Sint16) ((right - *x1) * m); + *x1 = right; + } else if (code1 & CLIP_BOTTOM_EDGE) { + if (*x2 != *x1) { + *x1 += (Sint16) ((bottom - *y1) / m); + } + *y1 = bottom; + } else if (code1 & CLIP_TOP_EDGE) { + if (*x2 != *x1) { + *x1 += (Sint16) ((top - *y1) / m); + } + *y1 = top; + } + } + } + + return draw; +} + + +void raster_line(SDL_Surface *dst, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t color) +{ + /* sdl-gfx */ + int pixx, pixy; + int x, y; + int dx, dy; + int sx, sy; + int swaptmp; + Uint8 *pixel; + + /* + * Clip line and test if we have to draw + */ + if (!(clipLine(dst, &x1, &y1, &x2, &y2))) { + return; + } + + /* + * Test for special cases of straight lines or single point + */ + if (x1 == x2) { + if (y1 < y2) { + raster_vline(dst, x1, y1, y2, color); + return; + } else if (y1 > y2) { + raster_vline(dst, x1, y2, y1, color); + return; + } else { + raster_PutPixel(dst, x1, y1, color); + return; + } + } + if (y1 == y2) { + if (x1 < x2) { + raster_hline(dst, x1, x2, y1, color); + return; + } else if (x1 > x2) { + raster_hline(dst, x2, x1, y1, color); + return; + } + } + + + /* + * Variable setup + */ + dx = x2 - x1; + dy = y2 - y1; + sx = (dx >= 0) ? 1 : -1; + sy = (dy >= 0) ? 1 : -1; + + /* Lock surface */ + if (SDL_MUSTLOCK(dst)) { + if (SDL_LockSurface(dst) < 0) { + return; + } + } + + /* + * No alpha blending - use fast pixel routines + */ + +#if 0 + /* + * Setup color + */ + colorptr = (Uint8 *) & color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } +#endif + + /* + * More variable setup + */ + dx = sx * dx + 1; + dy = sy * dy + 1; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1; + pixx *= sx; + pixy *= sy; + if (dx < dy) { + swaptmp = dx; + dx = dy; + dy = swaptmp; + swaptmp = pixx; + pixx = pixy; + pixy = swaptmp; + } + + /* + * Draw + */ + x = 0; + y = 0; + switch (dst->format->BytesPerPixel) { + case 1: + for (; x < dx; x++, pixel += pixx) { + *pixel = color; + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + case 2: + for (; x < dx; x++, pixel += pixx) { + *(Uint16 *) pixel = color; + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + case 3: + for (; x < dx; x++, pixel += pixx) { + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + default: /* case 4 */ + for (; x < dx; x++, pixel += pixx) { + *(Uint32 *) pixel = color; + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + } + + /* Unlock surface */ + if (SDL_MUSTLOCK(dst)) { + SDL_UnlockSurface(dst); + } + + return; +} + + +#define AAlevels 256 +#define AAbits 8 + +static void raster_aalineColorInt(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint) +{ + Sint32 xx0, yy0, xx1, yy1; + int result; + Uint32 intshift, erracc, erradj; + Uint32 erracctmp, wgt, wgtcompmask; + int dx, dy, tmp, xdir, y0p1, x0pxdir; + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return; + } + + /* + * Clip line and test if we have to draw + */ + if (!(clipLine(dst, &x1, &y1, &x2, &y2))) { + return; + } + + /* + * Keep on working with 32bit numbers + */ + xx0 = x1; + yy0 = y1; + xx1 = x2; + yy1 = y2; + + /* + * Reorder points if required + */ + if (yy0 > yy1) { + tmp = yy0; + yy0 = yy1; + yy1 = tmp; + tmp = xx0; + xx0 = xx1; + xx1 = tmp; + } + + /* + * Calculate distance + */ + dx = xx1 - xx0; + dy = yy1 - yy0; + + /* + * Adjust for negative dx and set xdir + */ + if (dx >= 0) { + xdir = 1; + } else { + xdir = -1; + dx = (-dx); + } + + /* + * Check for special cases + */ + if (dx == 0) { + /* + * Vertical line + */ + raster_vline(dst, x1, y1, y2, color); + return; + } else if (dy == 0) { + /* + * Horizontal line + */ + raster_hline(dst, x1, x2, y1, color); + return; + } else if (dx == dy) { + /* + * Diagonal line + */ + raster_line(dst, x1, y1, x2, y2, color); + return; + } + + /* + * Line is not horizontal, vertical or diagonal + */ + result = 0; + + /* + * Zero accumulator + */ + erracc = 0; + + /* + * # of bits by which to shift erracc to get intensity level + */ + intshift = 32 - AAbits; + /* + * Mask used to flip all bits in an intensity weighting + */ + wgtcompmask = AAlevels - 1; + + /* Lock surface */ + if (SDL_MUSTLOCK(dst)) { + if (SDL_LockSurface(dst) < 0) { + return; + } + } + + /* + * Draw the initial pixel in the foreground color + */ + raster_pixelColorNolock(dst, x1, y1, color); + + /* + * x-major or y-major? + */ + if (dy > dx) { + + /* + * y-major. Calculate 16-bit fixed point fractional part of a pixel that + * X advances every time Y advances 1 pixel, truncating the result so that + * we won't overrun the endpoint along the X axis + */ + /* + * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; + */ + erradj = ((dx << 16) / dy) << 16; + + /* + * draw all pixels other than the first and last + */ + x0pxdir = xx0 + xdir; + while (--dy) { + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) { + /* + * rollover in error accumulator, x coord advances + */ + xx0 = x0pxdir; + x0pxdir += xdir; + } + yy0++; /* y-major so always advance Y */ + + /* + * the AAbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = (erracc >> intshift) & 255; + raster_pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); + raster_pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt); + } + + } else { + + /* + * x-major line. Calculate 16-bit fixed-point fractional part of a pixel + * that Y advances each time X advances 1 pixel, truncating the result so + * that we won't overrun the endpoint along the X axis. + */ + /* + * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; + */ + erradj = ((dy << 16) / dx) << 16; + + /* + * draw all pixels other than the first and last + */ + y0p1 = yy0 + 1; + while (--dx) { + + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) { + /* + * Accumulator turned over, advance y + */ + yy0 = y0p1; + y0p1++; + } + xx0 += xdir; /* x-major so always advance X */ + /* + * the AAbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = (erracc >> intshift) & 255; + raster_pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); + raster_pixelColorWeightNolock (dst, xx0, y0p1, color, wgt); + } + } + + /* + * Do we have to draw the endpoint + */ + if (draw_endpoint) { + /* + * Draw final pixel, always exactly intersected by the line and doesn't + * need to be weighted. + */ + raster_pixelColorNolock (dst, x2, y2, color); + } + + /* Unlock surface */ + if (SDL_MUSTLOCK(dst)) { + SDL_UnlockSurface(dst); + } +} + +void raster_aaline(SDL_Surface *s, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t col) +{ + raster_aalineColorInt(s, x1, y1, x2, y2, col, 1); +} + + + +/* raster :: circle */ + +void raster_circle(SDL_Surface *dst, int16_t x, int16_t y, int16_t r, uint32_t color) +{ + /* sdl-gfx */ + Sint16 left, right, top, bottom; + int result; + Sint16 x1, y1, x2, y2; + Sint16 cx = 0; + Sint16 cy = r; + Sint16 ocx = (Sint16) 0xffff; + Sint16 ocy = (Sint16) 0xffff; + Sint16 df = 1 - r; + Sint16 d_e = 3; + Sint16 d_se = -2 * r + 5; + Sint16 xpcx, xmcx, xpcy, xmcy; + Sint16 ypcy, ymcy, ypcx, ymcx; + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return; + } + + /* + * Sanity check radius + */ + if (r < 0) { + return; + } + + /* + * Special case for r=0 - draw a point + */ + if (r == 0) { + return (raster_PutPixel(dst, x, y, color)); + } + + /* + * Get circle and clipping boundary and + * test if bounding box of circle is visible + */ + x2 = x + r; + left = dst->clip_rect.x; + if (x2<left) { + return; + } + x1 = x - r; + right = dst->clip_rect.x + dst->clip_rect.w - 1; + if (x1>right) { + return; + } + y2 = y + r; + top = dst->clip_rect.y; + if (y2<top) { + return; + } + y1 = y - r; + bottom = dst->clip_rect.y + dst->clip_rect.h - 1; + if (y1>bottom) { + return; + } + + /* + * Draw + */ + result = 0; + do { + xpcx = x + cx; + xmcx = x - cx; + xpcy = x + cy; + xmcy = x - cy; + if (ocy != cy) { + if (cy > 0) { + ypcy = y + cy; + ymcy = y - cy; + raster_hline(dst, xmcx, xpcx, ypcy, color); + raster_hline(dst, xmcx, xpcx, ymcy, color); +// raster_rect_inline(dst, xmcx, ypcy, 2*cx, 1, color); +// raster_rect_inline(dst, xmcx, ymcy, 2*cx, 1, color); + + } else { + raster_hline(dst, xmcx, xpcx, y, color); +// raster_rect_inline(dst, xmcx, y, 2*cx, 1, color); + } + ocy = cy; + } + if (ocx != cx) { + if (cx != cy) { + if (cx > 0) { + ypcx = y + cx; + ymcx = y - cx; + raster_hline(dst, xmcy, xpcy, ymcx, color); + raster_hline(dst, xmcy, xpcy, ypcx, color); + //raster_rect_inline(dst, xmcy, ymcx, 2*cy, 1, color); + //raster_rect_inline(dst, xmcy, ypcx, 2*cy, 1, color); + } else { + raster_hline(dst, xmcy, xpcy, y, color); + //raster_rect_inline(dst, xmcy, y, 2*cy, 1, color); + } + } + ocx = cx; + } + /* + * Update + */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while (cx <= cy); +} + + +/* FIXME: convert to fixed pt */ +static void raster_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color) +{ + /* sge */ + /* Sanity check */ + if (rx < 1) + rx = 1; + if (ry < 1) + ry = 1; + + int a2 = rx * rx; + int b2 = ry * ry; + + int ds = 2 * a2; + int dt = 2 * b2; + + int dxt = (int)(a2 / sqrt(a2 + b2)); + + int t = 0; + int s = -2 * a2 * ry; + int d = 0; + + Sint16 x = xc; + Sint16 y = yc - ry; + + Sint16 xs, ys, dyt; + float cp, is, ip, imax = 1.0; + + /* Lock surface */ + if ( SDL_MUSTLOCK(surface) ) + if ( SDL_LockSurface(surface) < 0 ) + return; + + /* "End points" */ + raster_PutPixel(surface, x, y, color); + raster_PutPixel(surface, 2*xc-x, y, color); + + raster_PutPixel(surface, x, 2*yc-y, color); + raster_PutPixel(surface, 2*xc-x, 2*yc-y, color); + + /* unlock surface */ + if (SDL_MUSTLOCK(surface) ) + SDL_UnlockSurface(surface); + + raster_vline(surface, x, y+1, 2*yc-y-1, color); + + int i; + + for (i = 1; i <= dxt; i++) + { + x--; + d += t - b2; + + if (d >= 0) + ys = y - 1; + else if ((d - s - a2) > 0) + { + if ((2 * d - s - a2) >= 0) + ys = y + 1; + else + { + ys = y; + y++; + d -= s + a2; + s += ds; + } + } + else + { + y++; + ys = y + 1; + d -= s + a2; + s += ds; + } + + t -= dt; + + /* Calculate alpha */ + cp = (float) abs(d) / abs(s); + is = cp * imax; + ip = imax - is; + + + /* Lock surface */ + if ( SDL_MUSTLOCK(surface) ) + if ( SDL_LockSurface(surface) < 0 ) + return; + + /* Upper half */ + raster_PutPixelAlpha(surface, x, y, color, (Uint8)(ip*255)); + raster_PutPixelAlpha(surface, 2*xc-x, y, color, (Uint8)(ip*255)); + + raster_PutPixelAlpha(surface, x, ys, color, (Uint8)(is*255)); + raster_PutPixelAlpha(surface, 2*xc-x, ys, color, (Uint8)(is*255)); + + + /* Lower half */ + raster_PutPixelAlpha(surface, x, 2*yc-y, color, (Uint8)(ip*255)); + raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, (Uint8)(ip*255)); + + raster_PutPixelAlpha(surface, x, 2*yc-ys, color, (Uint8)(is*255)); + raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-ys, color, (Uint8)(is*255)); + + /* unlock surface */ + if (SDL_MUSTLOCK(surface) ) + SDL_UnlockSurface(surface); + + + /* Fill */ + raster_vline(surface, x, y+1, 2*yc-y-1, color); + raster_vline(surface, 2*xc-x, y+1, 2*yc-y-1, color); + raster_vline(surface, x, ys+1, 2*yc-ys-1, color); + raster_vline(surface, 2*xc-x, ys+1, 2*yc-ys-1, color); + } + + dyt = abs(y - yc); + + for (i = 1; i <= dyt; i++) + { + y++; + d -= s + a2; + + if (d <= 0) + xs = x + 1; + else if ((d + t - b2) < 0) + { + if ((2 * d + t - b2) <= 0) + xs = x - 1; + else + { + xs = x; + x--; + d += t - b2; + t -= dt; + } + } + else + { + x--; + xs = x - 1; + d += t - b2; + t -= dt; + } + + s += ds; + + /* Calculate alpha */ + cp = (float) abs(d) / abs(t); + is = cp * imax; + ip = imax - is; + + + /* Lock surface */ + if ( SDL_MUSTLOCK(surface) ) + if ( SDL_LockSurface(surface) < 0 ) + return; + + /* Upper half */ + raster_PutPixelAlpha(surface, x, y, color, (Uint8)(ip*255)); + raster_PutPixelAlpha(surface, 2*xc-x, y, color, (Uint8)(ip*255)); + + raster_PutPixelAlpha(surface, xs, y, color, (Uint8)(is*255)); + raster_PutPixelAlpha(surface, 2*xc-xs, y, color, (Uint8)(is*255)); + + + /* Lower half*/ + raster_PutPixelAlpha(surface, x, 2*yc-y, color, (Uint8)(ip*255)); + raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, (Uint8)(ip*255)); + + raster_PutPixelAlpha(surface, xs, 2*yc-y, color, (Uint8)(is*255)); + raster_PutPixelAlpha(surface, 2*xc-xs, 2*yc-y, color, (Uint8)(is*255)); + + /* unlock surface */ + if (SDL_MUSTLOCK(surface) ) + SDL_UnlockSurface(surface); + + /* Fill */ + raster_hline(surface, x+1, 2*xc-x-1, y, color); + raster_hline(surface, xs+1, 2*xc-xs-1, y, color); + raster_hline(surface, x+1, 2*xc-x-1, 2*yc-y, color); + raster_hline(surface, xs+1, 2*xc-xs-1, 2*yc-y, color); + } +} + +void raster_aacircle(SDL_Surface *s, int16_t x, int16_t y, int16_t r, uint32_t col) +{ + raster_AAFilledEllipse(s, x, y, r, r, col); +} + +#if 0 +void raster_aacircle(SDL_Surface *s, int16_t x, int16_t y, int16_t r, uint32_t col) +{ + /* sdl-gfx */ + Sint16 left, right, top, bottom; + int result; + Sint16 x1, y1, x2, y2; + Sint16 cx = 0; + Sint16 cy = r; + Sint16 ocx = (Sint16) 0xffff; + Sint16 ocy = (Sint16) 0xffff; + Sint16 df = 1 - r; + Sint16 d_e = 3; + Sint16 d_se = -2 * r + 5; + Sint16 xpcx, xmcx, xpcy, xmcy; + Sint16 ypcy, ymcy, ypcx, ymcx; + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return; + } + + /* + * Sanity check radius + */ + if (r < 0) { + return; + } + +#if 0 + /* + * Special case for r=0 - draw a point + */ + if (r == 0) { + return (pixelColor(dst, x, y, color)); + } +#endif + + /* + * Get circle and clipping boundary and + * test if bounding box of circle is visible + */ + x2 = x + r; + left = dst->clip_rect.x; + if (x2<left) { + return; + } + x1 = x - r; + right = dst->clip_rect.x + dst->clip_rect.w - 1; + if (x1>right) { + return; + } + y2 = y + r; + top = dst->clip_rect.y; + if (y2<top) { + return; + } + y1 = y - r; + bottom = dst->clip_rect.y + dst->clip_rect.h - 1; + if (y1>bottom) { + return; + } + + /* + * Draw + */ + result = 0; + do { + xpcx = x + cx; + xmcx = x - cx; + xpcy = x + cy; + xmcy = x - cy; + if (ocy != cy) { + if (cy > 0) { + ypcy = y + cy; + ymcy = y - cy; + raster_hlineColor(dst, xmcx, xpcx, ypcy, color); + raster_hlineColor(dst, xmcx, xpcx, ymcy, color); +// raster_rect_inline(dst, xmcx, ypcy, 2*cx, 1, color); +// raster_rect_inline(dst, xmcx, ymcy, 2*cx, 1, color); + + } else { + raster_hlineColor(dst, xmcx, xpcx, y, color); +// raster_rect_inline(dst, xmcx, y, 2*cx, 1, color); + } + ocy = cy; + } + if (ocx != cx) { + if (cx != cy) { + if (cx > 0) { + ypcx = y + cx; + ymcx = y - cx; + raster_hlineColor(dst, xmcy, xpcy, ymcx, color); + raster_hlineColor(dst, xmcy, xpcy, ypcx, color); + //raster_rect_inline(dst, xmcy, ymcx, 2*cy, 1, color); + //raster_rect_inline(dst, xmcy, ypcx, 2*cy, 1, color); + } else { + raster_hlineColor(dst, xmcy, xpcy, y, color); + //raster_rect_inline(dst, xmcy, y, 2*cy, 1, color); + } + } + ocx = cx; + } + /* + * Update + */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while (cx <= cy); +#if 0 + /* sge */ + Sint16 cx = 0; + Sint16 cy = r; + int draw=1; + Sint16 df = 1 - r; + Sint16 d_e = 3; + Sint16 d_se = -2 * r + 5; + +#ifdef DEBUG + printf("raster_circle %d %d %d\n", x, y, r); +#endif + + if(r < 0) + { + return; + } + + do { + if(draw) + { + raster_rect_inline(s, x-cx, y+cy, 2*cx, 1, col); + raster_rect_inline(s, x-cx, y-cy, 2*cx, 1, col); + draw=0; + } + if(cx!=cy) + { + if(cx) + { + raster_rect_inline(s, x-cy, y-cx, 2*cy, 1, col); + raster_rect_inline(s, x-cy, y+cx, 2*cy, 1, col); + } + else + { + raster_rect_inline(s, x-cy, y, 2*cy, 1, col); + } + } + + if (df < 0) + { + df += d_e; + d_e += 2; + d_se += 2; + } + else + { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + draw=1; + } + cx++; + } while(cx <= cy); +#endif +} +#endif + + + +/* raster :: poly */ + + +/* ---- Filled Polygon */ + +/* Helper qsort callback for polygon drawing */ + +static int gfxPrimitivesCompareInt(const void *a, const void *b) +{ + return (*(const int *) a) - (*(const int *) b); +} + + +/* Global vertex array to use if optional parameters are not given in polygon calls. */ +static int *gfxPrimitivesPolyIntsGlobal = NULL; +static int gfxPrimitivesPolyAllocatedGlobal = 0; + +/* (Note: The last two parameters are optional; but required for multithreaded operation.) */ + +static inline int raster_filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated) +{ + /* sdl-gfx */ + int result; + int i; + int y, xa, xb; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *gfxPrimitivesPolyInts = NULL; + int gfxPrimitivesPolyAllocated = 0; + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return(0); + } + + /* + * Sanity check number of edges + */ + if (n < 3) { + return -1; + } + + /* + * Map polygon cache + */ + if ((polyInts==NULL) || (polyAllocated==NULL)) { + /* Use global cache */ + gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; + gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; + } else { + /* Use local cache */ + gfxPrimitivesPolyInts = *polyInts; + gfxPrimitivesPolyAllocated = *polyAllocated; + } + + /* + * Allocate temp array, only grow array + */ + if (!gfxPrimitivesPolyAllocated) { + gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); + gfxPrimitivesPolyAllocated = n; + } else { + if (gfxPrimitivesPolyAllocated < n) { + gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); + gfxPrimitivesPolyAllocated = n; + } + } + + /* + * Check temp array + */ + if (gfxPrimitivesPolyInts==NULL) { + gfxPrimitivesPolyAllocated = 0; + } + + /* + * Update cache variables + */ + if ((polyInts==NULL) || (polyAllocated==NULL)) { + gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; + gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; + } else { + *polyInts = gfxPrimitivesPolyInts; + *polyAllocated = gfxPrimitivesPolyAllocated; + } + + /* + * Check temp array again + */ + if (gfxPrimitivesPolyInts==NULL) { + return(-1); + } + + /* + * Determine Y maxima + */ + miny = vy[0]; + maxy = vy[0]; + for (i = 1; (i < n); i++) { + if (vy[i] < miny) { + miny = vy[i]; + } else if (vy[i] > maxy) { + maxy = vy[i]; + } + } + + /* + * Draw, scanning y + */ + result = 0; + for (y = miny; (y <= maxy); y++) { + ints = 0; + for (i = 0; (i < n); i++) { + if (!i) { + ind1 = n - 1; + ind2 = 0; + } else { + ind1 = i - 1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) { + x1 = vx[ind1]; + x2 = vx[ind2]; + } else if (y1 > y2) { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } else { + continue; + } + if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) { + gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); + } + } + + qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt); + + for (i = 0; (i < ints); i += 2) { + xa = gfxPrimitivesPolyInts[i] + 1; + xa = (xa >> 16) + ((xa & 32768) >> 15); + xb = gfxPrimitivesPolyInts[i+1] - 1; + xb = (xb >> 16) + ((xb & 32768) >> 15); + raster_hline(dst, xa, xb, y, color); +// raster_rect_inline(dst, xa, y, xb - xa, 1, color); + } + } + + return (result); +} + +void raster_polygon(SDL_Surface *s, int16_t n, int16_t *vx, int16_t *vy, uint32_t col) +{ + raster_filledPolygonColorMT(s, vx, vy, n, col, NULL, NULL); +} + + +void raster_aapolygon(SDL_Surface *dst, int16_t n, int16_t *vx, int16_t *vy, uint32_t color) +{ + /* sdl-gfx + sge w/ rphlx changes: basically, draw aaline border, + then fill. + + the output is not perfect yet but usually looks better than aliasing + */ + int result; + int i; + int y, xa, xb; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *gfxPrimitivesPolyInts = NULL; + int gfxPrimitivesPolyAllocated = 0; + const Sint16 *px1, *py1, *px2, *py2; + int **polyInts; + int *polyAllocated; + + polyInts = NULL; + polyAllocated = NULL; + + /* + * Check visibility of clipping rectangle + */ + if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { + return; + } + + /* + * Sanity check number of edges + */ + if (n < 3) { + return; + } + + + /* + * Pointer setup + */ + px1 = px2 = vx; + py1 = py2 = vy; + px2++; + py2++; + + /* + * Draw + */ + result = 0; + for (i = 1; i < n; i++) { + raster_aalineColorInt(dst, *px1, *py1, *px2, *py2, color, 0); + px1 = px2; + py1 = py2; + px2++; + py2++; + } + raster_aalineColorInt(dst, *px1, *py1, *vx, *vy, color, 0); + + /* + * Map polygon cache + */ + if ((polyInts==NULL) || (polyAllocated==NULL)) { + /* Use global cache */ + gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; + gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; + } else { + /* Use local cache */ + gfxPrimitivesPolyInts = *polyInts; + gfxPrimitivesPolyAllocated = *polyAllocated; + } + + /* + * Allocate temp array, only grow array + */ + if (!gfxPrimitivesPolyAllocated) { + gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); + gfxPrimitivesPolyAllocated = n; + } else { + if (gfxPrimitivesPolyAllocated < n) { + gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); + gfxPrimitivesPolyAllocated = n; + } + } + + /* + * Check temp array + */ + if (gfxPrimitivesPolyInts==NULL) { + gfxPrimitivesPolyAllocated = 0; + } + + /* + * Update cache variables + */ + if ((polyInts==NULL) || (polyAllocated==NULL)) { + gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; + gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; + } else { + *polyInts = gfxPrimitivesPolyInts; + *polyAllocated = gfxPrimitivesPolyAllocated; + } + + /* + * Check temp array again + */ + if (gfxPrimitivesPolyInts==NULL) { + return; + } + + /* + * Determine Y maxima + */ + miny = vy[0]; + maxy = vy[0]; + for (i = 1; (i < n); i++) { + if (vy[i] < miny) { + miny = vy[i]; + } else if (vy[i] > maxy) { + maxy = vy[i]; + } + } + + /* + * Draw, scanning y + */ + result = 0; + for (y = miny; (y <= maxy); y++) { + ints = 0; + for (i = 0; (i < n); i++) { + if (!i) { + ind1 = n - 1; + ind2 = 0; + } else { + ind1 = i - 1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) { + x1 = vx[ind1]; + x2 = vx[ind2]; + } else if (y1 > y2) { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } else { + continue; + } + if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) { + gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); + } + } + + qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt); + +// o = p = -1; + for (i = 0; (i < ints); i +=2) { +#if 0 + xa = gfxPrimitivesPolyInts[i] + 1; + xa = (xa >> 16) + ((xa & 32768) >> 15); + xb = gfxPrimitivesPolyInts[i+1] - 1; + xb = (xb >> 16) + ((xb & 32768) >> 15); +#else + xa = (gfxPrimitivesPolyInts[i] >> 16); + xb = (gfxPrimitivesPolyInts[i+1] >> 16); +#endif + +#if 0 + if(o < 0) + { + o = xa+1; + } + else if(p < 0) + { + p = xa; + } + + if( (o >= 0) && (p >= 0)) + { + if(p-o < 0) + { + o = p = -1; + continue; + } + + raster_hlineColor(dst, o, p, y, color); + + o = p = -1; + } +#else + + raster_hline(dst, xa+1, xb, y, color); +#endif + +// raster_rect_inline(dst, xa, y, xb - xa, 1, color); + } + } +} + |