Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

SDL_gfxPrimitives.c

Go to the documentation of this file.
00001 /* 
00002 
00003  SDL_gfxPrimitives - Graphics primitives for SDL surfaces
00004 
00005  LGPL (c) A. Schiffler
00006 
00007 */
00008 
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <math.h>
00012 #include <string.h>
00013 
00014 #include "SDL_gfxPrimitives.h"
00015 
00016 /* -===================- */
00017 
00018 /* ----- Defines for pixel clipping tests */
00019 
00020 #define clip_xmin(surface) surface->clip_rect.x
00021 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
00022 #define clip_ymin(surface) surface->clip_rect.y
00023 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
00024 
00025 /* ----- Pixel - fast, no blending, no locking, clipping */
00026 
00027 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00028 {
00029     int bpp;
00030     Uint8 *p;
00031 
00032     /*
00033      * Honor clipping setup at pixel level 
00034      */
00035     if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
00036 
00037    /*
00038     * Get destination format 
00039     */
00040    bpp = dst->format->BytesPerPixel;
00041    p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00042    switch (bpp) {
00043    case 1:
00044        *p = color;
00045        break;
00046    case 2:
00047        *(Uint16 *) p = color;
00048        break;
00049    case 3:
00050        if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00051       p[0] = (color >> 16) & 0xff;
00052       p[1] = (color >> 8) & 0xff;
00053       p[2] = color & 0xff;
00054        } else {
00055       p[0] = color & 0xff;
00056       p[1] = (color >> 8) & 0xff;
00057       p[2] = (color >> 16) & 0xff;
00058        }
00059        break;
00060    case 4:
00061        *(Uint32 *) p = color;
00062        break;
00063    }        /* switch */
00064 
00065 
00066     }
00067 
00068     return (0);
00069 }
00070 
00071 /* ----- Pixel - fast, no blending, no locking, no clipping */
00072 
00073 /* (faster but dangerous, make sure we stay in surface bounds) */
00074 
00075 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00076 {
00077     int bpp;
00078     Uint8 *p;
00079 
00080     /*
00081      * Get destination format 
00082      */
00083     bpp = dst->format->BytesPerPixel;
00084     p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00085     switch (bpp) {
00086     case 1:
00087    *p = color;
00088    break;
00089     case 2:
00090    *(Uint16 *) p = color;
00091    break;
00092     case 3:
00093    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00094        p[0] = (color >> 16) & 0xff;
00095        p[1] = (color >> 8) & 0xff;
00096        p[2] = color & 0xff;
00097    } else {
00098        p[0] = color & 0xff;
00099        p[1] = (color >> 8) & 0xff;
00100        p[2] = (color >> 16) & 0xff;
00101    }
00102    break;
00103     case 4:
00104    *(Uint32 *) p = color;
00105    break;
00106     }          /* switch */
00107 
00108     return (0);
00109 }
00110 
00111 /* ----- Pixel - fast, no blending, locking, clipping */
00112 
00113 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00114 {
00115     int result;
00116 
00117     /*
00118      * Lock the surface 
00119      */
00120     if (SDL_MUSTLOCK(dst)) {
00121    if (SDL_LockSurface(dst) < 0) {
00122        return (-1);
00123    }
00124     }
00125 
00126     result = fastPixelColorNolock(dst, x, y, color);
00127 
00128     /*
00129      * Unlock surface 
00130      */
00131     if (SDL_MUSTLOCK(dst)) {
00132    SDL_UnlockSurface(dst);
00133     }
00134 
00135     return (result);
00136 }
00137 
00138 /* ----- Pixel - fast, no blending, locking, RGB input */
00139 
00140 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00141 {
00142     Uint32 color;
00143 
00144     /*
00145      * Setup color 
00146      */
00147     color = SDL_MapRGBA(dst->format, r, g, b, a);
00148 
00149     /*
00150      * Draw 
00151      */
00152     return (fastPixelColor(dst, x, y, color));
00153 
00154 }
00155 
00156 /* ----- Pixel - fast, no blending, no locking RGB input */
00157 
00158 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00159 {
00160     Uint32 color;
00161 
00162     /*
00163      * Setup color 
00164      */
00165     color = SDL_MapRGBA(dst->format, r, g, b, a);
00166 
00167     /*
00168      * Draw 
00169      */
00170     return (fastPixelColorNolock(dst, x, y, color));
00171 }
00172 
00173 /* PutPixel routine with alpha blending, input color in destination format */
00174 
00175 /* New, faster routine - default blending pixel */
00176 
00177 int _putPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
00178 {
00179     Uint32 Rmask = surface->format->Rmask, Gmask =
00180    surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
00181     Uint32 R, G, B, A = 0;
00182 
00183     if (x >= clip_xmin(surface) && x <= clip_xmax(surface)
00184    && y >= clip_ymin(surface) && y <= clip_ymax(surface)) {
00185 
00186    switch (surface->format->BytesPerPixel) {
00187    case 1:{    /* Assuming 8-bpp */
00188       if (alpha == 255) {
00189           *((Uint8 *) surface->pixels + y * surface->pitch + x) = color;
00190       } else {
00191           Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x;
00192 
00193           Uint8 dR = surface->format->palette->colors[*pixel].r;
00194           Uint8 dG = surface->format->palette->colors[*pixel].g;
00195           Uint8 dB = surface->format->palette->colors[*pixel].b;
00196           Uint8 sR = surface->format->palette->colors[color].r;
00197           Uint8 sG = surface->format->palette->colors[color].g;
00198           Uint8 sB = surface->format->palette->colors[color].b;
00199 
00200           dR = dR + ((sR - dR) * alpha >> 8);
00201           dG = dG + ((sG - dG) * alpha >> 8);
00202           dB = dB + ((sB - dB) * alpha >> 8);
00203 
00204           *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
00205       }
00206        }
00207        break;
00208 
00209    case 2:{    /* Probably 15-bpp or 16-bpp */
00210       if (alpha == 255) {
00211           *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color;
00212       } else {
00213           Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x;
00214           Uint32 dc = *pixel;
00215 
00216           R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
00217           G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
00218           B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
00219           if (Amask)
00220          A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
00221 
00222           *pixel = R | G | B | A;
00223       }
00224        }
00225        break;
00226 
00227    case 3:{    /* Slow 24-bpp mode, usually not used */
00228       Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
00229       Uint8 rshift8 = surface->format->Rshift / 8;
00230       Uint8 gshift8 = surface->format->Gshift / 8;
00231       Uint8 bshift8 = surface->format->Bshift / 8;
00232       Uint8 ashift8 = surface->format->Ashift / 8;
00233 
00234 
00235       if (alpha == 255) {
00236           *(pix + rshift8) = color >> surface->format->Rshift;
00237           *(pix + gshift8) = color >> surface->format->Gshift;
00238           *(pix + bshift8) = color >> surface->format->Bshift;
00239           *(pix + ashift8) = color >> surface->format->Ashift;
00240       } else {
00241           Uint8 dR, dG, dB, dA = 0;
00242           Uint8 sR, sG, sB, sA = 0;
00243 
00244           pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
00245 
00246           dR = *((pix) + rshift8);
00247           dG = *((pix) + gshift8);
00248           dB = *((pix) + bshift8);
00249           dA = *((pix) + ashift8);
00250 
00251           sR = (color >> surface->format->Rshift) & 0xff;
00252           sG = (color >> surface->format->Gshift) & 0xff;
00253           sB = (color >> surface->format->Bshift) & 0xff;
00254           sA = (color >> surface->format->Ashift) & 0xff;
00255 
00256           dR = dR + ((sR - dR) * alpha >> 8);
00257           dG = dG + ((sG - dG) * alpha >> 8);
00258           dB = dB + ((sB - dB) * alpha >> 8);
00259           dA = dA + ((sA - dA) * alpha >> 8);
00260 
00261           *((pix) + rshift8) = dR;
00262           *((pix) + gshift8) = dG;
00263           *((pix) + bshift8) = dB;
00264           *((pix) + ashift8) = dA;
00265       }
00266        }
00267        break;
00268 
00269    case 4:{    /* Probably 32-bpp */
00270       if (alpha == 255) {
00271           *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
00272       } else {
00273           Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
00274           Uint32 dc = *pixel;
00275 
00276           R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
00277           G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
00278           B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
00279           if (Amask)
00280          A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
00281 
00282           *pixel = R | G | B | A;
00283       }
00284        }
00285        break;
00286    }
00287     }
00288 
00289     return (0);
00290 }
00291 
00292 /* ----- Pixel - pixel draw with blending enabled if a<255 */
00293 
00294 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00295 {
00296     Uint8 alpha;
00297     Uint32 mcolor;
00298     int result = 0;
00299 
00300     /*
00301      * Lock the surface 
00302      */
00303     if (SDL_MUSTLOCK(dst)) {
00304    if (SDL_LockSurface(dst) < 0) {
00305        return (-1);
00306    }
00307     }
00308 
00309     /*
00310      * Setup color 
00311      */
00312     alpha = color & 0x000000ff;
00313     mcolor =
00314    SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00315           (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00316 
00317     /*
00318      * Draw 
00319      */
00320     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00321 
00322     /*
00323      * Unlock the surface 
00324      */
00325     if (SDL_MUSTLOCK(dst)) {
00326    SDL_UnlockSurface(dst);
00327     }
00328 
00329     return (result);
00330 }
00331 
00332 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00333 {
00334     Uint8 alpha;
00335     Uint32 mcolor;
00336     int result = 0;
00337 
00338     /*
00339      * Setup color 
00340      */
00341     alpha = color & 0x000000ff;
00342     mcolor =
00343    SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00344           (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00345 
00346     /*
00347      * Draw 
00348      */
00349     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00350 
00351     return (result);
00352 }
00353 
00354 
00355 /* Filled rectangle with alpha blending, color in destination format */
00356 
00357 int _filledRectAlpha(SDL_Surface * surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
00358 {
00359     Uint32 Rmask = surface->format->Rmask, Gmask =
00360    surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
00361     Uint32 R, G, B, A = 0;
00362     Sint16 x, y;
00363 
00364     switch (surface->format->BytesPerPixel) {
00365     case 1:{         /* Assuming 8-bpp */
00366        Uint8 *row, *pixel;
00367        Uint8 dR, dG, dB;
00368 
00369        Uint8 sR = surface->format->palette->colors[color].r;
00370        Uint8 sG = surface->format->palette->colors[color].g;
00371        Uint8 sB = surface->format->palette->colors[color].b;
00372 
00373        for (y = y1; y <= y2; y++) {
00374       row = (Uint8 *) surface->pixels + y * surface->pitch;
00375       for (x = x1; x <= x2; x++) {
00376           pixel = row + x;
00377 
00378           dR = surface->format->palette->colors[*pixel].r;
00379           dG = surface->format->palette->colors[*pixel].g;
00380           dB = surface->format->palette->colors[*pixel].b;
00381 
00382           dR = dR + ((sR - dR) * alpha >> 8);
00383           dG = dG + ((sG - dG) * alpha >> 8);
00384           dB = dB + ((sB - dB) * alpha >> 8);
00385 
00386           *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
00387       }
00388        }
00389    }
00390    break;
00391 
00392     case 2:{         /* Probably 15-bpp or 16-bpp */
00393        Uint16 *row, *pixel;
00394        Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
00395 
00396        for (y = y1; y <= y2; y++) {
00397       row = (Uint16 *) surface->pixels + y * surface->pitch / 2;
00398       for (x = x1; x <= x2; x++) {
00399           pixel = row + x;
00400 
00401           R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
00402           G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
00403           B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
00404           if (Amask)
00405          A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
00406 
00407           *pixel = R | G | B | A;
00408       }
00409        }
00410    }
00411    break;
00412 
00413     case 3:{         /* Slow 24-bpp mode, usually not used */
00414        Uint8 *row, *pix;
00415        Uint8 dR, dG, dB, dA;
00416        Uint8 rshift8 = surface->format->Rshift / 8;
00417        Uint8 gshift8 = surface->format->Gshift / 8;
00418        Uint8 bshift8 = surface->format->Bshift / 8;
00419        Uint8 ashift8 = surface->format->Ashift / 8;
00420 
00421        Uint8 sR = (color >> surface->format->Rshift) & 0xff;
00422        Uint8 sG = (color >> surface->format->Gshift) & 0xff;
00423        Uint8 sB = (color >> surface->format->Bshift) & 0xff;
00424        Uint8 sA = (color >> surface->format->Ashift) & 0xff;
00425 
00426        for (y = y1; y <= y2; y++) {
00427       row = (Uint8 *) surface->pixels + y * surface->pitch;
00428       for (x = x1; x <= x2; x++) {
00429           pix = row + x * 3;
00430 
00431           dR = *((pix) + rshift8);
00432           dG = *((pix) + gshift8);
00433           dB = *((pix) + bshift8);
00434           dA = *((pix) + ashift8);
00435 
00436           dR = dR + ((sR - dR) * alpha >> 8);
00437           dG = dG + ((sG - dG) * alpha >> 8);
00438           dB = dB + ((sB - dB) * alpha >> 8);
00439           dA = dA + ((sA - dA) * alpha >> 8);
00440 
00441           *((pix) + rshift8) = dR;
00442           *((pix) + gshift8) = dG;
00443           *((pix) + bshift8) = dB;
00444           *((pix) + ashift8) = dA;
00445       }
00446        }
00447 
00448    }
00449    break;
00450 
00451     case 4:{         /* Probably 32-bpp */
00452        Uint32 *row, *pixel;
00453        Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
00454 
00455        for (y = y1; y <= y2; y++) {
00456       row = (Uint32 *) surface->pixels + y * surface->pitch / 4;
00457       for (x = x1; x <= x2; x++) {
00458           pixel = row + x;
00459 
00460           R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
00461           G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
00462           B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
00463           if (Amask)
00464          A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
00465 
00466           *pixel = R | G | B | A;
00467       }
00468        }
00469    }
00470    break;
00471     }
00472 
00473     return (0);
00474 }
00475 
00476 /* Draw rectangle with alpha enabled from RGBA color. */
00477 
00478 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
00479 {
00480     Uint8 alpha;
00481     Uint32 mcolor;
00482     int result = 0;
00483 
00484     /*
00485      * Lock the surface 
00486      */
00487     if (SDL_MUSTLOCK(dst)) {
00488    if (SDL_LockSurface(dst) < 0) {
00489        return (-1);
00490    }
00491     }
00492 
00493     /*
00494      * Setup color 
00495      */
00496     alpha = color & 0x000000ff;
00497     mcolor =
00498    SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00499           (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00500 
00501     /*
00502      * Draw 
00503      */
00504     result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
00505 
00506     /*
00507      * Unlock the surface 
00508      */
00509     if (SDL_MUSTLOCK(dst)) {
00510    SDL_UnlockSurface(dst);
00511     }
00512 
00513     return (result);
00514 }
00515 
00516 /* Draw horizontal line with alpha enabled from RGBA color */
00517 
00518 int HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
00519 {
00520     return (filledRectAlpha(dst, x1, y, x2, y, color));
00521 }
00522 
00523 
00524 /* Draw vertical line with alpha enabled from RGBA color */
00525 
00526 int VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
00527 {
00528     return (filledRectAlpha(dst, x, y1, x, y2, color));
00529 }
00530 
00531 
00532 /* Pixel - using alpha weight on color for AA-drawing */
00533 
00534 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
00535 {
00536     Uint32 a;
00537 
00538     /*
00539      * Get alpha 
00540      */
00541     a = (color & (Uint32) 0x000000ff);
00542 
00543     /*
00544      * Modify Alpha by weight 
00545      */
00546     a = ((a * weight) >> 8);
00547 
00548     return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
00549 }
00550 
00551 /* Pixel - using alpha weight on color for AA-drawing - no locking */
00552 
00553 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
00554 {
00555     Uint32 a;
00556 
00557     /*
00558      * Get alpha 
00559      */
00560     a = (color & (Uint32) 0x000000ff);
00561 
00562     /*
00563      * Modify Alpha by weight 
00564      */
00565     a = ((a * weight) >> 8);
00566 
00567     return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
00568 }
00569 
00570 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00571 {
00572     Uint32 color;
00573 
00574     /*
00575      * Check Alpha 
00576      */
00577     if (a == 255) {
00578    /*
00579     * No alpha blending required 
00580     */
00581    /*
00582     * Setup color 
00583     */
00584    color = SDL_MapRGBA(dst->format, r, g, b, a);
00585    /*
00586     * Draw 
00587     */
00588    return (fastPixelColor(dst, x, y, color));
00589     } else {
00590    /*
00591     * Alpha blending required 
00592     */
00593    /*
00594     * Draw 
00595     */
00596    return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
00597     }
00598 }
00599 
00600 /* ----- Horizontal line */
00601 
00602 /* Just store color including alpha, no blending */
00603 
00604 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
00605 {
00606     Sint16 left, right, top, bottom;
00607     Uint8 *pixel, *pixellast;
00608     int dx;
00609     int pixx, pixy;
00610     Sint16 w;
00611     Sint16 xtmp;
00612     int result = -1;
00613 
00614     /*
00615      * Get clipping boundary 
00616      */
00617     left = dst->clip_rect.x;
00618     right = dst->clip_rect.x + dst->clip_rect.w - 1;
00619     top = dst->clip_rect.y;
00620     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
00621 
00622     /*
00623      * Check visibility of hline 
00624      */
00625     if ((x1<left) && (x2<left)) {
00626      return(0);
00627     }
00628     if ((x1>right) && (x2>right)) {
00629      return(0);
00630     }
00631     if ((y<top) || (y>bottom)) {
00632      return (0);
00633     }
00634 
00635     /*
00636      * Clip x 
00637      */
00638     if (x1 < left) {
00639    x1 = left;
00640     }
00641     if (x2 > right) {
00642    x2 = right;
00643     }
00644 
00645     /*
00646      * Swap x1, x2 if required 
00647      */
00648     if (x1 > x2) {
00649    xtmp = x1;
00650    x1 = x2;
00651    x2 = xtmp;
00652     }
00653 
00654     /*
00655      * Calculate width 
00656      */
00657     w = x2 - x1;
00658 
00659     /*
00660      * Sanity check on width 
00661      */
00662     if (w < 0) {
00663    return (0);
00664     }
00665 
00666     /*
00667      * Lock surface 
00668      */
00669     SDL_LockSurface(dst);
00670 
00671     /*
00672      * More variable setup 
00673      */
00674     dx = w;
00675     pixx = dst->format->BytesPerPixel;
00676    pixy = dst->pitch;
00677    pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
00678 
00679    /*
00680     * Draw 
00681     */
00682    switch (dst->format->BytesPerPixel) {
00683    case 1:
00684        memset(pixel, color, dx);
00685        break;
00686    case 2:
00687        pixellast = pixel + dx + dx;
00688        for (; pixel <= pixellast; pixel += pixx) {
00689       *(Uint16 *) pixel = color;
00690        }
00691        break;
00692    case 3:
00693        pixellast = pixel + dx + dx + dx;
00694        for (; pixel <= pixellast; pixel += pixx) {
00695       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00696           pixel[0] = (color >> 16) & 0xff;
00697           pixel[1] = (color >> 8) & 0xff;
00698           pixel[2] = color & 0xff;
00699       } else {
00700           pixel[0] = color & 0xff;
00701           pixel[1] = (color >> 8) & 0xff;
00702           pixel[2] = (color >> 16) & 0xff;
00703       }
00704        }
00705        break;
00706    default:    /* case 4 */
00707        dx = dx + dx;
00708        pixellast = pixel + dx + dx;
00709        for (; pixel <= pixellast; pixel += pixx) {
00710       *(Uint32 *) pixel = color;
00711        }
00712        break;
00713    }
00714 
00715    /*
00716     * Unlock surface 
00717     */
00718    SDL_UnlockSurface(dst);
00719 
00720    /*
00721     * Set result code 
00722     */
00723    result = 0;
00724 
00725     return (result);
00726 }
00727 
00728 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00729 {
00730     /*
00731      * Draw 
00732      */
00733     return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
00734 }
00735 
00736 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
00737 {
00738     Sint16 left, right, top, bottom;
00739     Uint8 *pixel, *pixellast;
00740     int dx;
00741     int pixx, pixy;
00742     Sint16 w;
00743     Sint16 xtmp;
00744     int result = -1;
00745     Uint8 *colorptr;
00746 
00747     /*
00748      * Get clipping boundary 
00749      */
00750     left = dst->clip_rect.x;
00751     right = dst->clip_rect.x + dst->clip_rect.w - 1;
00752     top = dst->clip_rect.y;
00753     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
00754 
00755     /*
00756      * Check visibility of hline 
00757      */
00758     if ((x1<left) && (x2<left)) {
00759      return(0);
00760     }
00761     if ((x1>right) && (x2>right)) {
00762      return(0);
00763     }
00764     if ((y<top) || (y>bottom)) {
00765      return (0);
00766     }
00767 
00768     /*
00769      * Clip x 
00770      */
00771     if (x1 < left) {
00772    x1 = left;
00773     }
00774     if (x2 > right) {
00775    x2 = right;
00776     }
00777 
00778     /*
00779      * Swap x1, x2 if required 
00780      */
00781     if (x1 > x2) {
00782    xtmp = x1;
00783    x1 = x2;
00784    x2 = xtmp;
00785     }
00786 
00787     /*
00788      * Calculate width 
00789      */
00790     w = x2 - x1;
00791 
00792     /*
00793      * Sanity check on width 
00794      */
00795     if (w < 0) {
00796    return (0);
00797     }
00798 
00799     /*
00800      * Alpha check 
00801      */
00802     if ((color & 255) == 255) {
00803 
00804    /*
00805     * No alpha-blending required 
00806     */
00807 
00808    /*
00809     * Setup color 
00810     */
00811    colorptr = (Uint8 *) & color;
00812    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00813        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
00814    } else {
00815        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
00816    }
00817 
00818    /*
00819     * Lock surface 
00820     */
00821    SDL_LockSurface(dst);
00822 
00823    /*
00824     * More variable setup 
00825     */
00826    dx = w;
00827    pixx = dst->format->BytesPerPixel;
00828    pixy = dst->pitch;
00829    pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
00830 
00831    /*
00832     * Draw 
00833     */
00834    switch (dst->format->BytesPerPixel) {
00835    case 1:
00836        memset(pixel, color, dx);
00837        break;
00838    case 2:
00839        pixellast = pixel + dx + dx;
00840        for (; pixel <= pixellast; pixel += pixx) {
00841       *(Uint16 *) pixel = color;
00842        }
00843        break;
00844    case 3:
00845        pixellast = pixel + dx + dx + dx;
00846        for (; pixel <= pixellast; pixel += pixx) {
00847       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00848           pixel[0] = (color >> 16) & 0xff;
00849           pixel[1] = (color >> 8) & 0xff;
00850           pixel[2] = color & 0xff;
00851       } else {
00852           pixel[0] = color & 0xff;
00853           pixel[1] = (color >> 8) & 0xff;
00854           pixel[2] = (color >> 16) & 0xff;
00855       }
00856        }
00857        break;
00858    default:    /* case 4 */
00859        dx = dx + dx;
00860        pixellast = pixel + dx + dx;
00861        for (; pixel <= pixellast; pixel += pixx) {
00862       *(Uint32 *) pixel = color;
00863        }
00864        break;
00865    }
00866 
00867    /*
00868     * Unlock surface 
00869     */
00870    SDL_UnlockSurface(dst);
00871 
00872    /*
00873     * Set result code 
00874     */
00875    result = 0;
00876 
00877     } else {
00878 
00879    /*
00880     * Alpha blending blit 
00881     */
00882 
00883    result = HLineAlpha(dst, x1, x1 + w, y, color);
00884 
00885     }
00886 
00887     return (result);
00888 }
00889 
00890 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00891 {
00892     /*
00893      * Draw 
00894      */
00895     return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
00896 }
00897 
00898 /* ----- Vertical line */
00899 
00900 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
00901 {
00902     Sint16 left, right, top, bottom;
00903     Uint8 *pixel, *pixellast;
00904     int dy;
00905     int pixx, pixy;
00906     Sint16 h;
00907     Sint16 ytmp;
00908     int result = -1;
00909     Uint8 *colorptr;
00910 
00911     /*
00912      * Get clipping boundary 
00913      */
00914     left = dst->clip_rect.x;
00915     right = dst->clip_rect.x + dst->clip_rect.w - 1;
00916     top = dst->clip_rect.y;
00917     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
00918 
00919     /*
00920      * Check visibility of vline 
00921      */
00922     if ((x<left) || (x>right)) {
00923      return (0);
00924     }
00925     if ((y1<top) && (y2<top)) {
00926      return(0);
00927     }
00928     if ((y1>bottom) && (y2>bottom)) {
00929      return(0);
00930     }
00931 
00932     /*
00933      * Clip y 
00934      */
00935     if (y1 < top) {
00936    y1 = top;
00937     }
00938     if (y2 > bottom) {
00939    y2 = bottom;
00940     }
00941 
00942     /*
00943      * Swap y1, y2 if required 
00944      */
00945     if (y1 > y2) {
00946    ytmp = y1;
00947    y1 = y2;
00948    y2 = ytmp;
00949     }
00950 
00951     /*
00952      * Calculate height 
00953      */
00954     h = y2 - y1;
00955 
00956     /*
00957      * Sanity check on height 
00958      */
00959     if (h < 0) {
00960    return (0);
00961     }
00962 
00963     /*
00964      * Alpha check 
00965      */
00966     if ((color & 255) == 255) {
00967 
00968    /*
00969     * No alpha-blending required 
00970     */
00971 
00972    /*
00973     * Setup color 
00974     */
00975    colorptr = (Uint8 *) & color;
00976    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00977        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
00978    } else {
00979        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
00980    }
00981 
00982    /*
00983     * Lock surface 
00984     */
00985    SDL_LockSurface(dst);
00986 
00987    /*
00988     * More variable setup 
00989     */
00990    dy = h;
00991    pixx = dst->format->BytesPerPixel;
00992    pixy = dst->pitch;
00993    pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
00994    pixellast = pixel + pixy * dy;
00995 
00996    /*
00997     * Draw 
00998     */
00999    switch (dst->format->BytesPerPixel) {
01000    case 1:
01001        for (; pixel <= pixellast; pixel += pixy) {
01002       *(Uint8 *) pixel = color;
01003        }
01004        break;
01005    case 2:
01006        for (; pixel <= pixellast; pixel += pixy) {
01007       *(Uint16 *) pixel = color;
01008        }
01009        break;
01010    case 3:
01011        for (; pixel <= pixellast; pixel += pixy) {
01012       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01013           pixel[0] = (color >> 16) & 0xff;
01014           pixel[1] = (color >> 8) & 0xff;
01015           pixel[2] = color & 0xff;
01016       } else {
01017           pixel[0] = color & 0xff;
01018           pixel[1] = (color >> 8) & 0xff;
01019           pixel[2] = (color >> 16) & 0xff;
01020       }
01021        }
01022        break;
01023    default:    /* case 4 */
01024        for (; pixel <= pixellast; pixel += pixy) {
01025       *(Uint32 *) pixel = color;
01026        }
01027        break;
01028    }
01029 
01030    /*
01031     * Unlock surface 
01032     */
01033    SDL_UnlockSurface(dst);
01034 
01035    /*
01036     * Set result code 
01037     */
01038    result = 0;
01039 
01040     } else {
01041 
01042    /*
01043     * Alpha blending blit 
01044     */
01045 
01046    result = VLineAlpha(dst, x, y1, y1 + h, color);
01047 
01048     }
01049 
01050     return (result);
01051 }
01052 
01053 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01054 {
01055     /*
01056      * Draw 
01057      */
01058     return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01059 }
01060 
01061 /* ----- Rectangle */
01062 
01063 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
01064 {
01065     int result;
01066     Sint16 w, h, xtmp, ytmp;
01067 
01068     /*
01069      * Swap x1, x2 if required 
01070      */
01071     if (x1 > x2) {
01072    xtmp = x1;
01073    x1 = x2;
01074    x2 = xtmp;
01075     }
01076 
01077     /*
01078      * Swap y1, y2 if required 
01079      */
01080     if (y1 > y2) {
01081    ytmp = y1;
01082    y1 = y2;
01083    y2 = ytmp;
01084     }
01085 
01086     /*
01087      * Calculate width&height 
01088      */
01089     w = x2 - x1;
01090     h = y2 - y1;
01091 
01092     /*
01093      * Sanity check 
01094      */
01095     if ((w < 0) || (h < 0)) {
01096    return (0);
01097     }
01098 
01099     /*
01100      * Test for special cases of straight lines or single point 
01101      */
01102     if (x1 == x2) {
01103    if (y1 == y2) {
01104        return (pixelColor(dst, x1, y1, color));
01105    } else {
01106        return (vlineColor(dst, x1, y1, y2, color));
01107    }
01108     } else {
01109    if (y1 == y2) {
01110        return (hlineColor(dst, x1, x2, y1, color));
01111    }
01112     }
01113 
01114     /*
01115      * Draw rectangle 
01116      */
01117     result = 0;
01118     result |= hlineColor(dst, x1, x2, y1, color);
01119     result |= hlineColor(dst, x1, x2, y2, color);
01120     y1 += 1;
01121     y2 -= 1;
01122     if (y1<=y2) {
01123      result |= vlineColor(dst, x1, y1, y2, color);
01124      result |= vlineColor(dst, x2, y1, y2, color);
01125     }
01126     return (result);
01127 
01128 }
01129 
01130 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01131 {
01132     /*
01133      * Draw 
01134      */
01135     return (rectangleColor
01136        (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01137 }
01138 
01139 /* --------- Clipping routines for line */
01140 
01141 /* Clipping based heavily on code from                       */
01142 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
01143 
01144 #define CLIP_LEFT_EDGE   0x1
01145 #define CLIP_RIGHT_EDGE  0x2
01146 #define CLIP_BOTTOM_EDGE 0x4
01147 #define CLIP_TOP_EDGE    0x8
01148 #define CLIP_INSIDE(a)   (!a)
01149 #define CLIP_REJECT(a,b) (a&b)
01150 #define CLIP_ACCEPT(a,b) (!(a|b))
01151 
01152 static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
01153 {
01154     int code = 0;
01155 
01156     if (x < left) {
01157    code |= CLIP_LEFT_EDGE;
01158     } else if (x > right) {
01159    code |= CLIP_RIGHT_EDGE;
01160     }
01161     if (y < top) {
01162    code |= CLIP_TOP_EDGE;
01163     } else if (y > bottom) {
01164    code |= CLIP_BOTTOM_EDGE;
01165     }
01166     return code;
01167 }
01168 
01169 static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
01170 {
01171     Sint16 left, right, top, bottom;
01172     int code1, code2;
01173     int draw = 0;
01174     Sint16 swaptmp;
01175     float m;
01176 
01177     /*
01178      * Get clipping boundary 
01179      */
01180     left = dst->clip_rect.x;
01181     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01182     top = dst->clip_rect.y;
01183     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01184 
01185     while (1) {
01186    code1 = clipEncode(*x1, *y1, left, top, right, bottom);
01187    code2 = clipEncode(*x2, *y2, left, top, right, bottom);
01188    if (CLIP_ACCEPT(code1, code2)) {
01189        draw = 1;
01190        break;
01191    } else if (CLIP_REJECT(code1, code2))
01192        break;
01193    else {
01194        if (CLIP_INSIDE(code1)) {
01195       swaptmp = *x2;
01196       *x2 = *x1;
01197       *x1 = swaptmp;
01198       swaptmp = *y2;
01199       *y2 = *y1;
01200       *y1 = swaptmp;
01201       swaptmp = code2;
01202       code2 = code1;
01203       code1 = swaptmp;
01204        }
01205        if (*x2 != *x1) {
01206       m = (*y2 - *y1) / (float) (*x2 - *x1);
01207        } else {
01208       m = 1.0f;
01209        }
01210        if (code1 & CLIP_LEFT_EDGE) {
01211       *y1 += (Sint16) ((left - *x1) * m);
01212       *x1 = left;
01213        } else if (code1 & CLIP_RIGHT_EDGE) {
01214       *y1 += (Sint16) ((right - *x1) * m);
01215       *x1 = right;
01216        } else if (code1 & CLIP_BOTTOM_EDGE) {
01217       if (*x2 != *x1) {
01218           *x1 += (Sint16) ((bottom - *y1) / m);
01219       }
01220       *y1 = bottom;
01221        } else if (code1 & CLIP_TOP_EDGE) {
01222       if (*x2 != *x1) {
01223           *x1 += (Sint16) ((top - *y1) / m);
01224       }
01225       *y1 = top;
01226        }
01227    }
01228     }
01229 
01230     return draw;
01231 }
01232 
01233 /* ----- Filled rectangle (Box) */
01234 
01235 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
01236 {
01237     Sint16 left, right, top, bottom;
01238     Uint8 *pixel, *pixellast;
01239     int x, dx;
01240     int dy;
01241     int pixx, pixy;
01242     Sint16 w, h, tmp;
01243     int result;
01244     Uint8 *colorptr;
01245 
01246     /*
01247      * Get clipping boundary 
01248      */
01249     left = dst->clip_rect.x;
01250     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01251     top = dst->clip_rect.y;
01252     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01253     
01254     /* Check visibility */
01255     if ((x1<left) && (x2<left)) {
01256      return(0);
01257     }
01258     if ((x1>right) && (x2>right)) {
01259      return(0);
01260     }
01261     if ((y1<top) && (y2<top)) {
01262      return(0);
01263     }
01264     if ((y1>bottom) && (y2>bottom)) {
01265      return(0);
01266     }
01267      
01268     /* Clip all points */
01269     if (x1<left) { 
01270      x1=left; 
01271     } else if (x1>right) {
01272      x1=right;
01273     }
01274     if (x2<left) { 
01275      x2=left; 
01276     } else if (x2>right) {
01277      x2=right;
01278     }
01279     if (y1<top) { 
01280      y1=top; 
01281     } else if (y1>bottom) {
01282      y1=bottom;
01283     }
01284     if (y2<top) { 
01285      y2=top; 
01286     } else if (y2>bottom) {
01287      y2=bottom;
01288     }
01289 
01290     /*
01291      * Order coordinates 
01292      */
01293     if (x1 > x2) {
01294    tmp = x1;
01295    x1 = x2;
01296    x2 = tmp;
01297     }
01298     if (y1 > y2) {
01299    tmp = y1;
01300    y1 = y2;
01301    y2 = tmp;
01302     }
01303 
01304     /*
01305      * Test for special cases of straight line or single point 
01306      */
01307     if (x1 == x2) {
01308    if (y1 == y2) {
01309        return (pixelColor(dst, x1, y1, color));
01310    } else { 
01311        return (vlineColor(dst, x1, y1, y2, color));
01312    }
01313     }
01314     if (y1 == y2) {
01315    return (hlineColor(dst, x1, x2, y1, color));
01316     }
01317 
01318 
01319     /*
01320      * Calculate width&height 
01321      */
01322     w = x2 - x1;
01323     h = y2 - y1;
01324 
01325     /*
01326      * Alpha check 
01327      */
01328     if ((color & 255) == 255) {
01329 
01330    /*
01331     * No alpha-blending required 
01332     */
01333 
01334    /*
01335     * Setup color 
01336     */
01337    colorptr = (Uint8 *) & color;
01338    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01339        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01340    } else {
01341        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01342    }
01343 
01344    /*
01345     * Lock surface 
01346     */
01347    SDL_LockSurface(dst);
01348 
01349    /*
01350     * More variable setup 
01351     */
01352    dx = w;
01353    dy = h;
01354    pixx = dst->format->BytesPerPixel;
01355    pixy = dst->pitch;
01356    pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
01357    pixellast = pixel + pixx * dx + pixy * dy;
01358    dx++;
01359    
01360    /*
01361     * Draw 
01362     */
01363    switch (dst->format->BytesPerPixel) {
01364    case 1:
01365        for (; pixel <= pixellast; pixel += pixy) {
01366       memset(pixel, (Uint8) color, dx);
01367        }
01368        break;
01369    case 2:
01370        pixy -= (pixx * dx);
01371        for (; pixel <= pixellast; pixel += pixy) {
01372       for (x = 0; x < dx; x++) {
01373           *(Uint16 *) pixel = color;
01374           pixel += pixx;
01375       }
01376        }
01377        break;
01378    case 3:
01379        pixy -= (pixx * dx);
01380        for (; pixel <= pixellast; pixel += pixy) {
01381       for (x = 0; x < dx; x++) {
01382           if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01383          pixel[0] = (color >> 16) & 0xff;
01384          pixel[1] = (color >> 8) & 0xff;
01385          pixel[2] = color & 0xff;
01386           } else {
01387          pixel[0] = color & 0xff;
01388          pixel[1] = (color >> 8) & 0xff;
01389          pixel[2] = (color >> 16) & 0xff;
01390           }
01391           pixel += pixx;
01392       }
01393        }
01394        break;
01395    default:    /* case 4 */
01396        pixy -= (pixx * dx);
01397        for (; pixel <= pixellast; pixel += pixy) {
01398       for (x = 0; x < dx; x++) {
01399           *(Uint32 *) pixel = color;
01400           pixel += pixx;
01401       }
01402        }
01403        break;
01404    }
01405 
01406    /*
01407     * Unlock surface 
01408     */
01409    SDL_UnlockSurface(dst);
01410 
01411    result = 0;
01412 
01413     } else {
01414 
01415    result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
01416 
01417     }
01418 
01419     return (result);
01420 }
01421 
01422 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01423 {
01424     /*
01425      * Draw 
01426      */
01427     return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01428 }
01429 
01430 /* ----- Line */
01431 
01432 /* Non-alpha line drawing code adapted from routine          */
01433 /* by Pete Shinners, pete@shinners.org                       */
01434 /* Originally from pygame, http://pygame.seul.org            */
01435 
01436 #define ABS(a) (((a)<0) ? -(a) : (a))
01437 
01438 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
01439 {
01440     int pixx, pixy;
01441     int x, y;
01442     int dx, dy;
01443     int ax, ay;
01444     int sx, sy;
01445     int swaptmp;
01446     Uint8 *pixel;
01447     Uint8 *colorptr;
01448 
01449     /*
01450      * Clip line and test if we have to draw 
01451      */
01452     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
01453    return (0);
01454     }
01455 
01456     /*
01457      * Test for special cases of straight lines or single point 
01458      */
01459     if (x1 == x2) {
01460    if (y1 < y2) {
01461        return (vlineColor(dst, x1, y1, y2, color));
01462    } else if (y1 > y2) {
01463        return (vlineColor(dst, x1, y2, y1, color));
01464    } else {
01465        return (pixelColor(dst, x1, y1, color));
01466    }
01467     }
01468     if (y1 == y2) {
01469    if (x1 < x2) {
01470        return (hlineColor(dst, x1, x2, y1, color));
01471    } else if (x1 > x2) {
01472        return (hlineColor(dst, x2, x1, y1, color));
01473    }
01474     }
01475 
01476     /*
01477      * Variable setup 
01478      */
01479     dx = x2 - x1;
01480     dy = y2 - y1;
01481     sx = (dx >= 0) ? 1 : -1;
01482     sy = (dy >= 0) ? 1 : -1;
01483 
01484     /* Lock surface */
01485     if (SDL_MUSTLOCK(dst)) {
01486    if (SDL_LockSurface(dst) < 0) {
01487        return (-1);
01488    }
01489     }
01490 
01491     /*
01492      * Check for alpha blending 
01493      */
01494     if ((color & 255) == 255) {
01495 
01496    /*
01497     * No alpha blending - use fast pixel routines 
01498     */
01499 
01500    /*
01501     * Setup color 
01502     */
01503    colorptr = (Uint8 *) & color;
01504    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01505        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01506    } else {
01507        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01508    }
01509 
01510    /*
01511     * More variable setup 
01512     */
01513    dx = sx * dx + 1;
01514    dy = sy * dy + 1;
01515    pixx = dst->format->BytesPerPixel;
01516    pixy = dst->pitch;
01517    pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
01518    pixx *= sx;
01519    pixy *= sy;
01520    if (dx < dy) {
01521        swaptmp = dx;
01522        dx = dy;
01523        dy = swaptmp;
01524        swaptmp = pixx;
01525        pixx = pixy;
01526        pixy = swaptmp;
01527    }
01528 
01529    /*
01530     * Draw 
01531     */
01532    x = 0;
01533    y = 0;
01534    switch (dst->format->BytesPerPixel) {
01535    case 1:
01536        for (; x < dx; x++, pixel += pixx) {
01537       *pixel = color;
01538       y += dy;
01539       if (y >= dx) {
01540           y -= dx;
01541           pixel += pixy;
01542       }
01543        }
01544        break;
01545    case 2:
01546        for (; x < dx; x++, pixel += pixx) {
01547       *(Uint16 *) pixel = color;
01548       y += dy;
01549       if (y >= dx) {
01550           y -= dx;
01551           pixel += pixy;
01552       }
01553        }
01554        break;
01555    case 3:
01556        for (; x < dx; x++, pixel += pixx) {
01557       if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01558           pixel[0] = (color >> 16) & 0xff;
01559           pixel[1] = (color >> 8) & 0xff;
01560           pixel[2] = color & 0xff;
01561       } else {
01562           pixel[0] = color & 0xff;
01563           pixel[1] = (color >> 8) & 0xff;
01564           pixel[2] = (color >> 16) & 0xff;
01565       }
01566       y += dy;
01567       if (y >= dx) {
01568           y -= dx;
01569           pixel += pixy;
01570       }
01571        }
01572        break;
01573    default:    /* case 4 */
01574        for (; x < dx; x++, pixel += pixx) {
01575       *(Uint32 *) pixel = color;
01576       y += dy;
01577       if (y >= dx) {
01578           y -= dx;
01579           pixel += pixy;
01580       }
01581        }
01582        break;
01583    }
01584 
01585     } else {
01586 
01587    /*
01588     * Alpha blending required - use single-pixel blits 
01589     */
01590 
01591    ax = ABS(dx) << 1;
01592    ay = ABS(dy) << 1;
01593    x = x1;
01594    y = y1;
01595    if (ax > ay) {
01596        int d = ay - (ax >> 1);
01597 
01598        while (x != x2) {
01599       pixelColorNolock (dst, x, y, color);
01600       if (d > 0 || (d == 0 && sx == 1)) {
01601           y += sy;
01602           d -= ax;
01603       }
01604       x += sx;
01605       d += ay;
01606        }
01607    } else {
01608        int d = ax - (ay >> 1);
01609 
01610        while (y != y2) {
01611       pixelColorNolock (dst, x, y, color);
01612       if (d > 0 || ((d == 0) && (sy == 1))) {
01613           x += sx;
01614           d -= ay;
01615       }
01616       y += sy;
01617       d += ax;
01618        }
01619    }
01620    pixelColorNolock (dst, x, y, color);
01621 
01622     }
01623 
01624     /* Unlock surface */
01625     if (SDL_MUSTLOCK(dst)) {
01626    SDL_UnlockSurface(dst);
01627     }
01628 
01629     return (0);
01630 }
01631 
01632 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01633 {
01634     /*
01635      * Draw 
01636      */
01637     return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01638 }
01639 
01640 /* AA Line */
01641 
01642 #define AAlevels 256
01643 #define AAbits 8
01644 
01645 /* 
01646 
01647 This implementation of the Wu antialiasing code is based on Mike Abrash's
01648 DDJ article which was reprinted as Chapter 42 of his Graphics Programming
01649 Black Book, but has been optimized to work with SDL and utilizes 32-bit
01650 fixed-point arithmetic. (A. Schiffler).
01651 
01652 */
01653 
01654 int aalineColorInt(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
01655 {
01656     Sint32 xx0, yy0, xx1, yy1;
01657     int result;
01658     Uint32 intshift, erracc, erradj;
01659     Uint32 erracctmp, wgt, wgtcompmask;
01660     int dx, dy, tmp, xdir, y0p1, x0pxdir;
01661 
01662     /*
01663      * Clip line and test if we have to draw 
01664      */
01665     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
01666    return (0);
01667     }
01668 
01669     /*
01670      * Keep on working with 32bit numbers 
01671      */
01672     xx0 = x1;
01673     yy0 = y1;
01674     xx1 = x2;
01675     yy1 = y2;
01676 
01677     /*
01678      * Reorder points if required 
01679      */
01680     if (yy0 > yy1) {
01681    tmp = yy0;
01682    yy0 = yy1;
01683    yy1 = tmp;
01684    tmp = xx0;
01685    xx0 = xx1;
01686    xx1 = tmp;
01687     }
01688 
01689     /*
01690      * Calculate distance 
01691      */
01692     dx = xx1 - xx0;
01693     dy = yy1 - yy0;
01694 
01695     /*
01696      * Adjust for negative dx and set xdir 
01697      */
01698     if (dx >= 0) {
01699    xdir = 1;
01700     } else {
01701    xdir = -1;
01702    dx = (-dx);
01703     }
01704 
01705     /*
01706      * Check for special cases 
01707      */
01708     if (dx == 0) {
01709    /*
01710     * Vertical line 
01711     */
01712    return (vlineColor(dst, x1, y1, y2, color));
01713     } else if (dy == 0) {
01714    /*
01715     * Horizontal line 
01716     */
01717    return (hlineColor(dst, x1, x2, y1, color));
01718     } else if (dx == dy) {
01719    /*
01720     * Diagonal line 
01721     */
01722    return (lineColor(dst, x1, y1, x2, y2, color));
01723     }
01724 
01725     /*
01726      * Line is not horizontal, vertical or diagonal 
01727      */
01728     result = 0;
01729 
01730     /*
01731      * Zero accumulator 
01732      */
01733     erracc = 0;
01734 
01735     /*
01736      * # of bits by which to shift erracc to get intensity level 
01737      */
01738     intshift = 32 - AAbits;
01739     /*
01740      * Mask used to flip all bits in an intensity weighting 
01741      */
01742     wgtcompmask = AAlevels - 1;
01743 
01744     /* Lock surface */
01745     if (SDL_MUSTLOCK(dst)) {
01746    if (SDL_LockSurface(dst) < 0) {
01747        return (-1);
01748    }
01749     }
01750 
01751     /*
01752      * Draw the initial pixel in the foreground color 
01753      */
01754     result |= pixelColorNolock(dst, x1, y1, color);
01755 
01756     /*
01757      * x-major or y-major? 
01758      */
01759     if (dy > dx) {
01760 
01761    /*
01762     * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
01763     * X advances every time Y advances 1 pixel, truncating the result so that
01764     * we won't overrun the endpoint along the X axis 
01765     */
01766    /*
01767     * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; 
01768     */
01769    erradj = ((dx << 16) / dy) << 16;
01770 
01771    /*
01772     * draw all pixels other than the first and last 
01773     */
01774    x0pxdir = xx0 + xdir;
01775    while (--dy) {
01776        erracctmp = erracc;
01777        erracc += erradj;
01778        if (erracc <= erracctmp) {
01779       /*
01780        * rollover in error accumulator, x coord advances 
01781        */
01782       xx0 = x0pxdir;
01783       x0pxdir += xdir;
01784        }
01785        yy0++;     /* y-major so always advance Y */
01786 
01787        /*
01788         * the AAbits most significant bits of erracc give us the intensity
01789         * weighting for this pixel, and the complement of the weighting for
01790         * the paired pixel. 
01791         */
01792        wgt = (erracc >> intshift) & 255;
01793        result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
01794        result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
01795    }
01796 
01797     } else {
01798 
01799    /*
01800     * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
01801     * that Y advances each time X advances 1 pixel, truncating the result so
01802     * that we won't overrun the endpoint along the X axis. 
01803     */
01804    /*
01805     * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; 
01806     */
01807    erradj = ((dy << 16) / dx) << 16;
01808 
01809    /*
01810     * draw all pixels other than the first and last 
01811     */
01812    y0p1 = yy0 + 1;
01813    while (--dx) {
01814 
01815        erracctmp = erracc;
01816        erracc += erradj;
01817        if (erracc <= erracctmp) {
01818       /*
01819        * Accumulator turned over, advance y 
01820        */
01821       yy0 = y0p1;
01822       y0p1++;
01823        }
01824        xx0 += xdir;  /* x-major so always advance X */
01825        /*
01826         * the AAbits most significant bits of erracc give us the intensity
01827         * weighting for this pixel, and the complement of the weighting for
01828         * the paired pixel. 
01829         */
01830        wgt = (erracc >> intshift) & 255;
01831        result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
01832        result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
01833    }
01834     }
01835 
01836     /*
01837      * Do we have to draw the endpoint 
01838      */
01839     if (draw_endpoint) {
01840    /*
01841     * Draw final pixel, always exactly intersected by the line and doesn't
01842     * need to be weighted. 
01843     */
01844    result |= pixelColorNolock (dst, x2, y2, color);
01845     }
01846 
01847     /* Unlock surface */
01848     if (SDL_MUSTLOCK(dst)) {
01849    SDL_UnlockSurface(dst);
01850     }
01851 
01852     return (result);
01853 }
01854 
01855 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
01856 {
01857     return (aalineColorInt(dst, x1, y1, x2, y2, color, 1));
01858 }
01859 
01860 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01861 {
01862     return (aalineColorInt
01863        (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
01864 }
01865 
01866 
01867 /* ----- Circle */
01868 
01869 /* Note: Based on algorithm from sge library, modified by A. Schiffler */
01870 /* with multiple pixel-draw removal and other minor speedup changes.   */
01871 
01872 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
01873 {
01874     Sint16 left, right, top, bottom;
01875     int result;
01876     Sint16 x1, y1, x2, y2;
01877     Sint16 cx = 0;
01878     Sint16 cy = r;
01879     Sint16 ocx = (Sint16) 0xffff;
01880     Sint16 ocy = (Sint16) 0xffff;
01881     Sint16 df = 1 - r;
01882     Sint16 d_e = 3;
01883     Sint16 d_se = -2 * r + 5;
01884     Sint16 xpcx, xmcx, xpcy, xmcy;
01885     Sint16 ypcy, ymcy, ypcx, ymcx;
01886     Uint8 *colorptr;
01887 
01888     /*
01889      * Sanity check radius 
01890      */
01891     if (r < 0) {
01892    return (-1);
01893     }
01894 
01895     /*
01896      * Special case for r=0 - draw a point 
01897      */
01898     if (r == 0) {
01899    return (pixelColor(dst, x, y, color));
01900     }
01901 
01902     /*
01903      * Get clipping boundary 
01904      */
01905     left = dst->clip_rect.x;
01906     right = dst->clip_rect.x + dst->clip_rect.w - 1;
01907     top = dst->clip_rect.y;
01908     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01909 
01910     /*
01911      * Test if bounding box of circle is visible 
01912      */
01913     x1 = x - r;
01914     x2 = x + r;
01915     y1 = y - r;
01916     y2 = y + r;
01917     if ((x1<left) && (x2<left)) {
01918      return(0);
01919     } 
01920     if ((x1>right) && (x2>right)) {
01921      return(0);
01922     } 
01923     if ((y1<top) && (y2<top)) {
01924      return(0);
01925     } 
01926     if ((y1>bottom) && (y2>bottom)) {
01927      return(0);
01928     } 
01929 
01930     /*
01931      * Draw circle 
01932      */
01933     result = 0;
01934 
01935     /* Lock surface */
01936     if (SDL_MUSTLOCK(dst)) {
01937    if (SDL_LockSurface(dst) < 0) {
01938        return (-1);
01939    }
01940     }
01941 
01942     /*
01943      * Alpha Check 
01944      */
01945     if ((color & 255) == 255) {
01946 
01947    /*
01948     * No Alpha - direct memory writes 
01949     */
01950 
01951    /*
01952     * Setup color 
01953     */
01954    colorptr = (Uint8 *) & color;
01955    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01956        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01957    } else {
01958        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01959    }
01960 
01961    /*
01962     * Draw 
01963     */
01964    do {
01965        if ((ocy != cy) || (ocx != cx)) {
01966       xpcx = x + cx;
01967       xmcx = x - cx;
01968       if (cy > 0) {
01969           ypcy = y + cy;
01970           ymcy = y - cy;
01971           result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
01972           result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
01973           result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
01974           result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
01975       } else {
01976           result |= fastPixelColorNolock(dst, xmcx, y, color);
01977           result |= fastPixelColorNolock(dst, xpcx, y, color);
01978       }
01979       ocy = cy;
01980       xpcy = x + cy;
01981       xmcy = x - cy;
01982       if (cx > 0) {
01983           ypcx = y + cx;
01984           ymcx = y - cx;
01985           result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
01986           result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
01987           result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
01988           result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
01989       } else {
01990           result |= fastPixelColorNolock(dst, xmcy, y, color);
01991           result |= fastPixelColorNolock(dst, xpcy, y, color);
01992       }
01993       ocx = cx;
01994        }
01995        /*
01996         * Update 
01997         */
01998        if (df < 0) {
01999       df += d_e;
02000       d_e += 2;
02001       d_se += 2;
02002        } else {
02003       df += d_se;
02004       d_e += 2;
02005       d_se += 4;
02006       cy--;
02007        }
02008        cx++;
02009    } while (cx <= cy);
02010 
02011    /*
02012     * Unlock surface 
02013     */
02014    SDL_UnlockSurface(dst);
02015 
02016     } else {
02017 
02018    /*
02019     * Using Alpha - blended pixel blits 
02020     */
02021 
02022    do {
02023        /*
02024         * Draw 
02025         */
02026        if ((ocy != cy) || (ocx != cx)) {
02027       xpcx = x + cx;
02028       xmcx = x - cx;
02029       if (cy > 0) {
02030           ypcy = y + cy;
02031           ymcy = y - cy;
02032           result |= pixelColorNolock (dst, xmcx, ypcy, color);
02033           result |= pixelColorNolock (dst, xpcx, ypcy, color);
02034           result |= pixelColorNolock (dst, xmcx, ymcy, color);
02035           result |= pixelColorNolock (dst, xpcx, ymcy, color);
02036       } else {
02037           result |= pixelColorNolock (dst, xmcx, y, color);
02038           result |= pixelColorNolock (dst, xpcx, y, color);
02039       }
02040       ocy = cy;
02041       xpcy = x + cy;
02042       xmcy = x - cy;
02043       if (cx > 0) {
02044           ypcx = y + cx;
02045           ymcx = y - cx;
02046           result |= pixelColorNolock (dst, xmcy, ypcx, color);
02047           result |= pixelColorNolock (dst, xpcy, ypcx, color);
02048           result |= pixelColorNolock (dst, xmcy, ymcx, color);
02049           result |= pixelColorNolock (dst, xpcy, ymcx, color);
02050       } else {
02051           result |= pixelColorNolock (dst, xmcy, y, color);
02052           result |= pixelColorNolock (dst, xpcy, y, color);
02053       }
02054       ocx = cx;
02055        }
02056        /*
02057         * Update 
02058         */
02059        if (df < 0) {
02060       df += d_e;
02061       d_e += 2;
02062       d_se += 2;
02063        } else {
02064       df += d_se;
02065       d_e += 2;
02066       d_se += 4;
02067       cy--;
02068        }
02069        cx++;
02070    } while (cx <= cy);
02071 
02072     }          /* Alpha check */
02073 
02074     /* Unlock surface */
02075     if (SDL_MUSTLOCK(dst)) {
02076    SDL_UnlockSurface(dst);
02077     }
02078 
02079     return (result);
02080 }
02081 
02082 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02083 {
02084     /*
02085      * Draw 
02086      */
02087     return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02088 }
02089 
02090 /* ----- AA Circle */
02091 
02092 /* AA circle is based on AAellipse  */
02093 
02094 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
02095 {
02096     return (aaellipseColor(dst, x, y, r, r, color));
02097 }
02098 
02099 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02100 {
02101     /*
02102      * Draw 
02103      */
02104     return (aaellipseColor
02105        (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02106 }
02107 
02108 /* ----- Filled Circle */
02109 
02110 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
02111 
02112 /* and other speedup changes. */
02113 
02114 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
02115 {
02116     Sint16 left, right, top, bottom;
02117     int result;
02118     Sint16 x1, y1, x2, y2;
02119     Sint16 cx = 0;
02120     Sint16 cy = r;
02121     Sint16 ocx = (Sint16) 0xffff;
02122     Sint16 ocy = (Sint16) 0xffff;
02123     Sint16 df = 1 - r;
02124     Sint16 d_e = 3;
02125     Sint16 d_se = -2 * r + 5;
02126     Sint16 xpcx, xmcx, xpcy, xmcy;
02127     Sint16 ypcy, ymcy, ypcx, ymcx;
02128 
02129     /*
02130      * Sanity check radius 
02131      */
02132     if (r < 0) {
02133    return (-1);
02134     }
02135 
02136     /*
02137      * Special case for r=0 - draw a point 
02138      */
02139     if (r == 0) {
02140    return (pixelColor(dst, x, y, color));
02141     }
02142 
02143     /*
02144      * Get clipping boundary 
02145      */
02146     left = dst->clip_rect.x;
02147     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02148     top = dst->clip_rect.y;
02149     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02150 
02151     /*
02152      * Test if bounding box of circle is visible 
02153      */
02154     x1 = x - r;
02155     x2 = x + r;
02156     y1 = y - r;
02157     y2 = y + r;
02158     if ((x1<left) && (x2<left)) {
02159      return(0);
02160     } 
02161     if ((x1>right) && (x2>right)) {
02162      return(0);
02163     } 
02164     if ((y1<top) && (y2<top)) {
02165      return(0);
02166     } 
02167     if ((y1>bottom) && (y2>bottom)) {
02168      return(0);
02169     } 
02170 
02171     /*
02172      * Draw 
02173      */
02174     result = 0;
02175     do {
02176    xpcx = x + cx;
02177    xmcx = x - cx;
02178    xpcy = x + cy;
02179    xmcy = x - cy;
02180    if (ocy != cy) {
02181        if (cy > 0) {
02182       ypcy = y + cy;
02183       ymcy = y - cy;
02184       result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
02185       result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
02186        } else {
02187       result |= hlineColor(dst, xmcx, xpcx, y, color);
02188        }
02189        ocy = cy;
02190    }
02191    if (ocx != cx) {
02192        if (cx != cy) {
02193       if (cx > 0) {
02194           ypcx = y + cx;
02195           ymcx = y - cx;
02196           result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
02197           result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
02198       } else {
02199           result |= hlineColor(dst, xmcy, xpcy, y, color);
02200       }
02201        }
02202        ocx = cx;
02203    }
02204    /*
02205     * Update 
02206     */
02207    if (df < 0) {
02208        df += d_e;
02209        d_e += 2;
02210        d_se += 2;
02211    } else {
02212        df += d_se;
02213        d_e += 2;
02214        d_se += 4;
02215        cy--;
02216    }
02217    cx++;
02218     } while (cx <= cy);
02219 
02220     return (result);
02221 }
02222 
02223 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02224 {
02225     /*
02226      * Draw 
02227      */
02228     return (filledCircleColor
02229        (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02230 }
02231 
02232 
02233 /* ----- Ellipse */
02234 
02235 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
02236 /* and other speedup changes. */
02237 
02238 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
02239 {
02240     Sint16 left, right, top, bottom;
02241     int result;
02242     Sint16 x1, y1, x2, y2;
02243     int ix, iy;
02244     int h, i, j, k;
02245     int oh, oi, oj, ok;
02246     int xmh, xph, ypk, ymk;
02247     int xmi, xpi, ymj, ypj;
02248     int xmj, xpj, ymi, ypi;
02249     int xmk, xpk, ymh, yph;
02250     Uint8 *colorptr;
02251 
02252     /*
02253      * Sanity check radii 
02254      */
02255     if ((rx < 0) || (ry < 0)) {
02256    return (-1);
02257     }
02258 
02259     /*
02260      * Special case for rx=0 - draw a vline 
02261      */
02262     if (rx == 0) {
02263    return (vlineColor(dst, x, y - ry, y + ry, color));
02264     }
02265     /*
02266      * Special case for ry=0 - draw a hline 
02267      */
02268     if (ry == 0) {
02269    return (hlineColor(dst, x - rx, x + rx, y, color));
02270     }
02271 
02272     /*
02273      * Get clipping boundary 
02274      */
02275     left = dst->clip_rect.x;
02276     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02277     top = dst->clip_rect.y;
02278     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02279 
02280     /*
02281      * Test if bounding box of ellipse is visible 
02282      */
02283     x1 = x - rx;
02284     x2 = x + rx;
02285     y1 = y - ry;
02286     y2 = y + ry;
02287     if ((x1<left) && (x2<left)) {
02288      return(0);
02289     } 
02290     if ((x1>right) && (x2>right)) {
02291      return(0);
02292     } 
02293     if ((y1<top) && (y2<top)) {
02294      return(0);
02295     } 
02296     if ((y1>bottom) && (y2>bottom)) {
02297      return(0);
02298     } 
02299 
02300     /*
02301      * Init vars 
02302      */
02303     oh = oi = oj = ok = 0xFFFF;
02304 
02305     /*
02306      * Draw 
02307      */
02308     result = 0;
02309 
02310     /* Lock surface */
02311     if (SDL_MUSTLOCK(dst)) {
02312    if (SDL_LockSurface(dst) < 0) {
02313        return (-1);
02314    }
02315     }
02316 
02317     /*
02318      * Check alpha 
02319      */
02320     if ((color & 255) == 255) {
02321 
02322    /*
02323     * No Alpha - direct memory writes 
02324     */
02325 
02326    /*
02327     * Setup color 
02328     */
02329    colorptr = (Uint8 *) & color;
02330    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02331        color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02332    } else {
02333        color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02334    }
02335 
02336 
02337    if (rx > ry) {
02338        ix = 0;
02339        iy = rx * 64;
02340 
02341        do {
02342       h = (ix + 32) >> 6;
02343       i = (iy + 32) >> 6;
02344       j = (h * ry) / rx;
02345       k = (i * ry) / rx;
02346 
02347       if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
02348           xph = x + h;
02349           xmh = x - h;
02350           if (k > 0) {
02351          ypk = y + k;
02352          ymk = y - k;
02353          result |= fastPixelColorNolock(dst, xmh, ypk, color);
02354          result |= fastPixelColorNolock(dst, xph, ypk, color);
02355          result |= fastPixelColorNolock(dst, xmh, ymk, color);
02356          result |= fastPixelColorNolock(dst, xph, ymk, color);
02357           } else {
02358          result |= fastPixelColorNolock(dst, xmh, y, color);
02359          result |= fastPixelColorNolock(dst, xph, y, color);
02360           }
02361           ok = k;
02362           xpi = x + i;
02363           xmi = x - i;
02364           if (j > 0) {
02365          ypj = y + j;
02366          ymj = y - j;
02367          result |= fastPixelColorNolock(dst, xmi, ypj, color);
02368          result |= fastPixelColorNolock(dst, xpi, ypj, color);
02369          result |= fastPixelColorNolock(dst, xmi, ymj, color);
02370          result |= fastPixelColorNolock(dst, xpi, ymj, color);
02371           } else {
02372          result |= fastPixelColorNolock(dst, xmi, y, color);
02373          result |= fastPixelColorNolock(dst, xpi, y, color);
02374           }
02375           oj = j;
02376       }
02377 
02378       ix = ix + iy / rx;
02379       iy = iy - ix / rx;
02380 
02381        } while (i > h);
02382    } else {
02383        ix = 0;
02384        iy = ry * 64;
02385 
02386        do {
02387       h = (ix + 32) >> 6;
02388       i = (iy + 32) >> 6;
02389       j = (h * rx) / ry;
02390       k = (i * rx) / ry;
02391 
02392       if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
02393           xmj = x - j;
02394           xpj = x + j;
02395           if (i > 0) {
02396          ypi = y + i;
02397          ymi = y - i;
02398          result |= fastPixelColorNolock(dst, xmj, ypi, color);
02399          result |= fastPixelColorNolock(dst, xpj, ypi, color);
02400          result |= fastPixelColorNolock(dst, xmj, ymi, color);
02401          result |= fastPixelColorNolock(dst, xpj, ymi, color);
02402           } else {
02403          result |= fastPixelColorNolock(dst, xmj, y, color);
02404          result |= fastPixelColorNolock(dst, xpj, y, color);
02405           }
02406           oi = i;
02407           xmk = x - k;
02408           xpk = x + k;
02409           if (h > 0) {
02410          yph = y + h;
02411          ymh = y - h;
02412          result |= fastPixelColorNolock(dst, xmk, yph, color);
02413          result |= fastPixelColorNolock(dst, xpk, yph, color);
02414          result |= fastPixelColorNolock(dst, xmk, ymh, color);
02415          result |= fastPixelColorNolock(dst, xpk, ymh, color);
02416           } else {
02417          result |= fastPixelColorNolock(dst, xmk, y, color);
02418          result |= fastPixelColorNolock(dst, xpk, y, color);
02419           }
02420           oh = h;
02421       }
02422 
02423       ix = ix + iy / ry;
02424       iy = iy - ix / ry;
02425 
02426        } while (i > h);
02427    }
02428 
02429     } else {
02430 
02431    if (rx > ry) {
02432        ix = 0;
02433        iy = rx * 64;
02434 
02435        do {
02436       h = (ix + 32) >> 6;
02437       i = (iy + 32) >> 6;
02438       j = (h * ry) / rx;
02439       k = (i * ry) / rx;
02440 
02441       if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
02442           xph = x + h;
02443           xmh = x - h;
02444           if (k > 0) {
02445          ypk = y + k;
02446          ymk = y - k;
02447          result |= pixelColorNolock (dst, xmh, ypk, color);
02448          result |= pixelColorNolock (dst, xph, ypk, color);
02449          result |= pixelColorNolock (dst, xmh, ymk, color);
02450          result |= pixelColorNolock (dst, xph, ymk, color);
02451           } else {
02452          result |= pixelColorNolock (dst, xmh, y, color);
02453          result |= pixelColorNolock (dst, xph, y, color);
02454           }
02455           ok = k;
02456           xpi = x + i;
02457           xmi = x - i;
02458           if (j > 0) {
02459          ypj = y + j;
02460          ymj = y - j;
02461          result |= pixelColorNolock (dst, xmi, ypj, color);
02462          result |= pixelColorNolock (dst, xpi, ypj, color);
02463          result |= pixelColorNolock (dst, xmi, ymj, color);
02464          result |= pixelColor(dst, xpi, ymj, color);
02465           } else {
02466          result |= pixelColorNolock (dst, xmi, y, color);
02467          result |= pixelColorNolock (dst, xpi, y, color);
02468           }
02469           oj = j;
02470       }
02471 
02472       ix = ix + iy / rx;
02473       iy = iy - ix / rx;
02474 
02475        } while (i > h);
02476    } else {
02477        ix = 0;
02478        iy = ry * 64;
02479 
02480        do {
02481       h = (ix + 32) >> 6;
02482       i = (iy + 32) >> 6;
02483       j = (h * rx) / ry;
02484       k = (i * rx) / ry;
02485 
02486       if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
02487           xmj = x - j;
02488           xpj = x + j;
02489           if (i > 0) {
02490          ypi = y + i;
02491          ymi = y - i;
02492          result |= pixelColorNolock (dst, xmj, ypi, color);
02493          result |= pixelColorNolock (dst, xpj, ypi, color);
02494          result |= pixelColorNolock (dst, xmj, ymi, color);
02495          result |= pixelColorNolock (dst, xpj, ymi, color);
02496           } else {
02497          result |= pixelColorNolock (dst, xmj, y, color);
02498          result |= pixelColorNolock (dst, xpj, y, color);
02499           }
02500           oi = i;
02501           xmk = x - k;
02502           xpk = x + k;
02503           if (h > 0) {
02504          yph = y + h;
02505          ymh = y - h;
02506          result |= pixelColorNolock (dst, xmk, yph, color);
02507          result |= pixelColorNolock (dst, xpk, yph, color);
02508          result |= pixelColorNolock (dst, xmk, ymh, color);
02509          result |= pixelColorNolock (dst, xpk, ymh, color);
02510           } else {
02511          result |= pixelColorNolock (dst, xmk, y, color);
02512          result |= pixelColorNolock (dst, xpk, y, color);
02513           }
02514           oh = h;
02515       }
02516 
02517       ix = ix + iy / ry;
02518       iy = iy - ix / ry;
02519 
02520        } while (i > h);
02521    }
02522 
02523     }          /* Alpha check */
02524 
02525     /* Unlock surface */
02526     if (SDL_MUSTLOCK(dst)) {
02527    SDL_UnlockSurface(dst);
02528     }
02529 
02530     return (result);
02531 }
02532 
02533 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02534 {
02535     /*
02536      * Draw 
02537      */
02538     return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02539 }
02540 
02541 /* ----- AA Ellipse */
02542 
02543 /* Based on code from Anders Lindstroem, based on code from SGE, based on code from TwinLib */
02544 
02545 int aaellipseColor(SDL_Surface * dst, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
02546 {
02547     Sint16 left, right, top, bottom;
02548     Sint16 x1,y1,x2,y2;
02549     int i;
02550     int a2, b2, ds, dt, dxt, t, s, d;
02551     Sint16 x, y, xs, ys, dyt, xx, yy, xc2, yc2;
02552     float cp;
02553     Uint8 weight, iweight;
02554     int result;
02555 
02556     /*
02557      * Sanity check radii 
02558      */
02559     if ((rx < 0) || (ry < 0)) {
02560    return (-1);
02561     }
02562 
02563     /*
02564      * Special case for rx=0 - draw a vline 
02565      */
02566     if (rx == 0) {
02567    return (vlineColor(dst, xc, yc - ry, yc + ry, color));
02568     }
02569     /*
02570      * Special case for ry=0 - draw a hline 
02571      */
02572     if (ry == 0) {
02573    return (hlineColor(dst, xc - rx, xc + rx, yc, color));
02574     }
02575 
02576     /*
02577      * Get clipping boundary 
02578      */
02579     left = dst->clip_rect.x;
02580     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02581     top = dst->clip_rect.y;
02582     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02583 
02584     /*
02585      * Test if bounding box of ellipse is visible 
02586      */
02587     x1 = xc - rx;
02588     x2 = xc + rx;
02589     y1 = yc - ry;
02590     y2 = yc + ry;
02591     if ((x1<left) && (x2<left)) {
02592      return(0);
02593     } 
02594     if ((x1>right) && (x2>right)) {
02595      return(0);
02596     } 
02597     if ((y1<top) && (y2<top)) {
02598      return(0);
02599     } 
02600     if ((y1>bottom) && (y2>bottom)) {
02601      return(0);
02602     } 
02603     
02604     /* Variable setup */
02605     a2 = rx * rx;
02606     b2 = ry * ry;
02607 
02608     ds = 2 * a2;
02609     dt = 2 * b2;
02610 
02611     xc2 = 2 * xc;
02612     yc2 = 2 * yc;
02613 
02614     dxt = (int) (a2 / sqrt(a2 + b2));
02615 
02616     t = 0;
02617     s = -2 * a2 * ry;
02618     d = 0;
02619 
02620     x = xc;
02621     y = yc - ry;
02622 
02623     /* Draw */
02624     result = 0;
02625 
02626     /* Lock surface */
02627     if (SDL_MUSTLOCK(dst)) {
02628    if (SDL_LockSurface(dst) < 0) {
02629        return (-1);
02630    }
02631     }
02632 
02633     /* "End points" */
02634     result |= pixelColorNolock(dst, x, y, color);
02635     result |= pixelColorNolock(dst, xc2 - x, y, color);
02636     result |= pixelColorNolock(dst, x, yc2 - y, color);
02637     result |= pixelColorNolock(dst, xc2 - x, yc2 - y, color);
02638 
02639     for (i = 1; i <= dxt; i++) {
02640    x--;
02641    d += t - b2;
02642 
02643    if (d >= 0)
02644        ys = y - 1;
02645    else if ((d - s - a2) > 0) {
02646        if ((2 * d - s - a2) >= 0)
02647       ys = y + 1;
02648        else {
02649       ys = y;
02650       y++;
02651       d -= s + a2;
02652       s += ds;
02653        }
02654    } else {
02655        y++;
02656        ys = y + 1;
02657        d -= s + a2;
02658        s += ds;
02659    }
02660 
02661    t -= dt;
02662 
02663    /* Calculate alpha */
02664    if (s != 0.0) {
02665        cp = (float) abs(d) / (float) abs(s);
02666        if (cp > 1.0) {
02667       cp = 1.0;
02668        }
02669    } else {
02670        cp = 1.0;
02671    }
02672 
02673    /* Calculate weights */
02674    weight = (Uint8) (cp * 255);
02675    iweight = 255 - weight;
02676 
02677    /* Upper half */
02678    xx = xc2 - x;
02679    result |= pixelColorWeightNolock(dst, x, y, color, iweight);
02680    result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
02681 
02682    result |= pixelColorWeightNolock(dst, x, ys, color, weight);
02683    result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
02684 
02685    /* Lower half */
02686    yy = yc2 - y;
02687    result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
02688    result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
02689 
02690    yy = yc2 - ys;
02691    result |= pixelColorWeightNolock(dst, x, yy, color, weight);
02692    result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
02693     }
02694 
02695     dyt = abs(y - yc);
02696 
02697     for (i = 1; i <= dyt; i++) {
02698    y++;
02699    d -= s + a2;
02700 
02701    if (d <= 0)
02702        xs = x + 1;
02703    else if ((d + t - b2) < 0) {
02704        if ((2 * d + t - b2) <= 0)
02705       xs = x - 1;
02706        else {
02707       xs = x;
02708       x--;
02709       d += t - b2;
02710       t -= dt;
02711        }
02712    } else {
02713        x--;
02714        xs = x - 1;
02715        d += t - b2;
02716        t -= dt;
02717    }
02718 
02719    s += ds;
02720 
02721    /* Calculate alpha */
02722    if (t != 0.0) {
02723        cp = (float) abs(d) / (float) abs(t);
02724        if (cp > 1.0) {
02725       cp = 1.0;
02726        }
02727    } else {
02728        cp = 1.0;
02729    }
02730 
02731    /* Calculate weight */
02732    weight = (Uint8) (cp * 255);
02733    iweight = 255 - weight;
02734 
02735    /* Left half */
02736    xx = xc2 - x;
02737    yy = yc2 - y;
02738    result |= pixelColorWeightNolock(dst, x, y, color, iweight);
02739    result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
02740 
02741    result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
02742    result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
02743 
02744    /* Right half */
02745    xx = 2 * xc - xs;
02746    result |= pixelColorWeightNolock(dst, xs, y, color, weight);
02747    result |= pixelColorWeightNolock(dst, xx, y, color, weight);
02748 
02749    result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
02750    result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
02751 
02752 
02753     }
02754 
02755     /* Unlock surface */
02756     if (SDL_MUSTLOCK(dst)) {
02757    SDL_UnlockSurface(dst);
02758     }
02759 
02760     return (result);
02761 }
02762 
02763 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02764 {
02765     /*
02766      * Draw 
02767      */
02768     return (aaellipseColor
02769        (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02770 }
02771 
02772 /* ---- Filled Ellipse */
02773 
02774 /* Note: */
02775 /* Based on algorithm from sge library with multiple-hline draw removal */
02776 /* and other speedup changes. */
02777 
02778 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
02779 {
02780     Sint16 left, right, top, bottom;
02781     int result;
02782     Sint16 x1, y1, x2, y2;
02783     int ix, iy;
02784     int h, i, j, k;
02785     int oh, oi, oj, ok;
02786     int xmh, xph;
02787     int xmi, xpi;
02788     int xmj, xpj;
02789     int xmk, xpk;
02790 
02791     /*
02792      * Sanity check radii 
02793      */
02794     if ((rx < 0) || (ry < 0)) {
02795    return (-1);
02796     }
02797 
02798     /*
02799      * Special case for rx=0 - draw a vline 
02800      */
02801     if (rx == 0) {
02802    return (vlineColor(dst, x, y - ry, y + ry, color));
02803     }
02804     /*
02805      * Special case for ry=0 - draw a hline 
02806      */
02807     if (ry == 0) {
02808    return (hlineColor(dst, x - rx, x + rx, y, color));
02809     }
02810 
02811     /*
02812      * Get clipping boundary 
02813      */
02814     left = dst->clip_rect.x;
02815     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02816     top = dst->clip_rect.y;
02817     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02818 
02819     /*
02820      * Test if bounding box of ellipse is visible 
02821      */
02822     x1 = x - rx;
02823     x2 = x + rx;
02824     y1 = y - ry;
02825     y2 = y + ry;
02826     if ((x1<left) && (x2<left)) {
02827      return(0);
02828     } 
02829     if ((x1>right) && (x2>right)) {
02830      return(0);
02831     } 
02832     if ((y1<top) && (y2<top)) {
02833      return(0);
02834     } 
02835     if ((y1>bottom) && (y2>bottom)) {
02836      return(0);
02837     } 
02838 
02839     /*
02840      * Init vars 
02841      */
02842     oh = oi = oj = ok = 0xFFFF;
02843 
02844     /*
02845      * Draw 
02846      */
02847     result = 0;
02848     if (rx > ry) {
02849    ix = 0;
02850    iy = rx * 64;
02851 
02852    do {
02853        h = (ix + 32) >> 6;
02854        i = (iy + 32) >> 6;
02855        j = (h * ry) / rx;
02856        k = (i * ry) / rx;
02857 
02858        if ((ok != k) && (oj != k)) {
02859       xph = x + h;
02860       xmh = x - h;
02861       if (k > 0) {
02862           result |= hlineColor(dst, xmh, xph, y + k, color);
02863           result |= hlineColor(dst, xmh, xph, y - k, color);
02864       } else {
02865           result |= hlineColor(dst, xmh, xph, y, color);
02866       }
02867       ok = k;
02868        }
02869        if ((oj != j) && (ok != j) && (k != j)) {
02870       xmi = x - i;
02871       xpi = x + i;
02872       if (j > 0) {
02873           result |= hlineColor(dst, xmi, xpi, y + j, color);
02874           result |= hlineColor(dst, xmi, xpi, y - j, color);
02875       } else {
02876           result |= hlineColor(dst, xmi, xpi, y, color);
02877       }
02878       oj = j;
02879        }
02880 
02881        ix = ix + iy / rx;
02882        iy = iy - ix / rx;
02883 
02884    } while (i > h);
02885     } else {
02886    ix = 0;
02887    iy = ry * 64;
02888 
02889    do {
02890        h = (ix + 32) >> 6;
02891        i = (iy + 32) >> 6;
02892        j = (h * rx) / ry;
02893        k = (i * rx) / ry;
02894 
02895        if ((oi != i) && (oh != i)) {
02896       xmj = x - j;
02897       xpj = x + j;
02898       if (i > 0) {
02899           result |= hlineColor(dst, xmj, xpj, y + i, color);
02900           result |= hlineColor(dst, xmj, xpj, y - i, color);
02901       } else {
02902           result |= hlineColor(dst, xmj, xpj, y, color);
02903       }
02904       oi = i;
02905        }
02906        if ((oh != h) && (oi != h) && (i != h)) {
02907       xmk = x - k;
02908       xpk = x + k;
02909       if (h > 0) {
02910           result |= hlineColor(dst, xmk, xpk, y + h, color);
02911           result |= hlineColor(dst, xmk, xpk, y - h, color);
02912       } else {
02913           result |= hlineColor(dst, xmk, xpk, y, color);
02914       }
02915       oh = h;
02916        }
02917 
02918        ix = ix + iy / ry;
02919        iy = iy - ix / ry;
02920 
02921    } while (i > h);
02922     }
02923 
02924     return (result);
02925 }
02926 
02927 
02928 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02929 {
02930     /*
02931      * Draw 
02932      */
02933     return (filledEllipseColor
02934        (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02935 }
02936 
02937 /* ----- filled pie */
02938 
02939 /* Low-speed float pie-calc implementation by drawing polygons. */
02940 
02941 int filledpieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
02942 {
02943     Sint16 left, right, top, bottom;
02944     Sint16 x1, y1, x2, y2;
02945     int result;
02946     double angle, start_angle, end_angle;
02947     double deltaAngle;
02948     double dr;
02949     int posX, posY;
02950     int numpoints, i;
02951     Sint16 *vx, *vy;
02952 
02953     /*
02954      * Sanity check radii 
02955      */
02956     if (rad < 0) {
02957    return (-1);
02958     }
02959 
02960     /*
02961      * Fixup angles
02962      */
02963     start = start % 360;
02964     end = end % 360;
02965 
02966     /*
02967      * Special case for rad=0 - draw a point 
02968      */
02969     if (rad == 0) {
02970    return (pixelColor(dst, x, y, color));
02971     }
02972 
02973     /*
02974      * Get clipping boundary 
02975      */
02976     left = dst->clip_rect.x;
02977     right = dst->clip_rect.x + dst->clip_rect.w - 1;
02978     top = dst->clip_rect.y;
02979     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02980 
02981     /*
02982      * Test if bounding box of pie's circle is visible 
02983      */
02984     x1 = x - rad;
02985     x2 = x + rad;
02986     y1 = y - rad;
02987     y2 = y + rad;
02988     if ((x1<left) && (x2<left)) {
02989      return(0);
02990     } 
02991     if ((x1>right) && (x2>right)) {
02992      return(0);
02993     } 
02994     if ((y1<top) && (y2<top)) {
02995      return(0);
02996     } 
02997     if ((y1>bottom) && (y2>bottom)) {
02998      return(0);
02999     } 
03000 
03001     /*
03002      * Variable setup 
03003      */
03004     dr = (double) rad;
03005     deltaAngle = 3.0 / dr;
03006     start_angle = (double) start *(2.0 * M_PI / 360.0);
03007     end_angle = (double) end *(2.0 * M_PI / 360.0);
03008     if (start > end) {
03009    end_angle += (2.0 * M_PI);
03010     }
03011 
03012     /* Count points (rather than calculate it) */
03013     numpoints = 1;
03014     angle = start_angle;
03015     while (angle <= end_angle) {
03016    angle += deltaAngle;
03017    numpoints++;
03018     }
03019 
03020     /* Check size of array */
03021     if (numpoints == 1) {
03022    return (pixelColor(dst, x, y, color));
03023     } else if (numpoints == 2) {
03024    posX = x + (int) (dr * cos(start_angle));
03025    posY = y + (int) (dr * sin(start_angle));
03026    return (lineColor(dst, x, y, posX, posY, color));
03027     }
03028 
03029     /* Allocate vertex array */
03030     vx = vy = (Uint16 *) malloc(2 * sizeof(Uint16) * numpoints);
03031     if (vx == NULL) {
03032    return (-1);
03033     }
03034     vy += numpoints;
03035 
03036     /* Center */
03037     vx[0] = x;
03038     vy[0] = y;
03039 
03040     /* Calculate and store vertices */
03041     i = 1;
03042     angle = start_angle;
03043     while (angle <= end_angle) {
03044    vx[i] = x + (int) (dr * cos(angle));
03045    vy[i] = y + (int) (dr * sin(angle));
03046    angle += deltaAngle;
03047    i++;
03048     }
03049 
03050     /* Draw */
03051     result = filledPolygonColor(dst, vx, vy, numpoints, color);
03052 
03053     /* Free vertex array */
03054     free(vx);
03055 
03056     return (result);
03057 }
03058 
03059 int filledpieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
03060         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03061 {
03062     return (filledpieColor(dst, x, y, rad, start, end,
03063             ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03064 
03065 }
03066 
03067 
03068 /* Trigon */
03069 
03070 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
03071 {
03072  Sint16 vx[3]; 
03073  Sint16 vy[3];
03074  
03075  vx[0]=x1;
03076  vx[1]=x2;
03077  vx[2]=x3;
03078  vy[0]=y1;
03079  vy[1]=y2;
03080  vy[2]=y3;
03081  
03082  return(polygonColor(dst,vx,vy,3,color));
03083 }
03084 
03085 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
03086              Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03087 {
03088  Sint16 vx[3]; 
03089  Sint16 vy[3];
03090  
03091  vx[0]=x1;
03092  vx[1]=x2;
03093  vx[2]=x3;
03094  vy[0]=y1;
03095  vy[1]=y2;
03096  vy[2]=y3;
03097  
03098  return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
03099 }            
03100 
03101 /* AA-Trigon */
03102 
03103 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
03104 {
03105  Sint16 vx[3]; 
03106  Sint16 vy[3];
03107  
03108  vx[0]=x1;
03109  vx[1]=x2;
03110  vx[2]=x3;
03111  vy[0]=y1;
03112  vy[1]=y2;
03113  vy[2]=y3;
03114  
03115  return(aapolygonColor(dst,vx,vy,3,color));
03116 }
03117 
03118 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
03119                Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03120 {
03121  Sint16 vx[3]; 
03122  Sint16 vy[3];
03123  
03124  vx[0]=x1;
03125  vx[1]=x2;
03126  vx[2]=x3;
03127  vy[0]=y1;
03128  vy[1]=y2;
03129  vy[2]=y3;
03130  
03131  return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
03132 }              
03133 
03134 /* Filled Trigon */
03135 
03136 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, int color)
03137 {
03138  Sint16 vx[3]; 
03139  Sint16 vy[3];
03140  
03141  vx[0]=x1;
03142  vx[1]=x2;
03143  vx[2]=x3;
03144  vy[0]=y1;
03145  vy[1]=y2;
03146  vy[2]=y3;
03147  
03148  return(filledPolygonColor(dst,vx,vy,3,color));
03149 }
03150 
03151 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
03152                    Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03153 {
03154  Sint16 vx[3]; 
03155  Sint16 vy[3];
03156  
03157  vx[0]=x1;
03158  vx[1]=x2;
03159  vx[2]=x3;
03160  vy[0]=y1;
03161  vy[1]=y2;
03162  vy[2]=y3;
03163  
03164  return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
03165 }
03166 
03167 /* ---- Polygon */
03168 
03169 int polygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color)
03170 {
03171     int result;
03172     int i;
03173     Sint16 *x1, *y1, *x2, *y2;
03174 
03175     /*
03176      * Sanity check 
03177      */
03178     if (n < 3) {
03179    return (-1);
03180     }
03181 
03182     /*
03183      * Pointer setup 
03184      */
03185     x1 = x2 = vx;
03186     y1 = y2 = vy;
03187     x2++;
03188     y2++;
03189 
03190     /*
03191      * Draw 
03192      */
03193     result = 0;
03194     for (i = 1; i < n; i++) {
03195    result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
03196    x1 = x2;
03197    y1 = y2;
03198    x2++;
03199    y2++;
03200     }
03201     result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
03202 
03203     return (result);
03204 }
03205 
03206 int polygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03207 {
03208     /*
03209      * Draw 
03210      */
03211     return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03212 }
03213 
03214 /* ---- AA-Polygon */
03215 
03216 int aapolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color)
03217 {
03218     int result;
03219     int i;
03220     Sint16 *x1, *y1, *x2, *y2;
03221 
03222     /*
03223      * Sanity check 
03224      */
03225     if (n < 3) {
03226    return (-1);
03227     }
03228 
03229     /*
03230      * Pointer setup 
03231      */
03232     x1 = x2 = vx;
03233     y1 = y2 = vy;
03234     x2++;
03235     y2++;
03236 
03237     /*
03238      * Draw 
03239      */
03240     result = 0;
03241     for (i = 1; i < n; i++) {
03242    result |= aalineColorInt(dst, *x1, *y1, *x2, *y2, color, 0);
03243    x1 = x2;
03244    y1 = y2;
03245    x2++;
03246    y2++;
03247     }
03248     result |= aalineColorInt(dst, *x1, *y1, *vx, *vy, color, 0);
03249 
03250     return (result);
03251 }
03252 
03253 int aapolygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03254 {
03255     /*
03256      * Draw 
03257      */
03258     return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03259 }
03260 
03261 /* ---- Filled Polygon */
03262 
03263 int gfxPrimitivesCompareInt(const void *a, const void *b);
03264 
03265 static int *gfxPrimitivesPolyInts = NULL;
03266 static int gfxPrimitivesPolyAllocated = 0;
03267 
03268 int filledPolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int color)
03269 {
03270     int result;
03271     int i;
03272     int x, y, xa, xb;
03273     int miny, maxy;
03274     int x1, y1;
03275     int x2, y2;
03276     int ind1, ind2;
03277     int ints;
03278 
03279     /*
03280      * Sanity check 
03281      */
03282     if (n < 3) {
03283    return -1;
03284     }
03285 
03286     /*
03287      * Allocate temp array, only grow array 
03288      */
03289     if (!gfxPrimitivesPolyAllocated) {
03290    gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
03291    gfxPrimitivesPolyAllocated = n;
03292     } else {
03293    if (gfxPrimitivesPolyAllocated < n) {
03294        gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
03295        gfxPrimitivesPolyAllocated = n;
03296    }
03297     }
03298 
03299     /*
03300      * Determine Y maxima 
03301      */
03302     miny = vy[0];
03303     maxy = vy[0];
03304     for (i = 1; (i < n); i++) {
03305    if (vy[i] < miny) {
03306        miny = vy[i];
03307    } else if (vy[i] > maxy) {
03308        maxy = vy[i];
03309    }
03310     }
03311 
03312     /*
03313      * Draw, scanning y 
03314      */
03315     result = 0;
03316     for (y = miny; (y <= maxy); y++) {
03317    ints = 0;
03318    for (i = 0; (i < n); i++) {
03319        if (!i) {
03320       ind1 = n - 1;
03321       ind2 = 0;
03322        } else {
03323       ind1 = i - 1;
03324       ind2 = i;
03325        }
03326        y1 = vy[ind1];
03327        y2 = vy[ind2];
03328        if (y1 < y2) {
03329       x1 = vx[ind1];
03330       x2 = vx[ind2];
03331        } else if (y1 > y2) {
03332       y2 = vy[ind1];
03333       y1 = vy[ind2];
03334       x2 = vx[ind1];
03335       x1 = vx[ind2];
03336        } else {
03337       continue;
03338        }
03339        if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
03340       gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
03341        } 
03342        
03343    }
03344    
03345    qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
03346 
03347    for (i = 0; (i < ints); i += 2) {
03348        xa = gfxPrimitivesPolyInts[i] + 1;
03349        xa = (xa >> 16) + ((xa & 32768) >> 15);
03350        xb = gfxPrimitivesPolyInts[i+1] - 1;
03351        xb = (xb >> 16) + ((xb & 32768) >> 15);
03352        result |= hlineColor(dst, xa, xb, y, color);
03353    }
03354     }
03355 
03356     return (result);
03357 }
03358 
03359 int filledPolygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03360 {
03361     /*
03362      * Draw 
03363      */
03364     return (filledPolygonColor
03365        (dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03366 }
03367 
03368 int gfxPrimitivesCompareInt(const void *a, const void *b)
03369 {
03370     return (*(const int *) a) - (*(const int *) b);
03371 }
03372 
03373 /* ---- Bezier curve */
03374 
03375 /*
03376  Calculate bezier interpolator of data array with ndata values at position 't'
03377 */
03378 
03379 double evaluateBezier (double *data, int ndata, double t) 
03380 {
03381  double mu, result;
03382  int n,k,kn,nn,nkn;
03383  double blend,muk,munk;
03384      
03385  /* Sanity check bounds */
03386  if (t<0.0) {
03387   return(data[0]);
03388  }
03389  if (t>=(double)ndata) {
03390   return(data[ndata-1]);
03391  }
03392   
03393  /* Adjust t to the range 0.0 to 1.0 */ 
03394  mu=t/(double)ndata;
03395  
03396  /* Calculate interpolate */
03397  n=ndata-1;
03398  result=0.0;
03399  muk = 1;
03400  munk = pow(1-mu,(double)n);
03401  for (k=0;k<=n;k++) {
03402   nn = n;
03403   kn = k;
03404   nkn = n - k;
03405   blend = muk * munk;
03406   muk *= mu;
03407   munk /= (1-mu);
03408   while (nn >= 1) {
03409    blend *= nn;
03410    nn--;
03411    if (kn > 1) {
03412     blend /= (double)kn;
03413     kn--;
03414    }
03415    if (nkn > 1) {
03416     blend /= (double)nkn;
03417     nkn--;
03418    }
03419   }
03420   result += data[k] * blend;
03421  }
03422                                                           
03423  return(result);
03424 }
03425 
03426 int bezierColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int s, Uint32 color)
03427 {
03428     int result;
03429     int i;
03430     double *x, *y, t, stepsize;
03431     Sint16 x1, y1, x2, y2;
03432 
03433     /*
03434      * Sanity check 
03435      */
03436     if (n < 3) {
03437    return (-1);
03438     }
03439     if (s < 2) {
03440         return (-1);
03441     }
03442     
03443     /*
03444      * Variable setup 
03445      */
03446     stepsize=(double)1.0/(double)s;
03447     
03448     /* Transfer vertices into float arrays */
03449     if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
03450      return(-1);
03451     }
03452     if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
03453      free(x);
03454      return(-1);
03455     }    
03456     for (i=0; i<n; i++) {
03457      x[i]=vx[i];
03458      y[i]=vy[i];
03459     }      
03460     x[n]=vx[0];
03461     y[n]=vy[0];
03462     
03463     /*
03464      * Draw 
03465      */
03466     result = 0;
03467     t=0.0;
03468     x1=evaluateBezier(x,n+1,t);
03469     y1=evaluateBezier(y,n+1,t);
03470     for (i = 0; i <= (n*s); i++) {
03471    t += stepsize;
03472    x2=(Sint16)evaluateBezier(x,n,t);
03473    y2=(Sint16)evaluateBezier(y,n,t);
03474    result |= lineColor(dst, x1, y1, x2, y2, color);
03475    x1 = x2;
03476    y1 = y2;
03477     }
03478 
03479     /* Clean up temporary array */
03480     free(x);
03481     free(y);
03482     
03483     return (result);
03484 }
03485 
03486 int bezierRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03487 {
03488     /*
03489      * Draw 
03490      */
03491     return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03492 }

Generated on Wed Jun 1 09:54:31 2005 for Fish Fillets - Next Generation by  doxygen 1.4.2