Logo Search packages:      
Sourcecode: navit version File versions

raster.c

/* 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);
      }
    }
}


Generated by  Doxygen 1.6.0   Back to index