Atrinik Client 2.5
toolkit/SDL_gfx.c
00001 /*
00002 
00003 SDL_gfxPrimitives - Graphics primitives for SDL surfaces
00004 
00005 LGPL (c) A. Schiffler
00006 
00007 */
00008 
00009 #include <global.h>
00010 
00011 /* -===================- */
00012 
00013 #define DEFAULT_ALPHA_PIXEL_ROUTINE
00014 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00015 
00016 /* ---- Structures */
00017 
00021 typedef struct {
00022     Sint16 x, y;
00023     int dx, dy, s1, s2, swapdir, error;
00024     Uint32 count;
00025 } SDL_gfxBresenhamIterator;
00026 
00030 typedef struct {
00031     Uint32 color;
00032     SDL_Surface *dst;
00033     int u, v;       /* delta x , delta y */
00034     int ku, kt, kv, kd; /* loop constants */
00035     int oct2;
00036     int quad4;
00037     Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
00038 } SDL_gfxMurphyIterator;
00039 
00040 /* ----- Defines for pixel clipping tests */
00041 
00042 
00061 static int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2)
00062 {
00063     int temp;
00064 
00065     if (b==NULL) {
00066         return(-1);
00067     }
00068 
00069     b->x = x;
00070     b->y = y;
00071 
00072     /* dx = abs(x2-x1), s1 = sign(x2-x1) */
00073     if ((b->dx = x2 - x) != 0) {
00074         if (b->dx < 0) {
00075             b->dx = -b->dx;
00076             b->s1 = -1;
00077         } else {
00078             b->s1 = 1;
00079         }
00080     } else {
00081         b->s1 = 0;
00082     }
00083 
00084     /* dy = abs(y2-y1), s2 = sign(y2-y1)    */
00085     if ((b->dy = y2 - y) != 0) {
00086         if (b->dy < 0) {
00087             b->dy = -b->dy;
00088             b->s2 = -1;
00089         } else {
00090             b->s2 = 1;
00091         }
00092     } else {
00093         b->s2 = 0;
00094     }
00095 
00096     if (b->dy > b->dx) {
00097         temp = b->dx;
00098         b->dx = b->dy;
00099         b->dy = temp;
00100         b->swapdir = 1;
00101     } else {
00102         b->swapdir = 0;
00103     }
00104 
00105     b->count = b->dx;
00106     b->dy <<= 1;
00107     b->error = b->dy - b->dx;
00108     b->dx <<= 1;
00109 
00110     return(0);
00111 }
00112 
00113 
00123 static int _bresenhamIterate(SDL_gfxBresenhamIterator *b)
00124 {
00125     if (b==NULL) {
00126         return (-1);
00127     }
00128 
00129     /* last point check */
00130     if (b->count <= 0) {
00131         return (2);
00132     }
00133 
00134     while (b->error >= 0) {
00135         if (b->swapdir) {
00136             b->x += b->s1;
00137         } else  {
00138             b->y += b->s2;
00139         }
00140 
00141         b->error -= b->dx;
00142     }
00143 
00144     if (b->swapdir) {
00145         b->y += b->s2;
00146     } else {
00147         b->x += b->s1;
00148     }
00149 
00150     b->error += b->dy;
00151     b->count--;
00152 
00153     /* count==0 indicates "end-of-line" */
00154     return ((b->count) ? 0 : 1);
00155 }
00156 
00157 
00167 #define clip_xmin(surface) surface->clip_rect.x
00168 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
00169 #define clip_ymin(surface) surface->clip_rect.y
00170 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
00171 
00182 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00183 {
00184     int bpp;
00185     Uint8 *p;
00186 
00187     /*
00188     * Honor clipping setup at pixel level
00189     */
00190     if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
00191 
00192         /*
00193         * Get destination format
00194         */
00195         bpp = dst->format->BytesPerPixel;
00196         p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00197         switch (bpp) {
00198     case 1:
00199         *p = color;
00200         break;
00201     case 2:
00202         *(Uint16 *) p = color;
00203         break;
00204     case 3:
00205         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00206             p[0] = (color >> 16) & 0xff;
00207             p[1] = (color >> 8) & 0xff;
00208             p[2] = color & 0xff;
00209         } else {
00210             p[0] = color & 0xff;
00211             p[1] = (color >> 8) & 0xff;
00212             p[2] = (color >> 16) & 0xff;
00213         }
00214         break;
00215     case 4:
00216         *(Uint32 *) p = color;
00217         break;
00218         }           /* switch */
00219 
00220 
00221     }
00222 
00223     return (0);
00224 }
00225 
00239 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00240 {
00241     int bpp;
00242     Uint8 *p;
00243 
00244     /*
00245     * Get destination format
00246     */
00247     bpp = dst->format->BytesPerPixel;
00248     p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00249     switch (bpp) {
00250     case 1:
00251         *p = color;
00252         break;
00253     case 2:
00254         *(Uint16 *) p = color;
00255         break;
00256     case 3:
00257         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00258             p[0] = (color >> 16) & 0xff;
00259             p[1] = (color >> 8) & 0xff;
00260             p[2] = color & 0xff;
00261         } else {
00262             p[0] = color & 0xff;
00263             p[1] = (color >> 8) & 0xff;
00264             p[2] = (color >> 16) & 0xff;
00265         }
00266         break;
00267     case 4:
00268         *(Uint32 *) p = color;
00269         break;
00270     }               /* switch */
00271 
00272     return (0);
00273 }
00274 
00285 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00286 {
00287     int result;
00288 
00289     /*
00290     * Lock the surface
00291     */
00292     if (SDL_MUSTLOCK(dst)) {
00293         if (SDL_LockSurface(dst) < 0) {
00294             return (-1);
00295         }
00296     }
00297 
00298     result = fastPixelColorNolock(dst, x, y, color);
00299 
00300     /*
00301     * Unlock surface
00302     */
00303     if (SDL_MUSTLOCK(dst)) {
00304         SDL_UnlockSurface(dst);
00305     }
00306 
00307     return (result);
00308 }
00309 
00323 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00324 {
00325     Uint32 color;
00326 
00327     /*
00328     * Setup color
00329     */
00330     color = SDL_MapRGBA(dst->format, r, g, b, a);
00331 
00332     /*
00333     * Draw
00334     */
00335     return (fastPixelColor(dst, x, y, color));
00336 }
00337 
00351 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00352 {
00353     Uint32 color;
00354 
00355     /*
00356     * Setup color
00357     */
00358     color = SDL_MapRGBA(dst->format, r, g, b, a);
00359 
00360     /*
00361     * Draw
00362     */
00363     return (fastPixelColorNolock(dst, x, y, color));
00364 }
00365 
00381 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
00382 {
00383     SDL_PixelFormat *format;
00384     Uint32 Rmask, Gmask, Bmask, Amask;
00385     Uint32 Rshift, Gshift, Bshift, Ashift;
00386     Uint32 R, G, B, A;
00387 
00388     if (dst == NULL)
00389     {
00390         return (-1);
00391     }
00392 
00393     if (x >= clip_xmin(dst) && x <= clip_xmax(dst) &&
00394         y >= clip_ymin(dst) && y <= clip_ymax(dst))
00395     {
00396 
00397         format = dst->format;
00398 
00399         switch (format->BytesPerPixel) {
00400     case 1:
00401         {       /* Assuming 8-bpp */
00402             if (alpha == 255) {
00403                 *((Uint8 *) dst->pixels + y * dst->pitch + x) = color;
00404             } else {
00405                 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
00406                 SDL_Palette *palette = format->palette;
00407                 SDL_Color *colors = palette->colors;
00408                 SDL_Color dColor = colors[*pixel];
00409                 SDL_Color sColor = colors[color];
00410                 Uint8 dR = dColor.r;
00411                 Uint8 dG = dColor.g;
00412                 Uint8 dB = dColor.b;
00413                 Uint8 sR = sColor.r;
00414                 Uint8 sG = sColor.g;
00415                 Uint8 sB = sColor.b;
00416 
00417                 dR = dR + ((sR - dR) * alpha >> 8);
00418                 dG = dG + ((sG - dG) * alpha >> 8);
00419                 dB = dB + ((sB - dB) * alpha >> 8);
00420 
00421                 *pixel = SDL_MapRGB(format, dR, dG, dB);
00422             }
00423         }
00424         break;
00425 
00426     case 2:
00427         {       /* Probably 15-bpp or 16-bpp */
00428             if (alpha == 255) {
00429                 *((Uint16 *) dst->pixels + y * dst->pitch / 2 + x) = color;
00430             } else {
00431                 Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
00432                 Uint32 dc = *pixel;
00433 
00434                 Rmask = format->Rmask;
00435                 Gmask = format->Gmask;
00436                 Bmask = format->Bmask;
00437                 Amask = format->Amask;
00438                 R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
00439                 G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
00440                 B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
00441                 A = 255;
00442                 if (Amask) {
00443                     A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
00444                 }
00445                 *pixel = R | G | B | A;
00446             }
00447         }
00448         break;
00449 
00450     case 3:
00451         {       /* Slow 24-bpp mode, usually not used */
00452             Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
00453             Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
00454 
00455             Rshift = format->Rshift;
00456             Gshift = format->Gshift;
00457             Bshift = format->Bshift;
00458             Ashift = format->Ashift;
00459 
00460             Rshift8 = Rshift / 8;
00461             Gshift8 = Gshift / 8;
00462             Bshift8 = Bshift / 8;
00463             Ashift8 = Ashift / 8;
00464 
00465             if (alpha == 255) {
00466                 *(pixel + Rshift8) = color >> Rshift;
00467                 *(pixel + Gshift8) = color >> Gshift;
00468                 *(pixel + Bshift8) = color >> Bshift;
00469                 *(pixel + Ashift8) = color >> Ashift;
00470             } else {
00471                 Uint8 dR, dG, dB, dA = 0;
00472                 Uint8 sR, sG, sB, sA = 0;
00473 
00474                 dR = *((pixel) + Rshift8);
00475                 dG = *((pixel) + Gshift8);
00476                 dB = *((pixel) + Bshift8);
00477                 dA = *((pixel) + Ashift8);
00478 
00479                 sR = (color >> Rshift) & 0xff;
00480                 sG = (color >> Gshift) & 0xff;
00481                 sB = (color >> Bshift) & 0xff;
00482                 sA = (color >> Ashift) & 0xff;
00483 
00484                 dR = dR + ((sR - dR) * alpha >> 8);
00485                 dG = dG + ((sG - dG) * alpha >> 8);
00486                 dB = dB + ((sB - dB) * alpha >> 8);
00487                 dA = dA + ((sA - dA) * alpha >> 8);
00488 
00489                 *((pixel) + Rshift8) = dR;
00490                 *((pixel) + Gshift8) = dG;
00491                 *((pixel) + Bshift8) = dB;
00492                 *((pixel) + Ashift8) = dA;
00493             }
00494         }
00495         break;
00496 
00497 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
00498 
00499     case 4:
00500         {       /* Probably :-) 32-bpp */
00501             if (alpha == 255) {
00502                 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
00503             } else {
00504                 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
00505                 Uint32 dc = *pixel;
00506 
00507                 Rmask = format->Rmask;
00508                 Gmask = format->Gmask;
00509                 Bmask = format->Bmask;
00510                 Amask = format->Amask;
00511 
00512                 Rshift = format->Rshift;
00513                 Gshift = format->Gshift;
00514                 Bshift = format->Bshift;
00515                 Ashift = format->Ashift;
00516 
00517                 A = 0;
00518                 R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
00519                 G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
00520                 B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
00521                 if (Amask) {
00522                     A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
00523                 }
00524                 *pixel = R | G | B | A;
00525             }
00526         }
00527         break;
00528 #endif
00529 
00530 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00531 
00532     case 4:{        /* Probably :-) 32-bpp */
00533         if (alpha == 255) {
00534             *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
00535         } else {
00536             Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
00537             Uint32 dR, dG, dB, dA;
00538             Uint32 dc = *pixel;
00539 
00540             Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
00541             Uint32 aTmp;
00542 
00543             Rmask = format->Rmask;
00544             Gmask = format->Gmask;
00545             Bmask = format->Bmask;
00546             Amask = format->Amask;
00547 
00548             dR = (color & Rmask);
00549             dG = (color & Gmask);
00550             dB = (color & Bmask);
00551             dA = (color & Amask);
00552 
00553             Rshift = format->Rshift;
00554             Gshift = format->Gshift;
00555             Bshift = format->Bshift;
00556             Ashift = format->Ashift;
00557 
00558             preMultR = (alpha * (dR >> Rshift));
00559             preMultG = (alpha * (dG >> Gshift));
00560             preMultB = (alpha * (dB >> Bshift));
00561 
00562             surfaceAlpha = ((dc & Amask) >> Ashift);
00563             aTmp = (255 - alpha);
00564             if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
00565                 aTmp *= surfaceAlpha;
00566                 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
00567                 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
00568                 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
00569             }
00570             *pixel = R | G | B | (A << Ashift & Amask);
00571 
00572         }
00573            }
00574            break;
00575 #endif
00576         }
00577     }
00578 
00579     return (0);
00580 }
00581 
00592 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00593 {
00594     Uint8 alpha;
00595     Uint32 mcolor;
00596     int result = 0;
00597 
00598     /*
00599     * Lock the surface
00600     */
00601     if (SDL_MUSTLOCK(dst)) {
00602         if (SDL_LockSurface(dst) < 0) {
00603             return (-1);
00604         }
00605     }
00606 
00607     /*
00608     * Setup color
00609     */
00610     alpha = color & 0x000000ff;
00611     mcolor =
00612         SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00613         (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00614 
00615     /*
00616     * Draw
00617     */
00618     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00619 
00620     /*
00621     * Unlock the surface
00622     */
00623     if (SDL_MUSTLOCK(dst)) {
00624         SDL_UnlockSurface(dst);
00625     }
00626 
00627     return (result);
00628 }
00629 
00640 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00641 {
00642     Uint8 alpha;
00643     Uint32 mcolor;
00644     int result = 0;
00645 
00646     /*
00647     * Setup color
00648     */
00649     alpha = color & 0x000000ff;
00650     mcolor =
00651         SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00652         (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00653 
00654     /*
00655     * Draw
00656     */
00657     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00658 
00659     return (result);
00660 }
00661 
00662 
00678 int _filledRectAlpha(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
00679 {
00680     SDL_PixelFormat *format;
00681     Uint32 Rmask, Bmask, Gmask, Amask;
00682     Uint32 Rshift, Bshift, Gshift, Ashift;
00683     Uint8 sR, sG, sB, sA;
00684     Uint32 R, G, B, A;
00685     Sint16 x, y;
00686 
00687     format = dst->format;
00688     switch (format->BytesPerPixel) {
00689     case 1:
00690         {           /* Assuming 8-bpp */
00691             Uint8 *row, *pixel;
00692             Uint8 dR, dG, dB;
00693             SDL_Palette *palette = format->palette;
00694             SDL_Color *colors = palette->colors;
00695             sR = colors[color].r;
00696             sG = colors[color].g;
00697             sB = colors[color].b;
00698 
00699             for (y = yy; y <= y2; y++) {
00700                 row = (Uint8 *) dst->pixels + y * dst->pitch;
00701                 for (x = xx; x <= x2; x++) {
00702                     pixel = row + x;
00703 
00704                     dR = colors[*pixel].r;
00705                     dG = colors[*pixel].g;
00706                     dB = colors[*pixel].b;
00707 
00708                     dR = dR + ((sR - dR) * alpha >> 8);
00709                     dG = dG + ((sG - dG) * alpha >> 8);
00710                     dB = dB + ((sB - dB) * alpha >> 8);
00711 
00712                     *pixel = SDL_MapRGB(format, dR, dG, dB);
00713                 }
00714             }
00715         }
00716         break;
00717 
00718     case 2:
00719         {           /* Probably 15-bpp or 16-bpp */
00720             Uint16 *row, *pixel;
00721             Uint32 dR, dG, dB, dA;
00722             Rmask = format->Rmask;
00723             Gmask = format->Gmask;
00724             Bmask = format->Bmask;
00725             Amask = format->Amask;
00726 
00727             dR = (color & Rmask);
00728             dG = (color & Gmask);
00729             dB = (color & Bmask);
00730             dA = (color & Amask);
00731 
00732             A = 0;
00733 
00734             for (y = yy; y <= y2; y++) {
00735                 row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
00736                 for (x = xx; x <= x2; x++) {
00737                     pixel = row + x;
00738 
00739                     R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
00740                     G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
00741                     B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
00742                     if (Amask)
00743                     {
00744                         A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
00745                         *pixel = R | G | B | A;
00746                     } else {
00747                         *pixel = R | G | B;
00748                     }
00749                 }
00750             }
00751         }
00752         break;
00753 
00754     case 3:
00755         {           /* Slow 24-bpp mode, usually not used */
00756             Uint8 *row, *pix;
00757             Uint8 dR, dG, dB, dA;
00758             Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
00759 
00760             Rshift = format->Rshift;
00761             Gshift = format->Gshift;
00762             Bshift = format->Bshift;
00763             Ashift = format->Ashift;
00764 
00765             Rshift8 = Rshift / 8;
00766             Gshift8 = Gshift / 8;
00767             Bshift8 = Bshift / 8;
00768             Ashift8 = Ashift / 8;
00769 
00770             sR = (color >> Rshift) & 0xff;
00771             sG = (color >> Gshift) & 0xff;
00772             sB = (color >> Bshift) & 0xff;
00773             sA = (color >> Ashift) & 0xff;
00774 
00775             for (y = yy; y <= y2; y++) {
00776                 row = (Uint8 *) dst->pixels + y * dst->pitch;
00777                 for (x = xx; x <= x2; x++) {
00778                     pix = row + x * 3;
00779 
00780                     dR = *((pix) + Rshift8);
00781                     dG = *((pix) + Gshift8);
00782                     dB = *((pix) + Bshift8);
00783                     dA = *((pix) + Ashift8);
00784 
00785                     dR = dR + ((sR - dR) * alpha >> 8);
00786                     dG = dG + ((sG - dG) * alpha >> 8);
00787                     dB = dB + ((sB - dB) * alpha >> 8);
00788                     dA = dA + ((sA - dA) * alpha >> 8);
00789 
00790                     *((pix) + Rshift8) = dR;
00791                     *((pix) + Gshift8) = dG;
00792                     *((pix) + Bshift8) = dB;
00793                     *((pix) + Ashift8) = dA;
00794                 }
00795             }
00796         }
00797         break;
00798 
00799 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
00800     case 4:
00801         {           /* Probably :-) 32-bpp */
00802             Uint32 *row, *pixel;
00803             Uint32 dR, dG, dB, dA;
00804 
00805             Rmask = format->Rmask;
00806             Gmask = format->Gmask;
00807             Bmask = format->Bmask;
00808             Amask = format->Amask;
00809 
00810             Rshift = format->Rshift;
00811             Gshift = format->Gshift;
00812             Bshift = format->Bshift;
00813             Ashift = format->Ashift;
00814 
00815             dR = (color & Rmask);
00816             dG = (color & Gmask);
00817             dB = (color & Bmask);
00818             dA = (color & Amask);
00819 
00820             for (y = yy; y <= y2; y++) {
00821                 row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
00822                 for (x = xx; x <= x2; x++) {
00823                     pixel = row + x;
00824 
00825                     R = ((*pixel & Rmask) + ((((dR - (*pixel & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
00826                     G = ((*pixel & Gmask) + ((((dG - (*pixel & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
00827                     B = ((*pixel & Bmask) + ((((dB - (*pixel & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
00828                     if (Amask)
00829                     {
00830                         A = ((*pixel & Amask) + ((((dA - (*pixel & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
00831                         *pixel = R | G | B | A;
00832                     } else {
00833                         *pixel = R | G | B;
00834                     }
00835                 }
00836             }
00837         }
00838         break;
00839 #endif
00840 
00841 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00842     case 4:{            /* Probably :-) 32-bpp */
00843         Uint32 *row, *pixel;
00844         Uint32 dR, dG, dB, dA;
00845         Uint32 dc;
00846         Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
00847         Uint32 aTmp;
00848 
00849         Rmask = format->Rmask;
00850         Gmask = format->Gmask;
00851         Bmask = format->Bmask;
00852         Amask = format->Amask;
00853 
00854         dR = (color & Rmask);
00855         dG = (color & Gmask);
00856         dB = (color & Bmask);
00857         dA = (color & Amask);
00858 
00859         Rshift = format->Rshift;
00860         Gshift = format->Gshift;
00861         Bshift = format->Bshift;
00862         Ashift = format->Ashift;
00863 
00864         preMultR = (alpha * (dR >> Rshift));
00865         preMultG = (alpha * (dG >> Gshift));
00866         preMultB = (alpha * (dB >> Bshift));
00867 
00868         for (y = y1; y <= y2; y++) {
00869             row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
00870             for (x = x1; x <= x2; x++) {
00871                 pixel = row + x;
00872                 dc = *pixel;
00873 
00874                 surfaceAlpha = ((dc & Amask) >> Ashift);
00875                 aTmp = (255 - alpha);
00876                 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
00877                     aTmp *= surfaceAlpha;
00878                     R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
00879                     G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
00880                     B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
00881                 }
00882                 *pixel = R | G | B | (A << Ashift & Amask);
00883 
00884             }
00885         }
00886            }
00887            break;
00888 #endif
00889 
00890     }
00891 
00892     return (0);
00893 }
00894 
00907 int filledRectAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
00908 {
00909     Uint8 alpha;
00910     Uint32 mcolor;
00911     int result = 0;
00912 
00913     /*
00914     * Lock the surface
00915     */
00916     if (SDL_MUSTLOCK(dst)) {
00917         if (SDL_LockSurface(dst) < 0) {
00918             return (-1);
00919         }
00920     }
00921 
00922     /*
00923     * Setup color
00924     */
00925     alpha = color & 0x000000ff;
00926     mcolor =
00927         SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00928         (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00929 
00930     /*
00931     * Draw
00932     */
00933     result = _filledRectAlpha(dst, x, y, x2, y2, mcolor, alpha);
00934 
00935     /*
00936     * Unlock the surface
00937     */
00938     if (SDL_MUSTLOCK(dst)) {
00939         SDL_UnlockSurface(dst);
00940     }
00941 
00942     return (result);
00943 }
00944 
00956 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
00957 {
00958     return (filledRectAlpha(dst, x1, y, x2, y, color));
00959 }
00960 
00972 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color)
00973 {
00974     return (filledRectAlpha(dst, x, y, x, y2, color));
00975 }
00976 
00988 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
00989 {
00990     Uint32 a;
00991 
00992     /*
00993     * Get alpha
00994     */
00995     a = (color & (Uint32) 0x000000ff);
00996 
00997     /*
00998     * Modify Alpha by weight
00999     */
01000     a = ((a * weight) >> 8);
01001 
01002     return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
01003 }
01004 
01016 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
01017 {
01018     Uint32 a;
01019 
01020     /*
01021     * Get alpha
01022     */
01023     a = (color & (Uint32) 0x000000ff);
01024 
01025     /*
01026     * Modify Alpha by weight
01027     */
01028     a = ((a * weight) >> 8);
01029 
01030     return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
01031 }
01032 
01046 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01047 {
01048     Uint32 color;
01049 
01050     /*
01051     * Check Alpha
01052     */
01053     if (a == 255) {
01054         /*
01055         * No alpha blending required
01056         */
01057         /*
01058         * Setup color
01059         */
01060         color = SDL_MapRGBA(dst->format, r, g, b, a);
01061         /*
01062         * Draw
01063         */
01064         return (fastPixelColor(dst, x, y, color));
01065     } else {
01066         /*
01067         * Alpha blending required
01068         */
01069         /*
01070         * Draw
01071         */
01072         return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01073     }
01074 }
01075 
01076 
01092 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
01093 {
01094     Sint16 left, right, top, bottom;
01095     Uint8 *pixel, *pixellast;
01096     int dx;
01097     int pixx, pixy;
01098     Sint16 w;
01099     Sint16 xtmp;
01100     int result = -1;
01101 
01102     /*
01103     * Check visibility of clipping rectangle
01104     */
01105     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01106         return(0);
01107     }
01108 
01109     /*
01110     * Swap x1, x2 if required to ensure x1<=x2
01111     */
01112     if (x1 > x2) {
01113         xtmp = x1;
01114         x1 = x2;
01115         x2 = xtmp;
01116     }
01117 
01118     /*
01119     * Get clipping boundary and
01120     * check visibility of hline
01121     */
01122     left = dst->clip_rect.x;
01123     if (x2<left) {
01124         return(0);
01125     }
01126     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01127     if (x1>right) {
01128         return(0);
01129     }
01130     top = dst->clip_rect.y;
01131     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01132     if ((y<top) || (y>bottom)) {
01133         return (0);
01134     }
01135 
01136     /*
01137     * Clip x
01138     */
01139     if (x1 < left) {
01140         x1 = left;
01141     }
01142     if (x2 > right) {
01143         x2 = right;
01144     }
01145 
01146     /*
01147     * Calculate width
01148     */
01149     w = x2 - x1;
01150 
01151     /*
01152     * Lock the surface
01153     */
01154     if (SDL_MUSTLOCK(dst)) {
01155         if (SDL_LockSurface(dst) < 0) {
01156             return (-1);
01157         }
01158     }
01159 
01160     /*
01161     * More variable setup
01162     */
01163     dx = w;
01164     pixx = dst->format->BytesPerPixel;
01165     pixy = dst->pitch;
01166     pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
01167 
01168     /*
01169     * Draw
01170     */
01171     switch (dst->format->BytesPerPixel) {
01172     case 1:
01173         memset(pixel, color, dx+1);
01174         break;
01175     case 2:
01176         pixellast = pixel + dx + dx;
01177         for (; pixel <= pixellast; pixel += pixx) {
01178             *(Uint16 *) pixel = color;
01179         }
01180         break;
01181     case 3:
01182         pixellast = pixel + dx + dx + dx;
01183         for (; pixel <= pixellast; pixel += pixx) {
01184             if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01185                 pixel[0] = (color >> 16) & 0xff;
01186                 pixel[1] = (color >> 8) & 0xff;
01187                 pixel[2] = color & 0xff;
01188             } else {
01189                 pixel[0] = color & 0xff;
01190                 pixel[1] = (color >> 8) & 0xff;
01191                 pixel[2] = (color >> 16) & 0xff;
01192             }
01193         }
01194         break;
01195     default:        /* case 4 */
01196         dx = dx + dx;
01197         pixellast = pixel + dx + dx;
01198         for (; pixel <= pixellast; pixel += pixx) {
01199             *(Uint32 *) pixel = color;
01200         }
01201         break;
01202     }
01203 
01204     /*
01205     * Unlock surface
01206     */
01207     if (SDL_MUSTLOCK(dst)) {
01208         SDL_UnlockSurface(dst);
01209     }
01210 
01211     /*
01212     * Set result code
01213     */
01214     result = 0;
01215 
01216     return (result);
01217 }
01218 
01236 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01237 {
01238     /*
01239     * Draw
01240     */
01241     return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01242 }
01243 
01255 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
01256 {
01257     Sint16 left, right, top, bottom;
01258     Uint8 *pixel, *pixellast;
01259     int dx;
01260     int pixx, pixy;
01261     Sint16 xtmp;
01262     int result = -1;
01263     Uint8 *colorptr;
01264     Uint8 color3[3];
01265 
01266     /*
01267     * Check visibility of clipping rectangle
01268     */
01269     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01270         return(0);
01271     }
01272 
01273     /*
01274     * Swap x1, x2 if required to ensure x1<=x2
01275     */
01276     if (x1 > x2) {
01277         xtmp = x1;
01278         x1 = x2;
01279         x2 = xtmp;
01280     }
01281 
01282     /*
01283     * Get clipping boundary and
01284     * check visibility of hline
01285     */
01286     left = dst->clip_rect.x;
01287     if (x2<left) {
01288         return(0);
01289     }
01290     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01291     if (x1>right) {
01292         return(0);
01293     }
01294     top = dst->clip_rect.y;
01295     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01296     if ((y<top) || (y>bottom)) {
01297         return (0);
01298     }
01299 
01300     /*
01301     * Clip x
01302     */
01303     if (x1 < left) {
01304         x1 = left;
01305     }
01306     if (x2 > right) {
01307         x2 = right;
01308     }
01309 
01310     /*
01311     * Calculate width difference
01312     */
01313     dx = x2 - x1;
01314 
01315     /*
01316     * Alpha check
01317     */
01318     if ((color & 255) == 255) {
01319 
01320         /*
01321         * No alpha-blending required
01322         */
01323 
01324         /*
01325         * Setup color
01326         */
01327         colorptr = (Uint8 *) & color;
01328         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01329             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01330         } else {
01331             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01332         }
01333 
01334         /*
01335         * Lock the surface
01336         */
01337         if (SDL_MUSTLOCK(dst)) {
01338             if (SDL_LockSurface(dst) < 0) {
01339                 return (-1);
01340             }
01341         }
01342 
01343         /*
01344         * More variable setup
01345         */
01346         pixx = dst->format->BytesPerPixel;
01347         pixy = dst->pitch;
01348         pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
01349 
01350         /*
01351         * Draw
01352         */
01353         switch (dst->format->BytesPerPixel) {
01354     case 1:
01355         memset(pixel, color, dx + 1);
01356         break;
01357     case 2:
01358         pixellast = pixel + dx + dx;
01359         for (; pixel <= pixellast; pixel += pixx) {
01360             *(Uint16 *) pixel = color;
01361         }
01362         break;
01363     case 3:
01364         pixellast = pixel + dx + dx + dx;
01365         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01366             color3[0] = (color >> 16) & 0xff;
01367             color3[1] = (color >> 8) & 0xff;
01368             color3[2] = color & 0xff;
01369         } else {
01370             color3[0] = color & 0xff;
01371             color3[1] = (color >> 8) & 0xff;
01372             color3[2] = (color >> 16) & 0xff;
01373         }
01374         for (; pixel <= pixellast; pixel += pixx) {
01375             memcpy(pixel, color3, 3);
01376         }
01377         break;
01378     default:        /* case 4 */
01379         dx = dx + dx;
01380         pixellast = pixel + dx + dx;
01381         for (; pixel <= pixellast; pixel += pixx) {
01382             *(Uint32 *) pixel = color;
01383         }
01384         break;
01385         }
01386 
01387         /*
01388         * Unlock surface
01389         */
01390         if (SDL_MUSTLOCK(dst)) {
01391             SDL_UnlockSurface(dst);
01392         }
01393 
01394         /*
01395         * Set result code
01396         */
01397         result = 0;
01398 
01399     } else {
01400 
01401         /*
01402         * Alpha blending blit
01403         */
01404         result = _HLineAlpha(dst, x1, x1 + dx, y, color);
01405     }
01406 
01407     return (result);
01408 }
01409 
01424 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01425 {
01426     /*
01427     * Draw
01428     */
01429     return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01430 }
01431 
01443 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color)
01444 {
01445     Sint16 left, right, top, bottom;
01446     Uint8 *pixel, *pixellast;
01447     int dy;
01448     int pixx, pixy;
01449     Sint16 h;
01450     Sint16 ytmp;
01451     int result = -1;
01452     Uint8 *colorptr;
01453 
01454     /*
01455     * Check visibility of clipping rectangle
01456     */
01457     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01458         return(0);
01459     }
01460 
01461     /*
01462     * Swap y1, y2 if required to ensure y1<=y2
01463     */
01464     if (y > y2) {
01465         ytmp = y;
01466         y = y2;
01467         y2 = ytmp;
01468     }
01469 
01470     /*
01471     * Get clipping boundary and
01472     * check visibility of vline
01473     */
01474     left = dst->clip_rect.x;
01475     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01476     if ((x<left) || (x>right)) {
01477         return (0);
01478     }
01479     top = dst->clip_rect.y;
01480     if (y2<top) {
01481         return(0);
01482     }
01483     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01484     if (y>bottom) {
01485         return(0);
01486     }
01487 
01488     /*
01489     * Clip x
01490     */
01491     if (y < top) {
01492         y = top;
01493     }
01494     if (y2 > bottom) {
01495         y2 = bottom;
01496     }
01497 
01498     /*
01499     * Calculate height
01500     */
01501     h = y2 - y;
01502 
01503     /*
01504     * Alpha check
01505     */
01506     if ((color & 255) == 255) {
01507 
01508         /*
01509         * No alpha-blending required
01510         */
01511 
01512         /*
01513         * Setup color
01514         */
01515         colorptr = (Uint8 *) & color;
01516         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01517             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01518         } else {
01519             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01520         }
01521 
01522         /*
01523         * Lock the surface
01524         */
01525         if (SDL_MUSTLOCK(dst)) {
01526             if (SDL_LockSurface(dst) < 0) {
01527                 return (-1);
01528             }
01529         }
01530 
01531         /*
01532         * More variable setup
01533         */
01534         dy = h;
01535         pixx = dst->format->BytesPerPixel;
01536         pixy = dst->pitch;
01537         pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y;
01538         pixellast = pixel + pixy * dy;
01539 
01540         /*
01541         * Draw
01542         */
01543         switch (dst->format->BytesPerPixel) {
01544     case 1:
01545         for (; pixel <= pixellast; pixel += pixy) {
01546             *(Uint8 *) pixel = color;
01547         }
01548         break;
01549     case 2:
01550         for (; pixel <= pixellast; pixel += pixy) {
01551             *(Uint16 *) pixel = color;
01552         }
01553         break;
01554     case 3:
01555         for (; pixel <= pixellast; pixel += pixy) {
01556             if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01557                 pixel[0] = (color >> 16) & 0xff;
01558                 pixel[1] = (color >> 8) & 0xff;
01559                 pixel[2] = color & 0xff;
01560             } else {
01561                 pixel[0] = color & 0xff;
01562                 pixel[1] = (color >> 8) & 0xff;
01563                 pixel[2] = (color >> 16) & 0xff;
01564             }
01565         }
01566         break;
01567     default:        /* case 4 */
01568         for (; pixel <= pixellast; pixel += pixy) {
01569             *(Uint32 *) pixel = color;
01570         }
01571         break;
01572         }
01573 
01574         /* Unlock surface */
01575         if (SDL_MUSTLOCK(dst)) {
01576             SDL_UnlockSurface(dst);
01577         }
01578 
01579         /*
01580         * Set result code
01581         */
01582         result = 0;
01583 
01584     } else {
01585 
01586         /*
01587         * Alpha blending blit
01588         */
01589 
01590         result = _VLineAlpha(dst, x, y, y + h, color);
01591 
01592     }
01593 
01594     return (result);
01595 }
01596 
01611 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01612 {
01613     /*
01614     * Draw
01615     */
01616     return (vlineColor(dst, x, y, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01617 }
01618 
01631 int rectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
01632 {
01633     int result;
01634     Sint16 tmp;
01635 
01636     /* Check destination surface */
01637     if (dst == NULL)
01638     {
01639         return -1;
01640     }
01641 
01642     /*
01643     * Check visibility of clipping rectangle
01644     */
01645     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01646         return 0;
01647     }
01648 
01649     /*
01650     * Test for special cases of straight lines or single point
01651     */
01652     if (x == x2) {
01653         if (y == y2) {
01654             return (pixelColor(dst, x, y, color));
01655         } else {
01656             return (vlineColor(dst, x, y, y2, color));
01657         }
01658     } else {
01659         if (y == y2) {
01660             return (hlineColor(dst, x, x2, y, color));
01661         }
01662     }
01663 
01664     /*
01665     * Swap x1, x2 if required
01666     */
01667     if (x > x2) {
01668         tmp = x;
01669         x = x2;
01670         x2 = tmp;
01671     }
01672 
01673     /*
01674     * Swap y1, y2 if required
01675     */
01676     if (y > y2) {
01677         tmp = y;
01678         y = y2;
01679         y2 = tmp;
01680     }
01681 
01682     /*
01683     * Draw rectangle
01684     */
01685     result = 0;
01686     result |= hlineColor(dst, x, x2, y, color);
01687     result |= hlineColor(dst, x, x2, y2, color);
01688     y += 1;
01689     y2 -= 1;
01690     if (y <= y2) {
01691         result |= vlineColor(dst, x, y, y2, color);
01692         result |= vlineColor(dst, x2, y, y2, color);
01693     }
01694 
01695     return (result);
01696 
01697 }
01698 
01714 int rectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01715 {
01716     /*
01717     * Draw
01718     */
01719     return (rectangleColor
01720         (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01721 }
01722 
01736 int roundedRectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
01737 {
01738     int result;
01739     Sint16 w, h, tmp;
01740     Sint16 xx1, xx2, yy1, yy2;
01741 
01742     /*
01743     * Check destination surface
01744     */
01745     if (dst == NULL)
01746     {
01747         return -1;
01748     }
01749 
01750     /*
01751     * Check radius vor valid range
01752     */
01753     if (rad < 0) {
01754         return -1;
01755     }
01756 
01757     /*
01758     * Special case - no rounding
01759     */
01760     if (rad == 0) {
01761         return rectangleColor(dst, x, y, x2, y2, color);
01762     }
01763 
01764     /*
01765     * Check visibility of clipping rectangle
01766     */
01767     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01768         return 0;
01769     }
01770 
01771     /*
01772     * Test for special cases of straight lines or single point
01773     */
01774     if (x == x2) {
01775         if (y == y2) {
01776             return (pixelColor(dst, x, y, color));
01777         } else {
01778             return (vlineColor(dst, x, y, y2, color));
01779         }
01780     } else {
01781         if (y == y2) {
01782             return (hlineColor(dst, x, x2, y, color));
01783         }
01784     }
01785 
01786     /*
01787     * Swap x1, x2 if required
01788     */
01789     if (x > x2) {
01790         tmp = x;
01791         x = x2;
01792         x2 = tmp;
01793     }
01794 
01795     /*
01796     * Swap y1, y2 if required
01797     */
01798     if (y > y2) {
01799         tmp = y;
01800         y = y2;
01801         y2 = tmp;
01802     }
01803 
01804     /*
01805     * Calculate width&height
01806     */
01807     w = x2 - x;
01808     h = y2 - y;
01809 
01810     /*
01811     * Maybe adjust radius
01812     */
01813     if ((rad * 2) > w)
01814     {
01815         rad = w / 2;
01816     }
01817     if ((rad * 2) > h)
01818     {
01819         rad = h / 2;
01820     }
01821 
01822     /*
01823     * Draw corners
01824     */
01825     result = 0;
01826     xx1 = x + rad;
01827     xx2 = x2 - rad;
01828     yy1 = y + rad;
01829     yy2 = y2 - rad;
01830     result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
01831     result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
01832     result |= arcColor(dst, xx1, yy2, rad,  90, 180, color);
01833     result |= arcColor(dst, xx2, yy2, rad,   0,  90, color);
01834 
01835     /*
01836     * Draw lines
01837     */
01838     if (xx1 <= xx2) {
01839         result |= hlineColor(dst, xx1, xx2, y, color);
01840         result |= hlineColor(dst, xx1, xx2, y2, color);
01841     }
01842     if (yy1 <= yy2) {
01843         result |= vlineColor(dst, x, yy1, yy2, color);
01844         result |= vlineColor(dst, x2, yy1, yy2, color);
01845     }
01846 
01847     return result;
01848 }
01849 
01866 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01867 {
01868     /*
01869     * Draw
01870     */
01871     return (roundedRectangleColor
01872         (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01873 }
01874 
01888 int roundedBoxColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
01889 {
01890     int result;
01891     Sint16 w, h, tmp;
01892     Sint16 xx1, xx2, yy1, yy2;
01893 
01894     /*
01895     * Check destination surface
01896     */
01897     if (dst == NULL)
01898     {
01899         return -1;
01900     }
01901 
01902     /*
01903     * Check radius vor valid range
01904     */
01905     if (rad < 0) {
01906         return -1;
01907     }
01908 
01909     /*
01910     * Special case - no rounding
01911     */
01912     if (rad == 0) {
01913         return rectangleColor(dst, x, y, x2, y2, color);
01914     }
01915 
01916     /*
01917     * Check visibility of clipping rectangle
01918     */
01919     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01920         return 0;
01921     }
01922 
01923     /*
01924     * Test for special cases of straight lines or single point
01925     */
01926     if (x == x2) {
01927         if (y == y2) {
01928             return (pixelColor(dst, x, y, color));
01929         } else {
01930             return (vlineColor(dst, x, y, y2, color));
01931         }
01932     } else {
01933         if (y == y2) {
01934             return (hlineColor(dst, x, x2, y, color));
01935         }
01936     }
01937 
01938     /*
01939     * Swap x1, x2 if required
01940     */
01941     if (x > x2) {
01942         tmp = x;
01943         x = x2;
01944         x2 = tmp;
01945     }
01946 
01947     /*
01948     * Swap y1, y2 if required
01949     */
01950     if (y > y2) {
01951         tmp = y;
01952         y = y2;
01953         y2 = tmp;
01954     }
01955 
01956     /*
01957     * Calculate width&height
01958     */
01959     w = x2 - x;
01960     h = y2 - y;
01961 
01962     /*
01963     * Maybe adjust radius
01964     */
01965     if ((rad * 2) > w)
01966     {
01967         rad = w / 2;
01968     }
01969     if ((rad * 2) > h)
01970     {
01971         rad = h / 2;
01972     }
01973 
01974     /*
01975     * Draw corners
01976     */
01977     result = 0;
01978     xx1 = x + rad;
01979     xx2 = x2 - rad;
01980     yy1 = y + rad;
01981     yy2 = y2 - rad;
01982     result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
01983     result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
01984     result |= filledPieColor(dst, xx1, yy2, rad,  90, 180, color);
01985     result |= filledPieColor(dst, xx2, yy2, rad,   0,  90, color);
01986 
01987     /*
01988     * Draw body
01989     */
01990     xx1++;
01991     xx2--;
01992     yy1++;
01993     yy2--;
01994     if (xx1 <= xx2) {
01995         result |= boxColor(dst, xx1, y, xx2, y2, color);
01996     }
01997     if (yy1 <= yy2) {
01998         result |= boxColor(dst, x, yy1, xx1-1, yy2, color);
01999         result |= boxColor(dst, xx2+1, yy1, x2, yy2, color);
02000     }
02001 
02002     return result;
02003 }
02004 
02021 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2,
02022                    Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02023 {
02024     /*
02025     * Draw
02026     */
02027     return (roundedBoxColor
02028         (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02029 }
02030 
02031 /* --------- Clipping routines for line */
02032 
02033 /* Clipping based heavily on code from                       */
02034 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
02035 
02036 #define CLIP_LEFT_EDGE   0x1
02037 #define CLIP_RIGHT_EDGE  0x2
02038 #define CLIP_BOTTOM_EDGE 0x4
02039 #define CLIP_TOP_EDGE    0x8
02040 #define CLIP_INSIDE(a)   (!a)
02041 #define CLIP_REJECT(a,b) (a&b)
02042 #define CLIP_ACCEPT(a,b) (!(a|b))
02043 
02056 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
02057 {
02058     int code = 0;
02059 
02060     if (x < left) {
02061         code |= CLIP_LEFT_EDGE;
02062     } else if (x > right) {
02063         code |= CLIP_RIGHT_EDGE;
02064     }
02065     if (y < top) {
02066         code |= CLIP_TOP_EDGE;
02067     } else if (y > bottom) {
02068         code |= CLIP_BOTTOM_EDGE;
02069     }
02070     return code;
02071 }
02072 
02082 static int _clipLine(SDL_Surface * dst, Sint16 * x, Sint16 * y, Sint16 * x2, Sint16 * y2)
02083 {
02084     Sint16 left, right, top, bottom;
02085     int code1, code2;
02086     int draw = 0;
02087     Sint16 swaptmp;
02088     float m;
02089 
02090     /*
02091     * Get clipping boundary
02092     */
02093     left = dst->clip_rect.x;
02094     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02095     top = dst->clip_rect.y;
02096     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02097 
02098     while (1) {
02099         code1 = _clipEncode(*x, *y, left, top, right, bottom);
02100         code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
02101         if (CLIP_ACCEPT(code1, code2)) {
02102             draw = 1;
02103             break;
02104         } else if (CLIP_REJECT(code1, code2))
02105             break;
02106         else {
02107             if (CLIP_INSIDE(code1)) {
02108                 swaptmp = *x2;
02109                 *x2 = *x;
02110                 *x = swaptmp;
02111                 swaptmp = *y2;
02112                 *y2 = *y;
02113                 *y = swaptmp;
02114                 swaptmp = code2;
02115                 code2 = code1;
02116                 code1 = swaptmp;
02117             }
02118             if (*x2 != *x) {
02119                 m = (*y2 - *y) / (float) (*x2 - *x);
02120             } else {
02121                 m = 1.0f;
02122             }
02123             if (code1 & CLIP_LEFT_EDGE) {
02124                 *y += (Sint16) ((left - *x) * m);
02125                 *x = left;
02126             } else if (code1 & CLIP_RIGHT_EDGE) {
02127                 *y += (Sint16) ((right - *x) * m);
02128                 *x = right;
02129             } else if (code1 & CLIP_BOTTOM_EDGE) {
02130                 if (*x2 != *x) {
02131                     *x += (Sint16) ((bottom - *y) / m);
02132                 }
02133                 *y = bottom;
02134             } else if (code1 & CLIP_TOP_EDGE) {
02135                 if (*x2 != *x) {
02136                     *x += (Sint16) ((top - *y) / m);
02137                 }
02138                 *y = top;
02139             }
02140         }
02141     }
02142 
02143     return draw;
02144 }
02145 
02158 int boxColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color)
02159 {
02160     Sint16 left, right, top, bottom;
02161     Uint8 *pixel, *pixellast;
02162     int x, dx;
02163     int dy;
02164     int pixx, pixy;
02165     Sint16 w, h, tmp;
02166     int result;
02167     Uint8 *colorptr;
02168 
02169     /*
02170     * Check visibility of clipping rectangle
02171     */
02172     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02173         return(0);
02174     }
02175 
02176     /*
02177     * Order coordinates to ensure that
02178     * x1<=x2 and y1<=y2
02179     */
02180     if (xx > x2) {
02181         tmp = xx;
02182         xx = x2;
02183         x2 = tmp;
02184     }
02185     if (yy > y2) {
02186         tmp = yy;
02187         yy = y2;
02188         y2 = tmp;
02189     }
02190 
02191     /*
02192     * Get clipping boundary and
02193     * check visibility
02194     */
02195     left = dst->clip_rect.x;
02196     if (x2<left) {
02197         return(0);
02198     }
02199     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02200     if (xx>right) {
02201         return(0);
02202     }
02203     top = dst->clip_rect.y;
02204     if (y2<top) {
02205         return(0);
02206     }
02207     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02208     if (yy>bottom) {
02209         return(0);
02210     }
02211 
02212     /* Clip all points */
02213     if (xx<left) {
02214         xx=left;
02215     } else if (xx>right) {
02216         xx=right;
02217     }
02218     if (x2<left) {
02219         x2=left;
02220     } else if (x2>right) {
02221         x2=right;
02222     }
02223     if (yy<top) {
02224         yy=top;
02225     } else if (yy>bottom) {
02226         yy=bottom;
02227     }
02228     if (y2<top) {
02229         y2=top;
02230     } else if (y2>bottom) {
02231         y2=bottom;
02232     }
02233 
02234     /*
02235     * Test for special cases of straight line or single point
02236     */
02237     if (xx == x2) {
02238         if (yy == y2) {
02239             return (pixelColor(dst, xx, yy, color));
02240         } else {
02241             return (vlineColor(dst, xx, yy, y2, color));
02242         }
02243     }
02244     if (yy == y2) {
02245         return (hlineColor(dst, xx, x2, yy, color));
02246     }
02247 
02248     /*
02249     * Calculate width&height
02250     */
02251     w = x2 - xx;
02252     h = y2 - yy;
02253 
02254     /*
02255     * Alpha check
02256     */
02257     if ((color & 255) == 255) {
02258 
02259         /*
02260         * No alpha-blending required
02261         */
02262 
02263         /*
02264         * Setup color
02265         */
02266         colorptr = (Uint8 *) & color;
02267         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02268             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02269         } else {
02270             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02271         }
02272 
02273         /*
02274         * Lock the surface
02275         */
02276         if (SDL_MUSTLOCK(dst)) {
02277             if (SDL_LockSurface(dst) < 0) {
02278                 return (-1);
02279             }
02280         }
02281 
02282         /*
02283         * More variable setup
02284         */
02285         dx = w;
02286         dy = h;
02287         pixx = dst->format->BytesPerPixel;
02288         pixy = dst->pitch;
02289         pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy;
02290         pixellast = pixel + pixx * dx + pixy * dy;
02291         dx++;
02292 
02293         /*
02294         * Draw
02295         */
02296         switch (dst->format->BytesPerPixel) {
02297     case 1:
02298         for (; pixel <= pixellast; pixel += pixy) {
02299             memset(pixel, (Uint8) color, dx);
02300         }
02301         break;
02302     case 2:
02303         pixy -= (pixx * dx);
02304         for (; pixel <= pixellast; pixel += pixy) {
02305             for (x = 0; x < dx; x++) {
02306                 *(Uint16*) pixel = color;
02307                 pixel += pixx;
02308             }
02309         }
02310         break;
02311     case 3:
02312         pixy -= (pixx * dx);
02313         for (; pixel <= pixellast; pixel += pixy) {
02314             for (x = 0; x < dx; x++) {
02315                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02316                     pixel[0] = (color >> 16) & 0xff;
02317                     pixel[1] = (color >> 8) & 0xff;
02318                     pixel[2] = color & 0xff;
02319                 } else {
02320                     pixel[0] = color & 0xff;
02321                     pixel[1] = (color >> 8) & 0xff;
02322                     pixel[2] = (color >> 16) & 0xff;
02323                 }
02324                 pixel += pixx;
02325             }
02326         }
02327         break;
02328     default:        /* case 4 */
02329         pixy -= (pixx * dx);
02330         for (; pixel <= pixellast; pixel += pixy) {
02331             for (x = 0; x < dx; x++) {
02332                 *(Uint32 *) pixel = color;
02333                 pixel += pixx;
02334             }
02335         }
02336         break;
02337         }
02338 
02339         /* Unlock surface */
02340         if (SDL_MUSTLOCK(dst)) {
02341             SDL_UnlockSurface(dst);
02342         }
02343 
02344         result = 0;
02345 
02346     } else {
02347 
02348         result = filledRectAlpha(dst, xx, yy, xx + w, yy + h, color);
02349 
02350     }
02351 
02352     return (result);
02353 }
02354 
02370 int boxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02371 {
02372     /*
02373     * Draw
02374     */
02375     return (boxColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02376 }
02377 
02378 /* ----- Line */
02379 
02380 /* Non-alpha line drawing code adapted from routine          */
02381 /* by Pete Shinners, pete@shinners.org                       */
02382 /* Originally from pygame, http://pygame.seul.org            */
02383 
02384 #define ABS(a) (((a)<0) ? -(a) : (a))
02385 
02398 int lineColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color)
02399 {
02400     int pixx, pixy;
02401     int x, y;
02402     int dx, dy;
02403     int ax, ay;
02404     int sx, sy;
02405     int swaptmp;
02406     Uint8 *pixel;
02407     Uint8 *colorptr;
02408 
02409     /*
02410     * Clip line and test if we have to draw
02411     */
02412     if (!(_clipLine(dst, &xx, &yy, &x2, &y2))) {
02413         return (0);
02414     }
02415 
02416     /*
02417     * Test for special cases of straight lines or single point
02418     */
02419     if (xx == x2) {
02420         if (yy < y2) {
02421             return (vlineColor(dst, xx, yy, y2, color));
02422         } else if (yy > y2) {
02423             return (vlineColor(dst, xx, y2, yy, color));
02424         } else {
02425             return (pixelColor(dst, xx, yy, color));
02426         }
02427     }
02428     if (yy == y2) {
02429         if (xx < x2) {
02430             return (hlineColor(dst, xx, x2, yy, color));
02431         } else if (xx > x2) {
02432             return (hlineColor(dst, x2, xx, yy, color));
02433         }
02434     }
02435 
02436     /*
02437     * Variable setup
02438     */
02439     dx = x2 - xx;
02440     dy = y2 - yy;
02441     sx = (dx >= 0) ? 1 : -1;
02442     sy = (dy >= 0) ? 1 : -1;
02443 
02444     /* Lock surface */
02445     if (SDL_MUSTLOCK(dst)) {
02446         if (SDL_LockSurface(dst) < 0) {
02447             return (-1);
02448         }
02449     }
02450 
02451     /*
02452     * Check for alpha blending
02453     */
02454     if ((color & 255) == 255) {
02455 
02456         /*
02457         * No alpha blending - use fast pixel routines
02458         */
02459 
02460         /*
02461         * Setup color
02462         */
02463         colorptr = (Uint8 *) & color;
02464         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02465             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02466         } else {
02467             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02468         }
02469 
02470         /*
02471         * More variable setup
02472         */
02473         dx = sx * dx + 1;
02474         dy = sy * dy + 1;
02475         pixx = dst->format->BytesPerPixel;
02476         pixy = dst->pitch;
02477         pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy;
02478         pixx *= sx;
02479         pixy *= sy;
02480         if (dx < dy) {
02481             swaptmp = dx;
02482             dx = dy;
02483             dy = swaptmp;
02484             swaptmp = pixx;
02485             pixx = pixy;
02486             pixy = swaptmp;
02487         }
02488 
02489         /*
02490         * Draw
02491         */
02492         x = 0;
02493         y = 0;
02494         switch (dst->format->BytesPerPixel) {
02495     case 1:
02496         for (; x < dx; x++, pixel += pixx) {
02497             *pixel = color;
02498             y += dy;
02499             if (y >= dx) {
02500                 y -= dx;
02501                 pixel += pixy;
02502             }
02503         }
02504         break;
02505     case 2:
02506         for (; x < dx; x++, pixel += pixx) {
02507             *(Uint16 *) pixel = color;
02508             y += dy;
02509             if (y >= dx) {
02510                 y -= dx;
02511                 pixel += pixy;
02512             }
02513         }
02514         break;
02515     case 3:
02516         for (; x < dx; x++, pixel += pixx) {
02517             if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02518                 pixel[0] = (color >> 16) & 0xff;
02519                 pixel[1] = (color >> 8) & 0xff;
02520                 pixel[2] = color & 0xff;
02521             } else {
02522                 pixel[0] = color & 0xff;
02523                 pixel[1] = (color >> 8) & 0xff;
02524                 pixel[2] = (color >> 16) & 0xff;
02525             }
02526             y += dy;
02527             if (y >= dx) {
02528                 y -= dx;
02529                 pixel += pixy;
02530             }
02531         }
02532         break;
02533     default:        /* case 4 */
02534         for (; x < dx; x++, pixel += pixx) {
02535             *(Uint32 *) pixel = color;
02536             y += dy;
02537             if (y >= dx) {
02538                 y -= dx;
02539                 pixel += pixy;
02540             }
02541         }
02542         break;
02543         }
02544 
02545     } else {
02546 
02547         /*
02548         * Alpha blending required - use single-pixel blits
02549         */
02550 
02551         ax = ABS(dx) << 1;
02552         ay = ABS(dy) << 1;
02553         x = xx;
02554         y = yy;
02555         if (ax > ay) {
02556             int d = ay - (ax >> 1);
02557 
02558             while (x != x2) {
02559                 pixelColorNolock (dst, x, y, color);
02560                 if (d > 0 || (d == 0 && sx == 1)) {
02561                     y += sy;
02562                     d -= ax;
02563                 }
02564                 x += sx;
02565                 d += ay;
02566             }
02567         } else {
02568             int d = ax - (ay >> 1);
02569 
02570             while (y != y2) {
02571                 pixelColorNolock (dst, x, y, color);
02572                 if (d > 0 || ((d == 0) && (sy == 1))) {
02573                     x += sx;
02574                     d -= ay;
02575                 }
02576                 y += sy;
02577                 d += ax;
02578             }
02579         }
02580         pixelColorNolock (dst, x, y, color);
02581 
02582     }
02583 
02584     /* Unlock surface */
02585     if (SDL_MUSTLOCK(dst)) {
02586         SDL_UnlockSurface(dst);
02587     }
02588 
02589     return (0);
02590 }
02591 
02607 int lineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02608 {
02609     /*
02610     * Draw
02611     */
02612     return (lineColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02613 }
02614 
02615 /* AA Line */
02616 
02617 #define AAlevels 256
02618 #define AAbits 8
02619 
02640 int _aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
02641 {
02642     Sint32 xx0, yy0, xx1, yy1;
02643     int result;
02644     Uint32 intshift, erracc, erradj;
02645     Uint32 erracctmp, wgt;
02646     int dx, dy, tmp, xdir, y0p1, x0pxdir;
02647 
02648     /*
02649     * Check visibility of clipping rectangle
02650     */
02651     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02652         return(0);
02653     }
02654 
02655     /*
02656     * Clip line and test if we have to draw
02657     */
02658     if (!(_clipLine(dst, &x, &y, &x2, &y2))) {
02659         return (0);
02660     }
02661 
02662     /*
02663     * Keep on working with 32bit numbers
02664     */
02665     xx0 = x;
02666     yy0 = y;
02667     xx1 = x2;
02668     yy1 = y2;
02669 
02670     /*
02671     * Reorder points if required
02672     */
02673     if (yy0 > yy1) {
02674         tmp = yy0;
02675         yy0 = yy1;
02676         yy1 = tmp;
02677         tmp = xx0;
02678         xx0 = xx1;
02679         xx1 = tmp;
02680     }
02681 
02682     /*
02683     * Calculate distance
02684     */
02685     dx = xx1 - xx0;
02686     dy = yy1 - yy0;
02687 
02688     /*
02689     * Check for special cases
02690     */
02691     if (dx == 0) {
02692         /*
02693         * Vertical line
02694         */
02695         if (draw_endpoint)
02696         {
02697             return (vlineColor(dst, x, y, y2, color));
02698         } else {
02699             if (dy>0) {
02700                 return (vlineColor(dst, x, yy0, yy0+dy, color));
02701             } else {
02702                 return (pixelColor(dst, x, y, color));
02703             }
02704         }
02705     } else if (dy == 0) {
02706         /*
02707         * Horizontal line
02708         */
02709         if (draw_endpoint)
02710         {
02711             return (hlineColor(dst, x, x2, y, color));
02712         } else {
02713             if (dx>0) {
02714                 return (hlineColor(dst, xx0, xx0+dx, y, color));
02715             } else {
02716                 return (pixelColor(dst, x, y, color));
02717             }
02718         }
02719     } else if ((dx == dy) && (draw_endpoint)) {
02720         /*
02721         * Diagonal line (with endpoint)
02722         */
02723         return (lineColor(dst, x, y, x2, y2, color));
02724     }
02725 
02726     /*
02727     * Adjust for negative dx and set xdir
02728     */
02729     if (dx >= 0) {
02730         xdir = 1;
02731     } else {
02732         xdir = -1;
02733         dx = (-dx);
02734     }
02735 
02736     /*
02737     * Line is not horizontal, vertical or diagonal (with endpoint)
02738     */
02739     result = 0;
02740 
02741     /*
02742     * Zero accumulator
02743     */
02744     erracc = 0;
02745 
02746     /*
02747     * # of bits by which to shift erracc to get intensity level
02748     */
02749     intshift = 32 - AAbits;
02750 
02751     /* Lock surface */
02752     if (SDL_MUSTLOCK(dst)) {
02753         if (SDL_LockSurface(dst) < 0) {
02754             return (-1);
02755         }
02756     }
02757 
02758     /*
02759     * Draw the initial pixel in the foreground color
02760     */
02761     result |= pixelColorNolock(dst, x, y, color);
02762 
02763     /*
02764     * x-major or y-major?
02765     */
02766     if (dy > dx) {
02767 
02768         /*
02769         * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
02770         * X advances every time Y advances 1 pixel, truncating the result so that
02771         * we won't overrun the endpoint along the X axis
02772         */
02773         /*
02774         * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
02775         */
02776         erradj = ((dx << 16) / dy) << 16;
02777 
02778         /*
02779         * draw all pixels other than the first and last
02780         */
02781         x0pxdir = xx0 + xdir;
02782         while (--dy) {
02783             erracctmp = erracc;
02784             erracc += erradj;
02785             if (erracc <= erracctmp) {
02786                 /*
02787                 * rollover in error accumulator, x coord advances
02788                 */
02789                 xx0 = x0pxdir;
02790                 x0pxdir += xdir;
02791             }
02792             yy0++;      /* y-major so always advance Y */
02793 
02794             /*
02795             * the AAbits most significant bits of erracc give us the intensity
02796             * weighting for this pixel, and the complement of the weighting for
02797             * the paired pixel.
02798             */
02799             wgt = (erracc >> intshift) & 255;
02800             result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
02801             result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
02802         }
02803 
02804     } else {
02805 
02806         /*
02807         * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
02808         * that Y advances each time X advances 1 pixel, truncating the result so
02809         * that we won't overrun the endpoint along the X axis.
02810         */
02811         /*
02812         * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
02813         */
02814         erradj = ((dy << 16) / dx) << 16;
02815 
02816         /*
02817         * draw all pixels other than the first and last
02818         */
02819         y0p1 = yy0 + 1;
02820         while (--dx) {
02821 
02822             erracctmp = erracc;
02823             erracc += erradj;
02824             if (erracc <= erracctmp) {
02825                 /*
02826                 * Accumulator turned over, advance y
02827                 */
02828                 yy0 = y0p1;
02829                 y0p1++;
02830             }
02831             xx0 += xdir;    /* x-major so always advance X */
02832             /*
02833             * the AAbits most significant bits of erracc give us the intensity
02834             * weighting for this pixel, and the complement of the weighting for
02835             * the paired pixel.
02836             */
02837             wgt = (erracc >> intshift) & 255;
02838             result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
02839             result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
02840         }
02841     }
02842 
02843     /*
02844     * Do we have to draw the endpoint
02845     */
02846     if (draw_endpoint) {
02847         /*
02848         * Draw final pixel, always exactly intersected by the line and doesn't
02849         * need to be weighted.
02850         */
02851         result |= pixelColorNolock (dst, x2, y2, color);
02852     }
02853 
02854     /* Unlock surface */
02855     if (SDL_MUSTLOCK(dst)) {
02856         SDL_UnlockSurface(dst);
02857     }
02858 
02859     return (result);
02860 }
02861 
02874 int aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
02875 {
02876     return (_aalineColor(dst, x, y, x2, y2, color, 1));
02877 }
02878 
02894 int aalineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02895 {
02896     return (_aalineColor
02897         (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
02898 }
02899 
02900 
02901 /* ----- Circle */
02902 
02918 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
02919 {
02920     Sint16 left, right, top, bottom;
02921     int result;
02922     Sint16 xx, yy, x2, y2;
02923     Sint16 cx = 0;
02924     Sint16 cy = rad;
02925     Sint16 df = 1 - rad;
02926     Sint16 d_e = 3;
02927     Sint16 d_se = -2 * rad + 5;
02928     Sint16 xpcx, xmcx, xpcy, xmcy;
02929     Sint16 ypcy, ymcy, ypcx, ymcx;
02930     Uint8 *colorptr;
02931 
02932     /*
02933     * Check visibility of clipping rectangle
02934     */
02935     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02936         return(0);
02937     }
02938 
02939     /*
02940     * Sanity check radius
02941     */
02942     if (rad < 0) {
02943         return (-1);
02944     }
02945 
02946     /*
02947     * Special case for rad=0 - draw a point
02948     */
02949     if (rad == 0) {
02950         return (pixelColor(dst, x, y, color));
02951     }
02952 
02953     /*
02954     * Get circle and clipping boundary and
02955     * test if bounding box of circle is visible
02956     */
02957     x2 = x + rad;
02958     left = dst->clip_rect.x;
02959     if (x2<left) {
02960         return(0);
02961     }
02962     xx = x - rad;
02963     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02964     if (xx>right) {
02965         return(0);
02966     }
02967     y2 = y + rad;
02968     top = dst->clip_rect.y;
02969     if (y2<top) {
02970         return(0);
02971     }
02972     yy = y - rad;
02973     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02974     if (yy>bottom) {
02975         return(0);
02976     }
02977 
02978     /*
02979     * Draw circle
02980     */
02981     result = 0;
02982 
02983     /* Lock surface */
02984     if (SDL_MUSTLOCK(dst)) {
02985         if (SDL_LockSurface(dst) < 0) {
02986             return (-1);
02987         }
02988     }
02989 
02990     /*
02991     * Alpha Check
02992     */
02993     if ((color & 255) == 255) {
02994 
02995         /*
02996         * No Alpha - direct memory writes
02997         */
02998 
02999         /*
03000         * Setup color
03001         */
03002         colorptr = (Uint8 *) & color;
03003         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
03004             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
03005         } else {
03006             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
03007         }
03008 
03009         /*
03010         * Draw
03011         */
03012         do {
03013             ypcy = y + cy;
03014             ymcy = y - cy;
03015             if (cx > 0) {
03016                 xpcx = x + cx;
03017                 xmcx = x - cx;
03018                 result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
03019                 result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
03020                 result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
03021                 result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
03022             } else {
03023                 result |= fastPixelColorNolock(dst, x, ymcy, color);
03024                 result |= fastPixelColorNolock(dst, x, ypcy, color);
03025             }
03026             xpcy = x + cy;
03027             xmcy = x - cy;
03028             if ((cx > 0) && (cx != cy)) {
03029                 ypcx = y + cx;
03030                 ymcx = y - cx;
03031                 result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
03032                 result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
03033                 result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
03034                 result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
03035             } else if (cx == 0) {
03036                 result |= fastPixelColorNolock(dst, xmcy, y, color);
03037                 result |= fastPixelColorNolock(dst, xpcy, y, color);
03038             }
03039             /*
03040             * Update
03041             */
03042             if (df < 0) {
03043                 df += d_e;
03044                 d_e += 2;
03045                 d_se += 2;
03046             } else {
03047                 df += d_se;
03048                 d_e += 2;
03049                 d_se += 4;
03050                 cy--;
03051             }
03052             cx++;
03053         } while (cx <= cy);
03054 
03055         /*
03056         * Unlock surface
03057         */
03058         SDL_UnlockSurface(dst);
03059 
03060     } else {
03061 
03062         /*
03063         * Using Alpha - blended pixel blits
03064         */
03065 
03066         do {
03067             /*
03068             * Draw
03069             */
03070             ypcy = y + cy;
03071             ymcy = y - cy;
03072             if (cx > 0) {
03073                 xpcx = x + cx;
03074                 xmcx = x - cx;
03075                 result |= pixelColorNolock (dst, xmcx, ypcy, color);
03076                 result |= pixelColorNolock (dst, xpcx, ypcy, color);
03077                 result |= pixelColorNolock (dst, xmcx, ymcy, color);
03078                 result |= pixelColorNolock (dst, xpcx, ymcy, color);
03079             } else {
03080                 result |= pixelColorNolock (dst, x, ymcy, color);
03081                 result |= pixelColorNolock (dst, x, ypcy, color);
03082             }
03083             xpcy = x + cy;
03084             xmcy = x - cy;
03085             if ((cx > 0) && (cx != cy)) {
03086                 ypcx = y + cx;
03087                 ymcx = y - cx;
03088                 result |= pixelColorNolock (dst, xmcy, ypcx, color);
03089                 result |= pixelColorNolock (dst, xpcy, ypcx, color);
03090                 result |= pixelColorNolock (dst, xmcy, ymcx, color);
03091                 result |= pixelColorNolock (dst, xpcy, ymcx, color);
03092             } else if (cx == 0) {
03093                 result |= pixelColorNolock (dst, xmcy, y, color);
03094                 result |= pixelColorNolock (dst, xpcy, y, color);
03095             }
03096             /*
03097             * Update
03098             */
03099             if (df < 0) {
03100                 df += d_e;
03101                 d_e += 2;
03102                 d_se += 2;
03103             } else {
03104                 df += d_se;
03105                 d_e += 2;
03106                 d_se += 4;
03107                 cy--;
03108             }
03109             cx++;
03110         } while (cx <= cy);
03111 
03112     }               /* Alpha check */
03113 
03114     /* Unlock surface */
03115     if (SDL_MUSTLOCK(dst)) {
03116         SDL_UnlockSurface(dst);
03117     }
03118 
03119     return (result);
03120 }
03121 
03136 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03137 {
03138     /*
03139     * Draw
03140     */
03141     return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03142 }
03143 
03144 /* ----- Arc */
03145 
03163 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
03164 {
03165     Sint16 left, right, top, bottom;
03166     int result;
03167     Sint16 xx, yy, x2, y2;
03168     Sint16 cx = 0;
03169     Sint16 cy = rad;
03170     Sint16 df = 1 - rad;
03171     Sint16 d_e = 3;
03172     Sint16 d_se = -2 * rad + 5;
03173     Sint16 xpcx, xmcx, xpcy, xmcy;
03174     Sint16 ypcy, ymcy, ypcx, ymcx;
03175     Uint8 *colorptr;
03176     Uint8 drawoct;
03177     int startoct, endoct, oct, stopval_start = 0, stopval_end;
03178     double temp = 0;
03179 
03180     /*
03181     * Check visibility of clipping rectangle
03182     */
03183     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03184         return(0);
03185     }
03186 
03187     /*
03188     * Sanity check radius
03189     */
03190     if (rad < 0) {
03191         return (-1);
03192     }
03193 
03194     /*
03195     * Special case for rad=0 - draw a point
03196     */
03197     if (rad == 0) {
03198         return (pixelColor(dst, x, y, color));
03199     }
03200 
03201     /*
03202     * Get arc's circle and clipping boundary and
03203     * test if bounding box of circle is visible
03204     */
03205     x2 = x + rad;
03206     left = dst->clip_rect.x;
03207     if (x2<left) {
03208         return(0);
03209     }
03210     xx = x - rad;
03211     right = dst->clip_rect.x + dst->clip_rect.w - 1;
03212     if (xx>right) {
03213         return(0);
03214     }
03215     y2 = y + rad;
03216     top = dst->clip_rect.y;
03217     if (y2<top) {
03218         return(0);
03219     }
03220     yy = y - rad;
03221     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03222     if (yy>bottom) {
03223         return(0);
03224     }
03225 
03226     /* Octant labelling
03227     //  \ 5 | 6 /
03228     //   \  |  /
03229     //  4 \ | / 7
03230     //     \|/
03231     //------+------ +x
03232     //     /|\
03233     //  3 / | \ 0
03234     //   /  |  \
03235     //  / 2 | 1 \
03236     //      +y              */
03237 
03238     /* Initially reset bitmask to 0x00000000
03239      * the set whether or not to keep drawing a given octant.
03240      * For example: 0x00111100 means we're drawing in octants 2-5 */
03241     drawoct = 0;
03242 
03243     /*
03244     * Fixup angles
03245     */
03246     start %= 360;
03247     end %= 360;
03248     /* 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. */
03249     while (start < 0) start += 360;
03250     while (end < 0) end += 360;
03251     start %= 360;
03252     end %= 360;
03253 
03254     /* now, we find which octants we're drawing in. */
03255     startoct = start / 45;
03256     endoct = end / 45;
03257     oct = startoct - 1; /* we increment as first step in loop */
03258 
03259     /* stopval_start, stopval_end; */
03260     /* what values of cx to stop at. */
03261     do {
03262         oct = (oct + 1) % 8;
03263 
03264         if (oct == startoct) {
03265             /* need to compute stopval_start for this octant.  Look at picture above if this is unclear */
03266             switch (oct)
03267             {
03268             case 0:
03269             case 3:
03270                 temp = sin(start * M_PI / 180);
03271                 break;
03272             case 1:
03273             case 6:
03274                 temp = cos(start * M_PI / 180);
03275                 break;
03276             case 2:
03277             case 5:
03278                 temp = -cos(start * M_PI / 180);
03279                 break;
03280             case 4:
03281             case 7:
03282                 temp = -sin(start * M_PI / 180);
03283                 break;
03284             }
03285             temp *= rad;
03286             stopval_start = (int)temp; /* always round down. */
03287             /* This isn't arbitrary, but requires graph paper to explain well. */
03288             /* The basic idea is that we're always changing drawoct after we draw, so we */
03289             /* stop immediately after we render the last sensible pixel at x = ((int)temp). */
03290 
03291             /* and whether to draw in this octant initially */
03292             if (oct % 2) drawoct |= (1 << oct); /* this is basically like saying drawoct[oct] = true, if drawoct were a bool array */
03293             else         drawoct &= 255 - (1 << oct); /* this is basically like saying drawoct[oct] = false */
03294         }
03295         if (oct == endoct) {
03296             /* need to compute stopval_end for this octant */
03297             switch (oct)
03298             {
03299             case 0:
03300             case 3:
03301                 temp = sin(end * M_PI / 180);
03302                 break;
03303             case 1:
03304             case 6:
03305                 temp = cos(end * M_PI / 180);
03306                 break;
03307             case 2:
03308             case 5:
03309                 temp = -cos(end * M_PI / 180);
03310                 break;
03311             case 4:
03312             case 7:
03313                 temp = -sin(end * M_PI / 180);
03314                 break;
03315             }
03316             temp *= rad;
03317             stopval_end = (int)temp;
03318 
03319             /* and whether to draw in this octant initially */
03320             if (startoct == endoct) {
03321                 /* note:      we start drawing, stop, then start again in this case */
03322                 /* otherwise: we only draw in this octant, so initialize it to false, it will get set back to true */
03323                 if (start > end) {
03324                     /* unfortunately, if we're in the same octant and need to draw over the whole circle, */
03325                     /* we need to set the rest to true, because the while loop will end at the bottom. */
03326                     drawoct = 255;
03327                 } else {
03328                     drawoct &= 255 - (1 << oct);
03329                 }
03330             }
03331             else if (oct % 2) drawoct &= 255 - (1 << oct);
03332             else              drawoct |= (1 << oct);
03333         } else if (oct != startoct) { /* already verified that it's != endoct */
03334             drawoct |= (1 << oct); /* draw this entire segment */
03335         }
03336     } while (oct != endoct);
03337 
03338     /* so now we have what octants to draw and when to draw them.  all that's left is the actual raster code. */
03339 
03340     /* Lock surface */
03341     if (SDL_MUSTLOCK(dst)) {
03342         if (SDL_LockSurface(dst) < 0) {
03343             return (-1);
03344         }
03345     }
03346 
03347     /*
03348     * Draw arc
03349     */
03350     result = 0;
03351 
03352     /*
03353     * Alpha Check
03354     */
03355     if ((color & 255) == 255) {
03356 
03357         /*
03358         * No Alpha - direct memory writes
03359         */
03360 
03361         /*
03362         * Setup color
03363         */
03364         colorptr = (Uint8 *) & color;
03365         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
03366             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
03367         } else {
03368             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
03369         }
03370 
03371         /*
03372         * Draw
03373         */
03374         do {
03375             ypcy = y + cy;
03376             ymcy = y - cy;
03377             if (cx > 0) {
03378                 xpcx = x + cx;
03379                 xmcx = x - cx;
03380                 if (drawoct & 4)  result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
03381                 if (drawoct & 2)  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
03382                 if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
03383                 if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
03384             } else {
03385                 if (drawoct & 6)  result |= fastPixelColorNolock(dst, x, ypcy, color);
03386                 if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color);
03387             }
03388 
03389             xpcy = x + cy;
03390             xmcy = x - cy;
03391             if (cx > 0 && cx != cy) {
03392                 ypcx = y + cx;
03393                 ymcx = y - cx;
03394                 if (drawoct & 8)   result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
03395                 if (drawoct & 1)   result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
03396                 if (drawoct & 16)  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
03397                 if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
03398             } else if (cx == 0) {
03399                 if (drawoct & 24)  result |= fastPixelColorNolock(dst, xmcy, y, color);
03400                 if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color);
03401             }
03402 
03403             /*
03404             * Update whether we're drawing an octant
03405             */
03406             if (stopval_start == cx) {
03407                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
03408                 else drawoct |= (1 << startoct);
03409             }
03410             if (stopval_end == cx) {
03411                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
03412                 else drawoct |= (1 << endoct);
03413             }
03414 
03415             /*
03416             * Update pixels
03417             */
03418             if (df < 0) {
03419                 df += d_e;
03420                 d_e += 2;
03421                 d_se += 2;
03422             } else {
03423                 df += d_se;
03424                 d_e += 2;
03425                 d_se += 4;
03426                 cy--;
03427             }
03428             cx++;
03429         } while (cx <= cy);
03430 
03431         /*
03432         * Unlock surface
03433         */
03434         SDL_UnlockSurface(dst);
03435 
03436     } else {
03437 
03438         /*
03439         * Using Alpha - blended pixel blits
03440         */
03441 
03442         do {
03443             ypcy = y + cy;
03444             ymcy = y - cy;
03445             if (cx > 0) {
03446                 xpcx = x + cx;
03447                 xmcx = x - cx;
03448 
03449                 if (drawoct & 4)  result |= pixelColorNolock(dst, xmcx, ypcy, color);
03450                 if (drawoct & 2)  result |= pixelColorNolock(dst, xpcx, ypcy, color);
03451                 if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
03452                 if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
03453             } else {
03454                 if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
03455                 if (drawoct & 6)  result |= pixelColorNolock(dst, x, ypcy, color);
03456             }
03457 
03458             xpcy = x + cy;
03459             xmcy = x - cy;
03460             if (cx > 0 && cx != cy) {
03461                 ypcx = y + cx;
03462                 ymcx = y - cx;
03463                 if (drawoct & 8)   result |= pixelColorNolock(dst, xmcy, ypcx, color);
03464                 if (drawoct & 1)   result |= pixelColorNolock(dst, xpcy, ypcx, color);
03465                 if (drawoct & 16)  result |= pixelColorNolock(dst, xmcy, ymcx, color);
03466                 if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
03467             } else if (cx == 0) {
03468                 if (drawoct & 24)  result |= pixelColorNolock(dst, xmcy, y, color);
03469                 if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
03470             }
03471 
03472             /*
03473             * Update whether we're drawing an octant
03474             */
03475             if (stopval_start == cx) {
03476                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
03477                 else                           drawoct |= (1 << startoct);
03478             }
03479             if (stopval_end == cx) {
03480                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
03481                 else                         drawoct |= (1 << endoct);
03482             }
03483 
03484             /*
03485             * Update pixels
03486             */
03487             if (df < 0) {
03488                 df += d_e;
03489                 d_e += 2;
03490                 d_se += 2;
03491             } else {
03492                 df += d_se;
03493                 d_e += 2;
03494                 d_se += 4;
03495                 cy--;
03496             }
03497             cx++;
03498         } while (cx <= cy);
03499 
03500     }               /* Alpha check */
03501 
03502     /* Unlock surface */
03503     if (SDL_MUSTLOCK(dst)) {
03504         SDL_UnlockSurface(dst);
03505     }
03506 
03507     return (result);
03508 }
03509 
03526 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03527 {
03528     /*
03529     * Draw
03530     */
03531     return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03532 }
03533 
03534 /* ----- AA Circle */
03535 
03536 
03550 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
03551 {
03552     return (aaellipseColor(dst, x, y, rad, rad, color));
03553 }
03554 
03569 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03570 {
03571     /*
03572     * Draw
03573     */
03574     return (aaellipseColor
03575         (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03576 }
03577 
03578 /* ----- Filled Circle */
03579 
03594 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
03595 {
03596     Sint16 left, right, top, bottom;
03597     int result;
03598     Sint16 xx, yy, x2, y2;
03599     Sint16 cx = 0;
03600     Sint16 cy = rad;
03601     Sint16 ocx = (Sint16) 0xffff;
03602     Sint16 ocy = (Sint16) 0xffff;
03603     Sint16 df = 1 - rad;
03604     Sint16 d_e = 3;
03605     Sint16 d_se = -2 * rad + 5;
03606     Sint16 xpcx, xmcx, xpcy, xmcy;
03607     Sint16 ypcy, ymcy, ypcx, ymcx;
03608 
03609     /*
03610     * Check visibility of clipping rectangle
03611     */
03612     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03613         return(0);
03614     }
03615 
03616     /*
03617     * Sanity check radius
03618     */
03619     if (rad < 0) {
03620         return (-1);
03621     }
03622 
03623     /*
03624     * Special case for rad=0 - draw a point
03625     */
03626     if (rad == 0) {
03627         return (pixelColor(dst, x, y, color));
03628     }
03629 
03630     /*
03631     * Get circle and clipping boundary and
03632     * test if bounding box of circle is visible
03633     */
03634     x2 = x + rad;
03635     left = dst->clip_rect.x;
03636     if (x2<left) {
03637         return(0);
03638     }
03639     xx = x - rad;
03640     right = dst->clip_rect.x + dst->clip_rect.w - 1;
03641     if (xx>right) {
03642         return(0);
03643     }
03644     y2 = y + rad;
03645     top = dst->clip_rect.y;
03646     if (y2<top) {
03647         return(0);
03648     }
03649     yy = y - rad;
03650     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03651     if (yy>bottom) {
03652         return(0);
03653     }
03654 
03655     /*
03656     * Draw
03657     */
03658     result = 0;
03659     do {
03660         xpcx = x + cx;
03661         xmcx = x - cx;
03662         xpcy = x + cy;
03663         xmcy = x - cy;
03664         if (ocy != cy) {
03665             if (cy > 0) {
03666                 ypcy = y + cy;
03667                 ymcy = y - cy;
03668                 result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
03669                 result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
03670             } else {
03671                 result |= hlineColor(dst, xmcx, xpcx, y, color);
03672             }
03673             ocy = cy;
03674         }
03675         if (ocx != cx) {
03676             if (cx != cy) {
03677                 if (cx > 0) {
03678                     ypcx = y + cx;
03679                     ymcx = y - cx;
03680                     result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
03681                     result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
03682                 } else {
03683                     result |= hlineColor(dst, xmcy, xpcy, y, color);
03684                 }
03685             }
03686             ocx = cx;
03687         }
03688         /*
03689         * Update
03690         */
03691         if (df < 0) {
03692             df += d_e;
03693             d_e += 2;
03694             d_se += 2;
03695         } else {
03696             df += d_se;
03697             d_e += 2;
03698             d_se += 4;
03699             cy--;
03700         }
03701         cx++;
03702     } while (cx <= cy);
03703 
03704     return (result);
03705 }
03706 
03721 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03722 {
03723     /*
03724     * Draw
03725     */
03726     return (filledCircleColor
03727         (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03728 }
03729 
03730 /* ----- Ellipse */
03731 
03747 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
03748 {
03749     Sint16 left, right, top, bottom;
03750     int result;
03751     Sint16 xx, yy, x2, y2;
03752     int ix, iy;
03753     int h, i, j, k;
03754     int oh, oi, oj, ok;
03755     int xmh, xph, ypk, ymk;
03756     int xmi, xpi, ymj, ypj;
03757     int xmj, xpj, ymi, ypi;
03758     int xmk, xpk, ymh, yph;
03759     Uint8 *colorptr;
03760 
03761     /*
03762     * Check visibility of clipping rectangle
03763     */
03764     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03765         return(0);
03766     }
03767 
03768     /*
03769     * Sanity check radii
03770     */
03771     if ((rx < 0) || (ry < 0)) {
03772         return (-1);
03773     }
03774 
03775     /*
03776     * Special case for rx=0 - draw a vline
03777     */
03778     if (rx == 0) {
03779         return (vlineColor(dst, x, y - ry, y + ry, color));
03780     }
03781     /*
03782     * Special case for ry=0 - draw a hline
03783     */
03784     if (ry == 0) {
03785         return (hlineColor(dst, x - rx, x + rx, y, color));
03786     }
03787 
03788     /*
03789     * Get circle and clipping boundary and
03790     * test if bounding box of circle is visible
03791     */
03792     x2 = x + rx;
03793     left = dst->clip_rect.x;
03794     if (x2<left) {
03795         return(0);
03796     }
03797     xx = x - rx;
03798     right = dst->clip_rect.x + dst->clip_rect.w - 1;
03799     if (xx>right) {
03800         return(0);
03801     }
03802     y2 = y + ry;
03803     top = dst->clip_rect.y;
03804     if (y2<top) {
03805         return(0);
03806     }
03807     yy = y - ry;
03808     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03809     if (yy>bottom) {
03810         return(0);
03811     }
03812 
03813     /*
03814     * Init vars
03815     */
03816     oh = oi = oj = ok = 0xFFFF;
03817 
03818     /*
03819     * Draw
03820     */
03821     result = 0;
03822 
03823     /* Lock surface */
03824     if (SDL_MUSTLOCK(dst)) {
03825         if (SDL_LockSurface(dst) < 0) {
03826             return (-1);
03827         }
03828     }
03829 
03830     /*
03831     * Check alpha
03832     */
03833     if ((color & 255) == 255) {
03834 
03835         /*
03836         * No Alpha - direct memory writes
03837         */
03838 
03839         /*
03840         * Setup color
03841         */
03842         colorptr = (Uint8 *) & color;
03843         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
03844             color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
03845         } else {
03846             color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
03847         }
03848 
03849 
03850         if (rx > ry) {
03851             ix = 0;
03852             iy = rx * 64;
03853 
03854             do {
03855                 h = (ix + 32) >> 6;
03856                 i = (iy + 32) >> 6;
03857                 j = (h * ry) / rx;
03858                 k = (i * ry) / rx;
03859 
03860                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
03861                     xph = x + h;
03862                     xmh = x - h;
03863                     if (k > 0) {
03864                         ypk = y + k;
03865                         ymk = y - k;
03866                         result |= fastPixelColorNolock(dst, xmh, ypk, color);
03867                         result |= fastPixelColorNolock(dst, xph, ypk, color);
03868                         result |= fastPixelColorNolock(dst, xmh, ymk, color);
03869                         result |= fastPixelColorNolock(dst, xph, ymk, color);
03870                     } else {
03871                         result |= fastPixelColorNolock(dst, xmh, y, color);
03872                         result |= fastPixelColorNolock(dst, xph, y, color);
03873                     }
03874                     ok = k;
03875                     xpi = x + i;
03876                     xmi = x - i;
03877                     if (j > 0) {
03878                         ypj = y + j;
03879                         ymj = y - j;
03880                         result |= fastPixelColorNolock(dst, xmi, ypj, color);
03881                         result |= fastPixelColorNolock(dst, xpi, ypj, color);
03882                         result |= fastPixelColorNolock(dst, xmi, ymj, color);
03883                         result |= fastPixelColorNolock(dst, xpi, ymj, color);
03884                     } else {
03885                         result |= fastPixelColorNolock(dst, xmi, y, color);
03886                         result |= fastPixelColorNolock(dst, xpi, y, color);
03887                     }
03888                     oj = j;
03889                 }
03890 
03891                 ix = ix + iy / rx;
03892                 iy = iy - ix / rx;
03893 
03894             } while (i > h);
03895         } else {
03896             ix = 0;
03897             iy = ry * 64;
03898 
03899             do {
03900                 h = (ix + 32) >> 6;
03901                 i = (iy + 32) >> 6;
03902                 j = (h * rx) / ry;
03903                 k = (i * rx) / ry;
03904 
03905                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
03906                     xmj = x - j;
03907                     xpj = x + j;
03908                     if (i > 0) {
03909                         ypi = y + i;
03910                         ymi = y - i;
03911                         result |= fastPixelColorNolock(dst, xmj, ypi, color);
03912                         result |= fastPixelColorNolock(dst, xpj, ypi, color);
03913                         result |= fastPixelColorNolock(dst, xmj, ymi, color);
03914                         result |= fastPixelColorNolock(dst, xpj, ymi, color);
03915                     } else {
03916                         result |= fastPixelColorNolock(dst, xmj, y, color);
03917                         result |= fastPixelColorNolock(dst, xpj, y, color);
03918                     }
03919                     oi = i;
03920                     xmk = x - k;
03921                     xpk = x + k;
03922                     if (h > 0) {
03923                         yph = y + h;
03924                         ymh = y - h;
03925                         result |= fastPixelColorNolock(dst, xmk, yph, color);
03926                         result |= fastPixelColorNolock(dst, xpk, yph, color);
03927                         result |= fastPixelColorNolock(dst, xmk, ymh, color);
03928                         result |= fastPixelColorNolock(dst, xpk, ymh, color);
03929                     } else {
03930                         result |= fastPixelColorNolock(dst, xmk, y, color);
03931                         result |= fastPixelColorNolock(dst, xpk, y, color);
03932                     }
03933                     oh = h;
03934                 }
03935 
03936                 ix = ix + iy / ry;
03937                 iy = iy - ix / ry;
03938 
03939             } while (i > h);
03940         }
03941 
03942     } else {
03943 
03944         if (rx > ry) {
03945             ix = 0;
03946             iy = rx * 64;
03947 
03948             do {
03949                 h = (ix + 32) >> 6;
03950                 i = (iy + 32) >> 6;
03951                 j = (h * ry) / rx;
03952                 k = (i * ry) / rx;
03953 
03954                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
03955                     xph = x + h;
03956                     xmh = x - h;
03957                     if (k > 0) {
03958                         ypk = y + k;
03959                         ymk = y - k;
03960                         result |= pixelColorNolock (dst, xmh, ypk, color);
03961                         result |= pixelColorNolock (dst, xph, ypk, color);
03962                         result |= pixelColorNolock (dst, xmh, ymk, color);
03963                         result |= pixelColorNolock (dst, xph, ymk, color);
03964                     } else {
03965                         result |= pixelColorNolock (dst, xmh, y, color);
03966                         result |= pixelColorNolock (dst, xph, y, color);
03967                     }
03968                     ok = k;
03969                     xpi = x + i;
03970                     xmi = x - i;
03971                     if (j > 0) {
03972                         ypj = y + j;
03973                         ymj = y - j;
03974                         result |= pixelColorNolock (dst, xmi, ypj, color);
03975                         result |= pixelColorNolock (dst, xpi, ypj, color);
03976                         result |= pixelColorNolock (dst, xmi, ymj, color);
03977                         result |= pixelColor(dst, xpi, ymj, color);
03978                     } else {
03979                         result |= pixelColorNolock (dst, xmi, y, color);
03980                         result |= pixelColorNolock (dst, xpi, y, color);
03981                     }
03982                     oj = j;
03983                 }
03984 
03985                 ix = ix + iy / rx;
03986                 iy = iy - ix / rx;
03987 
03988             } while (i > h);
03989         } else {
03990             ix = 0;
03991             iy = ry * 64;
03992 
03993             do {
03994                 h = (ix + 32) >> 6;
03995                 i = (iy + 32) >> 6;
03996                 j = (h * rx) / ry;
03997                 k = (i * rx) / ry;
03998 
03999                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
04000                     xmj = x - j;
04001                     xpj = x + j;
04002                     if (i > 0) {
04003                         ypi = y + i;
04004                         ymi = y - i;
04005                         result |= pixelColorNolock (dst, xmj, ypi, color);
04006                         result |= pixelColorNolock (dst, xpj, ypi, color);
04007                         result |= pixelColorNolock (dst, xmj, ymi, color);
04008                         result |= pixelColorNolock (dst, xpj, ymi, color);
04009                     } else {
04010                         result |= pixelColorNolock (dst, xmj, y, color);
04011                         result |= pixelColorNolock (dst, xpj, y, color);
04012                     }
04013                     oi = i;
04014                     xmk = x - k;
04015                     xpk = x + k;
04016                     if (h > 0) {
04017                         yph = y + h;
04018                         ymh = y - h;
04019                         result |= pixelColorNolock (dst, xmk, yph, color);
04020                         result |= pixelColorNolock (dst, xpk, yph, color);
04021                         result |= pixelColorNolock (dst, xmk, ymh, color);
04022                         result |= pixelColorNolock (dst, xpk, ymh, color);
04023                     } else {
04024                         result |= pixelColorNolock (dst, xmk, y, color);
04025                         result |= pixelColorNolock (dst, xpk, y, color);
04026                     }
04027                     oh = h;
04028                 }
04029 
04030                 ix = ix + iy / ry;
04031                 iy = iy - ix / ry;
04032 
04033             } while (i > h);
04034         }
04035 
04036     }               /* Alpha check */
04037 
04038     /* Unlock surface */
04039     if (SDL_MUSTLOCK(dst)) {
04040         SDL_UnlockSurface(dst);
04041     }
04042 
04043     return (result);
04044 }
04045 
04061 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04062 {
04063     /*
04064     * Draw
04065     */
04066     return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04067 }
04068 
04069 /* ----- AA Ellipse */
04070 
04086 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
04087 {
04088     Sint16 left, right, top, bottom;
04089     Sint16 xx1, yy1, x2, y2;
04090     int i;
04091     int a2, b2, ds, dt, dxt, t, s, d;
04092     Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
04093     float cp;
04094     double sab;
04095     Uint8 weight, iweight;
04096     int result;
04097 
04098     /*
04099     * Check visibility of clipping rectangle
04100     */
04101     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04102         return(0);
04103     }
04104 
04105     /*
04106     * Sanity check radii
04107     */
04108     if ((rx < 0) || (ry < 0)) {
04109         return (-1);
04110     }
04111 
04112     /*
04113     * Special case for rx=0 - draw a vline
04114     */
04115     if (rx == 0) {
04116         return (vlineColor(dst, x, y - ry, y + ry, color));
04117     }
04118     /*
04119     * Special case for ry=0 - draw an hline
04120     */
04121     if (ry == 0) {
04122         return (hlineColor(dst, x - rx, x + rx, y, color));
04123     }
04124 
04125     /*
04126     * Get circle and clipping boundary and
04127     * test if bounding box of circle is visible
04128     */
04129     x2 = x + rx;
04130     left = dst->clip_rect.x;
04131     if (x2<left) {
04132         return(0);
04133     }
04134     xx1 = x - rx;
04135     right = dst->clip_rect.x + dst->clip_rect.w - 1;
04136     if (xx1>right) {
04137         return(0);
04138     }
04139     y2 = y + ry;
04140     top = dst->clip_rect.y;
04141     if (y2<top) {
04142         return(0);
04143     }
04144     yy1 = y - ry;
04145     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04146     if (yy1>bottom) {
04147         return(0);
04148     }
04149 
04150     /* Variable setup */
04151     a2 = rx * rx;
04152     b2 = ry * ry;
04153 
04154     ds = 2 * a2;
04155     dt = 2 * b2;
04156 
04157     xc2 = 2 * x;
04158     yc2 = 2 * y;
04159 
04160     sab = sqrt(a2 + b2);
04161     od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
04162     dxt = (Sint16)lrint((double)a2 / sab) + od;
04163 
04164     t = 0;
04165     s = -2 * a2 * ry;
04166     d = 0;
04167 
04168     xp = x;
04169     yp = y - ry;
04170 
04171     /* Lock surface */
04172     if (SDL_MUSTLOCK(dst)) {
04173         if (SDL_LockSurface(dst) < 0) {
04174             return (-1);
04175         }
04176     }
04177 
04178     /* Draw */
04179     result = 0;
04180 
04181     /* "End points" */
04182     result |= pixelColorNolock(dst, xp, yp, color);
04183     result |= pixelColorNolock(dst, xc2 - xp, yp, color);
04184     result |= pixelColorNolock(dst, xp, yc2 - yp, color);
04185     result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
04186 
04187     for (i = 1; i <= dxt; i++) {
04188         xp--;
04189         d += t - b2;
04190 
04191         if (d >= 0)
04192             ys = yp - 1;
04193         else if ((d - s - a2) > 0) {
04194             if ((2 * d - s - a2) >= 0)
04195                 ys = yp + 1;
04196             else {
04197                 ys = yp;
04198                 yp++;
04199                 d -= s + a2;
04200                 s += ds;
04201             }
04202         } else {
04203             yp++;
04204             ys = yp + 1;
04205             d -= s + a2;
04206             s += ds;
04207         }
04208 
04209         t -= dt;
04210 
04211         /* Calculate alpha */
04212         if (s != 0.0) {
04213             cp = abs(d) / abs(s);
04214             if (cp > 1.0) {
04215                 cp = 1.0;
04216             }
04217         } else {
04218             cp = 1.0;
04219         }
04220 
04221         /* Calculate weights */
04222         weight = (Uint8) (cp * 255);
04223         iweight = 255 - weight;
04224 
04225         /* Upper half */
04226         xx = xc2 - xp;
04227         result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
04228         result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
04229 
04230         result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
04231         result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
04232 
04233         /* Lower half */
04234         yy = yc2 - yp;
04235         result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
04236         result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
04237 
04238         yy = yc2 - ys;
04239         result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
04240         result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
04241     }
04242 
04243     /* Replaces original approximation code dyt = abs(yp - yc); */
04244     dyt = (Sint16)lrint((double)b2 / sab ) + od;
04245 
04246     for (i = 1; i <= dyt; i++) {
04247         yp++;
04248         d -= s + a2;
04249 
04250         if (d <= 0)
04251             xs = xp + 1;
04252         else if ((d + t - b2) < 0) {
04253             if ((2 * d + t - b2) <= 0)
04254                 xs = xp - 1;
04255             else {
04256                 xs = xp;
04257                 xp--;
04258                 d += t - b2;
04259                 t -= dt;
04260             }
04261         } else {
04262             xp--;
04263             xs = xp - 1;
04264             d += t - b2;
04265             t -= dt;
04266         }
04267 
04268         s += ds;
04269 
04270         /* Calculate alpha */
04271         if (t != 0.0) {
04272             cp = abs(d) / abs(t);
04273             if (cp > 1.0) {
04274                 cp = 1.0;
04275             }
04276         } else {
04277             cp = 1.0;
04278         }
04279 
04280         /* Calculate weight */
04281         weight = (Uint8) (cp * 255);
04282         iweight = 255 - weight;
04283 
04284         /* Left half */
04285         xx = xc2 - xp;
04286         yy = yc2 - yp;
04287         result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
04288         result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
04289 
04290         result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
04291         result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
04292 
04293         /* Right half */
04294         xx = xc2 - xs;
04295         result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
04296         result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
04297 
04298         result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
04299         result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
04300 
04301     }
04302 
04303     /* Unlock surface */
04304     if (SDL_MUSTLOCK(dst)) {
04305         SDL_UnlockSurface(dst);
04306     }
04307 
04308     return (result);
04309 }
04310 
04326 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04327 {
04328     /*
04329     * Draw
04330     */
04331     return (aaellipseColor
04332         (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04333 }
04334 
04335 /* ---- Filled Ellipse */
04336 
04337 /* Note: */
04338 /* Based on algorithm from sge library with multiple-hline draw removal */
04339 /* and other speedup changes. */
04340 
04356 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
04357 {
04358     Sint16 left, right, top, bottom;
04359     int result;
04360     Sint16 xx, yy, x2, y2;
04361     int ix, iy;
04362     int h, i, j, k;
04363     int oh, oi, oj, ok;
04364     int xmh, xph;
04365     int xmi, xpi;
04366     int xmj, xpj;
04367     int xmk, xpk;
04368 
04369     /*
04370     * Check visibility of clipping rectangle
04371     */
04372     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04373         return(0);
04374     }
04375 
04376     /*
04377     * Sanity check radii
04378     */
04379     if ((rx < 0) || (ry < 0)) {
04380         return (-1);
04381     }
04382 
04383     /*
04384     * Special case for rx=0 - draw a vline
04385     */
04386     if (rx == 0) {
04387         return (vlineColor(dst, x, y - ry, y + ry, color));
04388     }
04389     /*
04390     * Special case for ry=0 - draw a hline
04391     */
04392     if (ry == 0) {
04393         return (hlineColor(dst, x - rx, x + rx, y, color));
04394     }
04395 
04396     /*
04397     * Get circle and clipping boundary and
04398     * test if bounding box of circle is visible
04399     */
04400     x2 = x + rx;
04401     left = dst->clip_rect.x;
04402     if (x2<left) {
04403         return(0);
04404     }
04405     xx = x - rx;
04406     right = dst->clip_rect.x + dst->clip_rect.w - 1;
04407     if (xx>right) {
04408         return(0);
04409     }
04410     y2 = y + ry;
04411     top = dst->clip_rect.y;
04412     if (y2<top) {
04413         return(0);
04414     }
04415     yy = y - ry;
04416     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04417     if (yy>bottom) {
04418         return(0);
04419     }
04420 
04421     /*
04422     * Init vars
04423     */
04424     oh = oi = oj = ok = 0xFFFF;
04425 
04426     /*
04427     * Draw
04428     */
04429     result = 0;
04430     if (rx > ry) {
04431         ix = 0;
04432         iy = rx * 64;
04433 
04434         do {
04435             h = (ix + 32) >> 6;
04436             i = (iy + 32) >> 6;
04437             j = (h * ry) / rx;
04438             k = (i * ry) / rx;
04439 
04440             if ((ok != k) && (oj != k)) {
04441                 xph = x + h;
04442                 xmh = x - h;
04443                 if (k > 0) {
04444                     result |= hlineColor(dst, xmh, xph, y + k, color);
04445                     result |= hlineColor(dst, xmh, xph, y - k, color);
04446                 } else {
04447                     result |= hlineColor(dst, xmh, xph, y, color);
04448                 }
04449                 ok = k;
04450             }
04451             if ((oj != j) && (ok != j) && (k != j)) {
04452                 xmi = x - i;
04453                 xpi = x + i;
04454                 if (j > 0) {
04455                     result |= hlineColor(dst, xmi, xpi, y + j, color);
04456                     result |= hlineColor(dst, xmi, xpi, y - j, color);
04457                 } else {
04458                     result |= hlineColor(dst, xmi, xpi, y, color);
04459                 }
04460                 oj = j;
04461             }
04462 
04463             ix = ix + iy / rx;
04464             iy = iy - ix / rx;
04465 
04466         } while (i > h);
04467     } else {
04468         ix = 0;
04469         iy = ry * 64;
04470 
04471         do {
04472             h = (ix + 32) >> 6;
04473             i = (iy + 32) >> 6;
04474             j = (h * rx) / ry;
04475             k = (i * rx) / ry;
04476 
04477             if ((oi != i) && (oh != i)) {
04478                 xmj = x - j;
04479                 xpj = x + j;
04480                 if (i > 0) {
04481                     result |= hlineColor(dst, xmj, xpj, y + i, color);
04482                     result |= hlineColor(dst, xmj, xpj, y - i, color);
04483                 } else {
04484                     result |= hlineColor(dst, xmj, xpj, y, color);
04485                 }
04486                 oi = i;
04487             }
04488             if ((oh != h) && (oi != h) && (i != h)) {
04489                 xmk = x - k;
04490                 xpk = x + k;
04491                 if (h > 0) {
04492                     result |= hlineColor(dst, xmk, xpk, y + h, color);
04493                     result |= hlineColor(dst, xmk, xpk, y - h, color);
04494                 } else {
04495                     result |= hlineColor(dst, xmk, xpk, y, color);
04496                 }
04497                 oh = h;
04498             }
04499 
04500             ix = ix + iy / ry;
04501             iy = iy - ix / ry;
04502 
04503         } while (i > h);
04504     }
04505 
04506     return (result);
04507 }
04508 
04524 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04525 {
04526     /*
04527     * Draw
04528     */
04529     return (filledEllipseColor
04530         (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04531 }
04532 
04533 /* ----- pie */
04534 
04551 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
04552 {
04553     Sint16 left, right, top, bottom;
04554     Sint16 xx, yy, x2, y2;
04555     int result;
04556     double angle, start_angle, end_angle;
04557     double deltaAngle;
04558     double dr;
04559     int numpoints, i;
04560     Sint16 *vx, *vy;
04561 
04562     /*
04563     * Check visibility of clipping rectangle
04564     */
04565     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04566         return(0);
04567     }
04568 
04569     /*
04570     * Sanity check radii
04571     */
04572     if (rad < 0) {
04573         return (-1);
04574     }
04575 
04576     /*
04577     * Fixup angles
04578     */
04579     start = start % 360;
04580     end = end % 360;
04581 
04582     /*
04583     * Special case for rad=0 - draw a point
04584     */
04585     if (rad == 0) {
04586         return (pixelColor(dst, x, y, color));
04587     }
04588 
04589     /*
04590     * Clip against circle, not pie (not 100% optimal).
04591     * Get pie's circle and clipping boundary and
04592     * test if bounding box of circle is visible
04593     */
04594     x2 = x + rad;
04595     left = dst->clip_rect.x;
04596     if (x2<left) {
04597         return(0);
04598     }
04599     xx = x - rad;
04600     right = dst->clip_rect.x + dst->clip_rect.w - 1;
04601     if (xx>right) {
04602         return(0);
04603     }
04604     y2 = y + rad;
04605     top = dst->clip_rect.y;
04606     if (y2<top) {
04607         return(0);
04608     }
04609     yy = y - rad;
04610     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04611     if (yy>bottom) {
04612         return(0);
04613     }
04614 
04615     /*
04616     * Variable setup
04617     */
04618     dr = (double) rad;
04619     deltaAngle = 3.0 / dr;
04620     start_angle = (double) start *(2.0 * M_PI / 360.0);
04621     end_angle = (double) end *(2.0 * M_PI / 360.0);
04622     if (start > end) {
04623         end_angle += (2.0 * M_PI);
04624     }
04625 
04626     /* We will always have at least 2 points */
04627     numpoints = 2;
04628 
04629     /* Count points (rather than calculating it) */
04630     angle = start_angle;
04631     while (angle < end_angle) {
04632         angle += deltaAngle;
04633         numpoints++;
04634     }
04635 
04636     /* Allocate combined vertex array */
04637     vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
04638     if (vx == NULL) {
04639         return (-1);
04640     }
04641 
04642     /* Update point to start of vy */
04643     vy += numpoints;
04644 
04645     /* Center */
04646     vx[0] = x;
04647     vy[0] = y;
04648 
04649     /* First vertex */
04650     angle = start_angle;
04651     vx[1] = x + (int) (dr * cos(angle));
04652     vy[1] = y + (int) (dr * sin(angle));
04653 
04654     if (numpoints<3)
04655     {
04656         result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
04657     }
04658     else
04659     {
04660         /* Calculate other vertices */
04661         i = 2;
04662         angle = start_angle;
04663         while (angle < end_angle) {
04664             angle += deltaAngle;
04665             if (angle>end_angle)
04666             {
04667                 angle = end_angle;
04668             }
04669             vx[i] = x + (int) (dr * cos(angle));
04670             vy[i] = y + (int) (dr * sin(angle));
04671             i++;
04672         }
04673 
04674         /* Draw */
04675         if (filled) {
04676             result = filledPolygonColor(dst, vx, vy, numpoints, color);
04677         } else {
04678             result = polygonColor(dst, vx, vy, numpoints, color);
04679         }
04680     }
04681 
04682     /* Free combined vertex array */
04683     free(vx);
04684 
04685     return (result);
04686 }
04687 
04701 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
04702              Sint16 start, Sint16 end, Uint32 color)
04703 {
04704     return (_pieColor(dst, x, y, rad, start, end, color, 0));
04705 
04706 }
04707 
04724 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
04725             Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04726 {
04727     return (_pieColor(dst, x, y, rad, start, end,
04728         ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
04729 
04730 }
04731 
04745 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
04746 {
04747     return (_pieColor(dst, x, y, rad, start, end, color, 1));
04748 }
04749 
04766 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
04767                   Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04768 {
04769     return (_pieColor(dst, x, y, rad, start, end,
04770         ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
04771 }
04772 
04773 /* ------ Trigon */
04774 
04791 int trigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04792 {
04793     Sint16 vx[3];
04794     Sint16 vy[3];
04795 
04796     vx[0]=x;
04797     vx[1]=x2;
04798     vx[2]=x3;
04799     vy[0]=y;
04800     vy[1]=y2;
04801     vy[2]=y3;
04802 
04803     return(polygonColor(dst,vx,vy,3,color));
04804 }
04805 
04823 int trigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04824                Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04825 {
04826     Sint16 vx[3];
04827     Sint16 vy[3];
04828 
04829     vx[0]=x;
04830     vx[1]=x2;
04831     vx[2]=x3;
04832     vy[0]=y;
04833     vy[1]=y2;
04834     vy[2]=y3;
04835 
04836     return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
04837 }
04838 
04839 /* ------ AA-Trigon */
04840 
04857 int aatrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04858 {
04859     Sint16 vx[3];
04860     Sint16 vy[3];
04861 
04862     vx[0]=x;
04863     vx[1]=x2;
04864     vx[2]=x3;
04865     vy[0]=y;
04866     vy[1]=y2;
04867     vy[2]=y3;
04868 
04869     return(aapolygonColor(dst,vx,vy,3,color));
04870 }
04871 
04889 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04890                  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04891 {
04892     Sint16 vx[3];
04893     Sint16 vy[3];
04894 
04895     vx[0]=x;
04896     vx[1]=x2;
04897     vx[2]=x3;
04898     vy[0]=y;
04899     vy[1]=y2;
04900     vy[2]=y3;
04901 
04902     return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
04903 }
04904 
04905 /* ------ Filled Trigon */
04906 
04923 int filledTrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04924 {
04925     Sint16 vx[3];
04926     Sint16 vy[3];
04927 
04928     vx[0]=x;
04929     vx[1]=x2;
04930     vx[2]=x3;
04931     vy[0]=y;
04932     vy[1]=y2;
04933     vy[2]=y3;
04934 
04935     return(filledPolygonColor(dst,vx,vy,3,color));
04936 }
04937 
04957 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04958                      Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04959 {
04960     Sint16 vx[3];
04961     Sint16 vy[3];
04962 
04963     vx[0]=x;
04964     vx[1]=x2;
04965     vx[2]=x3;
04966     vy[0]=y;
04967     vy[1]=y2;
04968     vy[2]=y3;
04969 
04970     return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
04971 }
04972 
04973 /* ---- Polygon */
04974 
04986 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
04987 {
04988     int result;
04989     int i;
04990     const Sint16 *x, *y, *x2, *y2;
04991 
04992     /*
04993     * Check visibility of clipping rectangle
04994     */
04995     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04996         return(0);
04997     }
04998 
04999     /*
05000     * Vertex array NULL check
05001     */
05002     if (vx == NULL) {
05003         return (-1);
05004     }
05005     if (vy == NULL) {
05006         return (-1);
05007     }
05008 
05009     /*
05010     * Sanity check
05011     */
05012     if (n < 3) {
05013         return (-1);
05014     }
05015 
05016     /*
05017     * Pointer setup
05018     */
05019     x = x2 = vx;
05020     y = y2 = vy;
05021     x2++;
05022     y2++;
05023 
05024     /*
05025     * Draw
05026     */
05027     result = 0;
05028     for (i = 1; i < n; i++) {
05029         result |= lineColor(dst, *x, *y, *x2, *y2, color);
05030         x = x2;
05031         y = y2;
05032         x2++;
05033         y2++;
05034     }
05035     result |= lineColor(dst, *x, *y, *vx, *vy, color);
05036 
05037     return (result);
05038 }
05039 
05054 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05055 {
05056     /*
05057     * Draw
05058     */
05059     return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
05060 }
05061 
05062 /* ---- AA-Polygon */
05063 
05075 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
05076 {
05077     int result;
05078     int i;
05079     const Sint16 *x, *y, *x2, *y2;
05080 
05081     /*
05082     * Check visibility of clipping rectangle
05083     */
05084     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05085         return(0);
05086     }
05087 
05088     /*
05089     * Vertex array NULL check
05090     */
05091     if (vx == NULL) {
05092         return (-1);
05093     }
05094     if (vy == NULL) {
05095         return (-1);
05096     }
05097 
05098     /*
05099     * Sanity check
05100     */
05101     if (n < 3) {
05102         return (-1);
05103     }
05104 
05105     /*
05106     * Pointer setup
05107     */
05108     x = x2 = vx;
05109     y = y2 = vy;
05110     x2++;
05111     y2++;
05112 
05113     /*
05114     * Draw
05115     */
05116     result = 0;
05117     for (i = 1; i < n; i++) {
05118         result |= _aalineColor(dst, *x, *y, *x2, *y2, color, 0);
05119         x = x2;
05120         y = y2;
05121         x2++;
05122         y2++;
05123     }
05124     result |= _aalineColor(dst, *x, *y, *vx, *vy, color, 0);
05125 
05126     return (result);
05127 }
05128 
05143 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05144 {
05145     /*
05146     * Draw
05147     */
05148     return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
05149 }
05150 
05151 /* ---- Filled Polygon */
05152 
05161 int _gfxPrimitivesCompareInt(const void *a, const void *b)
05162 {
05163     return (*(const int *) a) - (*(const int *) b);
05164 }
05165 
05171 static int *gfxPrimitivesPolyIntsGlobal = NULL;
05172 
05178 static int gfxPrimitivesPolyAllocatedGlobal = 0;
05179 
05195 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
05196 {
05197     int result;
05198     int i;
05199     int y, xa, xb;
05200     int miny, maxy;
05201     int xx, yy;
05202     int x2, y2;
05203     int ind1, ind2;
05204     int ints;
05205     int *gfxPrimitivesPolyInts = NULL;
05206     int gfxPrimitivesPolyAllocated = 0;
05207 
05208     /*
05209     * Check visibility of clipping rectangle
05210     */
05211     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05212         return(0);
05213     }
05214 
05215     /*
05216     * Vertex array NULL check
05217     */
05218     if (vx == NULL) {
05219         return (-1);
05220     }
05221     if (vy == NULL) {
05222         return (-1);
05223     }
05224 
05225     /*
05226     * Sanity check number of edges
05227     */
05228     if (n < 3) {
05229         return -1;
05230     }
05231 
05232     /*
05233     * Map polygon cache
05234     */
05235     if ((polyInts==NULL) || (polyAllocated==NULL)) {
05236         /* Use global cache */
05237         gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
05238         gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
05239     } else {
05240         /* Use local cache */
05241         gfxPrimitivesPolyInts = *polyInts;
05242         gfxPrimitivesPolyAllocated = *polyAllocated;
05243     }
05244 
05245     /*
05246     * Allocate temp array, only grow array
05247     */
05248     if (!gfxPrimitivesPolyAllocated) {
05249         gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
05250         gfxPrimitivesPolyAllocated = n;
05251     } else {
05252         if (gfxPrimitivesPolyAllocated < n) {
05253             gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
05254             gfxPrimitivesPolyAllocated = n;
05255         }
05256     }
05257 
05258     /*
05259     * Check temp array
05260     */
05261     if (gfxPrimitivesPolyInts==NULL) {
05262         gfxPrimitivesPolyAllocated = 0;
05263     }
05264 
05265     /*
05266     * Update cache variables
05267     */
05268     if ((polyInts==NULL) || (polyAllocated==NULL)) {
05269         gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
05270         gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
05271     } else {
05272         *polyInts = gfxPrimitivesPolyInts;
05273         *polyAllocated = gfxPrimitivesPolyAllocated;
05274     }
05275 
05276     /*
05277     * Check temp array again
05278     */
05279     if (gfxPrimitivesPolyInts==NULL) {
05280         return(-1);
05281     }
05282 
05283     /*
05284     * Determine Y maxima
05285     */
05286     miny = vy[0];
05287     maxy = vy[0];
05288     for (i = 1; (i < n); i++) {
05289         if (vy[i] < miny) {
05290             miny = vy[i];
05291         } else if (vy[i] > maxy) {
05292             maxy = vy[i];
05293         }
05294     }
05295 
05296     /*
05297     * Draw, scanning y
05298     */
05299     result = 0;
05300     for (y = miny; (y <= maxy); y++) {
05301         ints = 0;
05302         for (i = 0; (i < n); i++) {
05303             if (!i) {
05304                 ind1 = n - 1;
05305                 ind2 = 0;
05306             } else {
05307                 ind1 = i - 1;
05308                 ind2 = i;
05309             }
05310             yy = vy[ind1];
05311             y2 = vy[ind2];
05312             if (yy < y2) {
05313                 xx = vx[ind1];
05314                 x2 = vx[ind2];
05315             } else if (yy > y2) {
05316                 y2 = vy[ind1];
05317                 yy = vy[ind2];
05318                 x2 = vx[ind1];
05319                 xx = vx[ind2];
05320             } else {
05321                 continue;
05322             }
05323             if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) {
05324                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx);
05325             }
05326         }
05327 
05328         qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
05329 
05330         for (i = 0; (i < ints); i += 2) {
05331             xa = gfxPrimitivesPolyInts[i] + 1;
05332             xa = (xa >> 16) + ((xa & 32768) >> 15);
05333             xb = gfxPrimitivesPolyInts[i+1] - 1;
05334             xb = (xb >> 16) + ((xb & 32768) >> 15);
05335             result |= hlineColor(dst, xa, xb, y, color);
05336         }
05337     }
05338 
05339     return (result);
05340 }
05341 
05360 int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
05361 {
05362     /*
05363     * Draw
05364     */
05365     return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
05366 }
05367 
05382 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
05383 {
05384     /*
05385     * Draw
05386     */
05387     return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
05388 }
05389 
05404 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05405 {
05406     /*
05407     * Draw
05408     */
05409     return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
05410 }
05411 
05425 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy)
05426 {
05427     Sint16 left, right, top, bottom;
05428     Sint16 w;
05429     Sint16 xtmp;
05430     int result = 0;
05431     int texture_x_walker;
05432     int texture_y_start;
05433     SDL_Rect source_rect,dst_rect;
05434     int pixels_written,write_width;
05435 
05436     /*
05437     * Check visibility of clipping rectangle
05438     */
05439     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05440         return(0);
05441     }
05442 
05443     /*
05444     * Swap x1, x2 if required to ensure x1<=x2
05445     */
05446     if (x1 > x2) {
05447         xtmp = x1;
05448         x1 = x2;
05449         x2 = xtmp;
05450     }
05451 
05452     /*
05453     * Get clipping boundary and
05454     * check visibility of hline
05455     */
05456     left = dst->clip_rect.x;
05457     if (x2<left) {
05458         return(0);
05459     }
05460     right = dst->clip_rect.x + dst->clip_rect.w - 1;
05461     if (x1>right) {
05462         return(0);
05463     }
05464     top = dst->clip_rect.y;
05465     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
05466     if ((y<top) || (y>bottom)) {
05467         return (0);
05468     }
05469 
05470     /*
05471     * Clip x
05472     */
05473     if (x1 < left) {
05474         x1 = left;
05475     }
05476     if (x2 > right) {
05477         x2 = right;
05478     }
05479 
05480     /*
05481     * Calculate width to draw
05482     */
05483     w = x2 - x1 + 1;
05484 
05485     /*
05486     * Determine where in the texture we start drawing
05487     */
05488     texture_x_walker =   (x1 - texture_dx)  % texture->w;
05489     if (texture_x_walker < 0){
05490         texture_x_walker = texture->w + texture_x_walker ;
05491     }
05492 
05493     texture_y_start = (y + texture_dy) % texture->h;
05494     if (texture_y_start < 0){
05495         texture_y_start = texture->h + texture_y_start;
05496     }
05497 
05498     source_rect.y = texture_y_start;
05499     source_rect.x = texture_x_walker;
05500     source_rect.h = 1;
05501 
05502     dst_rect.y = y;
05503 
05504     if (w <= texture->w -texture_x_walker){
05505         source_rect.w = w;
05506         source_rect.x = texture_x_walker;
05507         dst_rect.x= x1;
05508         result = (SDL_BlitSurface  (texture, &source_rect , dst, &dst_rect) == 0);
05509     } else {
05510         pixels_written = texture->w  - texture_x_walker;
05511         source_rect.w = pixels_written;
05512         source_rect.x = texture_x_walker;
05513         dst_rect.x= x1;
05514         result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
05515         write_width = texture->w;
05516 
05517         source_rect.x = 0;
05518         while (pixels_written < w){
05519             if (write_width >= w - pixels_written) {
05520                 write_width =  w - pixels_written;
05521             }
05522             source_rect.w = write_width;
05523             dst_rect.x = x1 + pixels_written;
05524             result  |= (SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) == 0);
05525             pixels_written += write_width;
05526         }
05527     }
05528 
05529     return result;
05530 }
05531 
05555 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n,
05556                       SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
05557 {
05558     int result;
05559     int i;
05560     int y, xa, xb;
05561     int minx,maxx,miny, maxy;
05562     int xx, yy;
05563     int x2, y2;
05564     int ind1, ind2;
05565     int ints;
05566     int *gfxPrimitivesPolyInts = NULL;
05567     int gfxPrimitivesPolyAllocated = 0;
05568 
05569     /*
05570     * Check visibility of clipping rectangle
05571     */
05572     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05573         return(0);
05574     }
05575 
05576     /*
05577     * Sanity check number of edges
05578     */
05579     if (n < 3) {
05580         return -1;
05581     }
05582 
05583     /*
05584     * Map polygon cache
05585     */
05586     if ((polyInts==NULL) || (polyAllocated==NULL)) {
05587         /* Use global cache */
05588         gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
05589         gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
05590     } else {
05591         /* Use local cache */
05592         gfxPrimitivesPolyInts = *polyInts;
05593         gfxPrimitivesPolyAllocated = *polyAllocated;
05594     }
05595 
05596     /*
05597     * Allocate temp array, only grow array
05598     */
05599     if (!gfxPrimitivesPolyAllocated) {
05600         gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
05601         gfxPrimitivesPolyAllocated = n;
05602     } else {
05603         if (gfxPrimitivesPolyAllocated < n) {
05604             gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
05605             gfxPrimitivesPolyAllocated = n;
05606         }
05607     }
05608 
05609     /*
05610     * Check temp array
05611     */
05612     if (gfxPrimitivesPolyInts==NULL) {
05613         gfxPrimitivesPolyAllocated = 0;
05614     }
05615 
05616     /*
05617     * Update cache variables
05618     */
05619     if ((polyInts==NULL) || (polyAllocated==NULL)) {
05620         gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
05621         gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
05622     } else {
05623         *polyInts = gfxPrimitivesPolyInts;
05624         *polyAllocated = gfxPrimitivesPolyAllocated;
05625     }
05626 
05627     /*
05628     * Check temp array again
05629     */
05630     if (gfxPrimitivesPolyInts==NULL) {
05631         return(-1);
05632     }
05633 
05634     /*
05635     * Determine X,Y minima,maxima
05636     */
05637     miny = vy[0];
05638     maxy = vy[0];
05639     minx = vx[0];
05640     maxx = vx[0];
05641     for (i = 1; (i < n); i++) {
05642         if (vy[i] < miny) {
05643             miny = vy[i];
05644         } else if (vy[i] > maxy) {
05645             maxy = vy[i];
05646         }
05647         if (vx[i] < minx) {
05648             minx = vx[i];
05649         } else if (vx[i] > maxx) {
05650             maxx = vx[i];
05651         }
05652     }
05653     if (maxx <0 || minx > dst->w){
05654         return -1;
05655     }
05656     if (maxy <0 || miny > dst->h){
05657         return -1;
05658     }
05659 
05660     /*
05661     * Draw, scanning y
05662     */
05663     result = 0;
05664     for (y = miny; (y <= maxy); y++) {
05665         ints = 0;
05666         for (i = 0; (i < n); i++) {
05667             if (!i) {
05668                 ind1 = n - 1;
05669                 ind2 = 0;
05670             } else {
05671                 ind1 = i - 1;
05672                 ind2 = i;
05673             }
05674             yy = vy[ind1];
05675             y2 = vy[ind2];
05676             if (yy < y2) {
05677                 xx = vx[ind1];
05678                 x2 = vx[ind2];
05679             } else if (yy > y2) {
05680                 y2 = vy[ind1];
05681                 yy = vy[ind2];
05682                 x2 = vx[ind1];
05683                 xx = vx[ind2];
05684             } else {
05685                 continue;
05686             }
05687             if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) {
05688                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx);
05689             }
05690         }
05691 
05692         qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
05693 
05694         for (i = 0; (i < ints); i += 2) {
05695             xa = gfxPrimitivesPolyInts[i] + 1;
05696             xa = (xa >> 16) + ((xa & 32768) >> 15);
05697             xb = gfxPrimitivesPolyInts[i+1] - 1;
05698             xb = (xb >> 16) + ((xb & 32768) >> 15);
05699             result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
05700         }
05701     }
05702 
05703     return (result);
05704 }
05705 
05722 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
05723 {
05724     /*
05725     * Draw
05726     */
05727     return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
05728 }
05729 
05730 
05740 double _evaluateBezier (double *data, int ndata, double t)
05741 {
05742     double mu, result;
05743     int n,k,kn,nn,nkn;
05744     double blend,muk,munk;
05745 
05746     /* Sanity check bounds */
05747     if (t<0.0) {
05748         return(data[0]);
05749     }
05750     if (t>=(double)ndata) {
05751         return(data[ndata-1]);
05752     }
05753 
05754     /* Adjust t to the range 0.0 to 1.0 */
05755     mu=t/(double)ndata;
05756 
05757     /* Calculate interpolate */
05758     n=ndata-1;
05759     result=0.0;
05760     muk = 1;
05761     munk = pow(1-mu,(double)n);
05762     for (k=0;k<=n;k++) {
05763         nn = n;
05764         kn = k;
05765         nkn = n - k;
05766         blend = muk * munk;
05767         muk *= mu;
05768         munk /= (1-mu);
05769         while (nn >= 1) {
05770             blend *= nn;
05771             nn--;
05772             if (kn > 1) {
05773                 blend /= (double)kn;
05774                 kn--;
05775             }
05776             if (nkn > 1) {
05777                 blend /= (double)nkn;
05778                 nkn--;
05779             }
05780         }
05781         result += data[k] * blend;
05782     }
05783 
05784     return (result);
05785 }
05786 
05799 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
05800 {
05801     int result;
05802     int i;
05803     double *x, *y, t, stepsize;
05804     Sint16 xx, yy, x2, y2;
05805 
05806     /*
05807     * Sanity check
05808     */
05809     if (n < 3) {
05810         return (-1);
05811     }
05812     if (s < 2) {
05813         return (-1);
05814     }
05815 
05816     /*
05817     * Variable setup
05818     */
05819     stepsize=(double)1.0/(double)s;
05820 
05821     /* Transfer vertices into float arrays */
05822     if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
05823         return(-1);
05824     }
05825     if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
05826         free(x);
05827         return(-1);
05828     }
05829     for (i=0; i<n; i++) {
05830         x[i]=vx[i];
05831         y[i]=vy[i];
05832     }
05833     x[n]=vx[0];
05834     y[n]=vy[0];
05835 
05836     /*
05837     * Draw
05838     */
05839     result = 0;
05840     t=0.0;
05841     xx=(Sint16)lrint(_evaluateBezier(x,n+1,t));
05842     yy=(Sint16)lrint(_evaluateBezier(y,n+1,t));
05843     for (i = 0; i <= (n*s); i++) {
05844         t += stepsize;
05845         x2=_evaluateBezier(x,n,t);
05846         y2=_evaluateBezier(y,n,t);
05847         result |= lineColor(dst, xx, yy, x2, y2, color);
05848         xx = x2;
05849         yy = y2;
05850     }
05851 
05852     /* Clean up temporary array */
05853     free(x);
05854     free(y);
05855 
05856     return (result);
05857 }
05858 
05874 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05875 {
05876     /*
05877     * Draw
05878     */
05879     return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
05880 }
05881 static void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
05882 {
05883     int p;
05884     d1 = -d1;
05885 
05886     /*
05887     * Lock the surface
05888     */
05889     if (SDL_MUSTLOCK(m->dst)) {
05890         SDL_LockSurface(m->dst);
05891     }
05892 
05893     for (p = 0; p <= m->u; p++) {
05894 
05895         pixelColorNolock(m->dst, x, y, m->color);
05896 
05897         if (d1 <= m->kt) {
05898             if (m->oct2 == 0) {
05899                 x++;
05900             } else {
05901                 if (m->quad4 == 0) {
05902                     y++;
05903                 } else {
05904                     y--;
05905                 }
05906             }
05907             d1 += m->kv;
05908         } else {
05909             x++;
05910             if (m->quad4 == 0) {
05911                 y++;
05912             } else {
05913                 y--;
05914             }
05915             d1 += m->kd;
05916         }
05917     }
05918 
05919     /* Unlock surface */
05920     if (SDL_MUSTLOCK(m->dst)) {
05921         SDL_UnlockSurface(m->dst);
05922     }
05923 
05924     m->tempx = x;
05925     m->tempy = y;
05926 }
05927 
05943 static void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter,
05944                       Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
05945                       Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
05946 {
05947     int atemp1, atemp2;
05948     int ftmp1, ftmp2;
05949     Uint16 m1x, m1y, m2x, m2y;
05950     Uint16 fix, fiy, lax, lay, curx, cury;
05951     Uint16 px[4], py[4];
05952     SDL_gfxBresenhamIterator b;
05953 
05954     if (miter > 1) {
05955         if (m->first1x != -32768) {
05956             fix = (m->first1x + m->first2x) / 2;
05957             fiy = (m->first1y + m->first2y) / 2;
05958             lax = (m->last1x + m->last2x) / 2;
05959             lay = (m->last1y + m->last2y) / 2;
05960             curx = (ml1x + ml2x) / 2;
05961             cury = (ml1y + ml2y) / 2;
05962 
05963             atemp1 = (fix - curx);
05964             atemp2 = (fiy - cury);
05965             ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
05966             atemp1 = (lax - curx);
05967             atemp2 = (lay - cury);
05968             ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
05969 
05970             if (ftmp1 <= ftmp2) {
05971                 m1x = m->first1x;
05972                 m1y = m->first1y;
05973                 m2x = m->first2x;
05974                 m2y = m->first2y;
05975             } else {
05976                 m1x = m->last1x;
05977                 m1y = m->last1y;
05978                 m2x = m->last2x;
05979                 m2y = m->last2y;
05980             }
05981 
05982             atemp1 = (m2x - ml2x);
05983             atemp2 = (m2y - ml2y);
05984             ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
05985             atemp1 = (m2x - ml2bx);
05986             atemp2 = (m2y - ml2by);
05987             ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
05988 
05989             if (ftmp2 >= ftmp1) {
05990                 ftmp1 = ml2bx;
05991                 ftmp2 = ml2by;
05992                 ml2bx = ml2x;
05993                 ml2by = ml2y;
05994                 ml2x = ftmp1;
05995                 ml2y = ftmp2;
05996                 ftmp1 = ml1bx;
05997                 ftmp2 = ml1by;
05998                 ml1bx = ml1x;
05999                 ml1by = ml1y;
06000                 ml1x = ftmp1;
06001                 ml1y = ftmp2;
06002             }
06003 
06004             /*
06005             * Lock the surface
06006             */
06007             if (SDL_MUSTLOCK(m->dst)) {
06008                 SDL_LockSurface(m->dst);
06009             }
06010 
06011             _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
06012             do {
06013                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06014             } while (_bresenhamIterate(&b)==0);
06015 
06016             _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
06017             do {
06018                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06019             } while (_bresenhamIterate(&b)==0);
06020 
06021             _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
06022             do {
06023                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06024             } while (_bresenhamIterate(&b)==0);
06025 
06026             _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
06027             do {
06028                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06029             } while (_bresenhamIterate(&b)==0);
06030 
06031             /* Unlock surface */
06032             if (SDL_MUSTLOCK(m->dst)) {
06033                 SDL_UnlockSurface(m->dst);
06034             }
06035 
06036             px[0] = m1x;
06037             px[1] = m2x;
06038             px[2] = ml1bx;
06039             px[3] = ml2bx;
06040             py[0] = m1y;
06041             py[1] = m2y;
06042             py[2] = ml1by;
06043             py[3] = ml2by;
06044             polygonColor(m->dst, (const Sint16 *) px, (const Sint16 *) py, 4, m->color);
06045         }
06046     }
06047 
06048     m->last1x = ml1x;
06049     m->last1y = ml1y;
06050     m->last2x = ml2x;
06051     m->last2y = ml2y;
06052     m->first1x = ml1bx;
06053     m->first1y = ml1by;
06054     m->first2x = ml2bx;
06055     m->first2y = ml2by;
06056 }
06057 
06058 
06059 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
06060 
06075 static void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
06076 {
06077     float offset = width / 2.f;
06078 
06079     Sint16 temp;
06080     Sint16 ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
06081 
06082     int d0, d1;     /* difference terms d0=perpendicular to line, d1=along line */
06083 
06084     int q;          /* pel counter,q=perpendicular to line */
06085     int tmp;
06086 
06087     int dd;         /* distance along line */
06088     int tk;         /* thickness threshold */
06089     double ang;     /* angle for initial point calculation */
06090     double sang, cang;
06091 
06092     ml2by = ml2bx = ml1by = ml1bx = ml2y = ml2x = ml1y = ml1x = 0;
06093 
06094     /* Initialisation */
06095     m->u = x2 - x;  /* delta x */
06096     m->v = y2 - y;  /* delta y */
06097 
06098     if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
06099         temp = x;
06100         x = x2;
06101         x2 = temp;
06102         temp = y;
06103         y = y2;
06104         y = temp;
06105         m->u *= -1;
06106         m->v *= -1;
06107     }
06108 
06109     if (m->v < 0) { /* swap to 1st quadrant and flag */
06110         m->v *= -1;
06111         m->quad4 = 1;
06112     } else {
06113         m->quad4 = 0;
06114     }
06115 
06116     if (m->v > m->u) {  /* swap things if in 2 octant */
06117         tmp = m->u;
06118         m->u = m->v;
06119         m->v = tmp;
06120         m->oct2 = 1;
06121     } else {
06122         m->oct2 = 0;
06123     }
06124 
06125     m->ku = m->u + m->u;    /* change in l for square shift */
06126     m->kv = m->v + m->v;    /* change in d for square shift */
06127     m->kd = m->kv - m->ku;  /* change in d for diagonal shift */
06128     m->kt = m->u - m->kv;   /* diag/square decision threshold */
06129 
06130     d0 = 0;
06131     d1 = 0;
06132     dd = 0;
06133 
06134     ang = atan((double) m->v / (double) m->u);  /* calc new initial point - offset both sides of ideal */
06135     sang = sin(ang);
06136     cang = cos(ang);
06137 
06138     if (m->oct2 == 0) {
06139         ptx = x + (Sint16)lrint(offset * sang);
06140         if (m->quad4 == 0) {
06141             pty = y - (Sint16)lrint(offset * cang);
06142         } else {
06143             pty = y + (Sint16)lrint(offset * cang);
06144         }
06145     } else {
06146         ptx = x - (Sint16)lrint(offset * cang);
06147         if (m->quad4 == 0) {
06148             pty = y + (Sint16)lrint(offset * sang);
06149         } else {
06150             pty = y - (Sint16)lrint(offset * sang);
06151         }
06152     }
06153 
06154     /* used here for constant thickness line */
06155     tk = (int) (4. * HYPOT(ptx - x, pty - y) * HYPOT(m->u, m->v));
06156 
06157     if (miter == 0) {
06158         m->first1x = -32768;
06159         m->first1y = -32768;
06160         m->first2x = -32768;
06161         m->first2y = -32768;
06162         m->last1x = -32768;
06163         m->last1y = -32768;
06164         m->last2x = -32768;
06165         m->last2y = -32768;
06166     }
06167 
06168     for (q = 0; dd <= tk; q++) {    /* outer loop, stepping perpendicular to line */
06169 
06170         _murphyParaline(m, ptx, pty, d1);   /* call to inner loop - right edge */
06171         if (q == 0) {
06172             ml1x = ptx;
06173             ml1y = pty;
06174             ml1bx = m->tempx;
06175             ml1by = m->tempy;
06176         } else {
06177             ml2x = ptx;
06178             ml2y = pty;
06179             ml2bx = m->tempx;
06180             ml2by = m->tempy;
06181         }
06182         if (d0 < m->kt) {   /* square move */
06183             if (m->oct2 == 0) {
06184                 if (m->quad4 == 0) {
06185                     pty++;
06186                 } else {
06187                     pty--;
06188                 }
06189             } else {
06190                 ptx++;
06191             }
06192         } else {    /* diagonal move */
06193             dd += m->kv;
06194             d0 -= m->ku;
06195             if (d1 < m->kt) {   /* normal diagonal */
06196                 if (m->oct2 == 0) {
06197                     ptx--;
06198                     if (m->quad4 == 0) {
06199                         pty++;
06200                     } else {
06201                         pty--;
06202                     }
06203                 } else {
06204                     ptx++;
06205                     if (m->quad4 == 0) {
06206                         pty--;
06207                     } else {
06208                         pty++;
06209                     }
06210                 }
06211                 d1 += m->kv;
06212             } else {    /* double square move, extra parallel line */
06213                 if (m->oct2 == 0) {
06214                     ptx--;
06215                 } else {
06216                     if (m->quad4 == 0) {
06217                         pty--;
06218                     } else {
06219                         pty++;
06220                     }
06221                 }
06222                 d1 += m->kd;
06223                 if (dd > tk) {
06224                     _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
06225                     return; /* breakout on the extra line */
06226                 }
06227                 _murphyParaline(m, ptx, pty, d1);
06228                 if (m->oct2 == 0) {
06229                     if (m->quad4 == 0) {
06230                         pty++;
06231                     } else {
06232 
06233                         pty--;
06234                     }
06235                 } else {
06236                     ptx++;
06237                 }
06238             }
06239         }
06240         dd += m->ku;
06241         d0 += m->kv;
06242     }
06243 
06244     _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
06245 }
06246 
06247 
06261 int thickLineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
06262 {
06263     SDL_gfxMurphyIterator m;
06264 
06265     if (dst == NULL) return -1;
06266     if (width < 1) return -1;
06267 
06268     m.dst = dst;
06269     m.color = color;
06270 
06271     _murphyWideline(&m, x, y, x2, y2, width, 0);
06272     _murphyWideline(&m, x, y, x2, y2, width, 1);
06273 
06274     return(0);
06275 }
06276 
06293 int thickLineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
06294 {
06295     return (thickLineColor(dst, x, y, x2, y2, width,
06296         ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
06297 }