SDL_gfx  2.0.25
I:/Sources/sdlgfx/SDL_gfxPrimitives.c
Go to the documentation of this file.
00001 /* 
00002 
00003 SDL_gfxPrimitives.c: graphics primitives for SDL surfaces
00004 
00005 Copyright (C) 2001-2012  Andreas Schiffler
00006 
00007 This software is provided 'as-is', without any express or implied
00008 warranty. In no event will the authors be held liable for any damages
00009 arising from the use of this software.
00010 
00011 Permission is granted to anyone to use this software for any purpose,
00012 including commercial applications, and to alter it and redistribute it
00013 freely, subject to the following restrictions:
00014 
00015 1. The origin of this software must not be misrepresented; you must not
00016 claim that you wrote the original software. If you use this software
00017 in a product, an acknowledgment in the product documentation would be
00018 appreciated but is not required.
00019 
00020 2. Altered source versions must be plainly marked as such, and must not be
00021 misrepresented as being the original software.
00022 
00023 3. This notice may not be removed or altered from any source
00024 distribution.
00025 
00026 Andreas Schiffler -- aschiffler at ferzkopp dot net
00027 
00028 */
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <math.h>
00033 #include <string.h>
00034 
00035 #include "SDL_gfxPrimitives.h"
00036 #include "SDL_rotozoom.h"
00037 #include "SDL_gfxPrimitives_font.h"
00038 #include "SDL_gfxBlitFunc.h"
00039 
00040 /* -===================- */
00041 
00042 #define DEFAULT_ALPHA_PIXEL_ROUTINE
00043 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00044 #define ALPHA_PIXEL_ADDITIVE_BLEND
00045 
00046 /* ---- Structures */
00047 
00051 typedef struct {
00052         Sint16 x, y;
00053         int dx, dy, s1, s2, swapdir, error;
00054         Uint32 count;
00055 } SDL_gfxBresenhamIterator;
00056 
00060 typedef struct {
00061         Uint32 color;
00062         SDL_Surface *dst;
00063         int u, v;               /* delta x , delta y */
00064         int ku, kt, kv, kd;     /* loop constants */
00065         int oct2;
00066         int quad4;
00067         Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
00068 } SDL_gfxMurphyIterator;
00069 
00070 /* ----- Defines for pixel clipping tests */
00071 
00072 #define clip_xmin(surface) surface->clip_rect.x
00073 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
00074 #define clip_ymin(surface) surface->clip_rect.y
00075 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
00076 
00087 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00088 {
00089         int bpp;
00090         Uint8 *p;
00091 
00092         /*
00093         * Honor clipping setup at pixel level 
00094         */
00095         if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
00096 
00097                 /*
00098                 * Get destination format 
00099                 */
00100                 bpp = dst->format->BytesPerPixel;
00101                 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00102                 switch (bpp) {
00103                 case 1:
00104                         *p = color;
00105                         break;
00106                 case 2:
00107                         *(Uint16 *) p = color;
00108                         break;
00109                 case 3:
00110                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00111                                 p[0] = (color >> 16) & 0xff;
00112                                 p[1] = (color >> 8) & 0xff;
00113                                 p[2] = color & 0xff;
00114                         } else {
00115                                 p[0] = color & 0xff;
00116                                 p[1] = (color >> 8) & 0xff;
00117                                 p[2] = (color >> 16) & 0xff;
00118                         }
00119                         break;
00120                 case 4:
00121                         *(Uint32 *) p = color;
00122                         break;
00123                 }                       /* switch */
00124 
00125 
00126         }
00127 
00128         return (0);
00129 }
00130 
00144 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00145 {
00146         int bpp;
00147         Uint8 *p;
00148 
00149         /*
00150         * Get destination format 
00151         */
00152         bpp = dst->format->BytesPerPixel;
00153         p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00154         switch (bpp) {
00155         case 1:
00156                 *p = color;
00157                 break;
00158         case 2:
00159                 *(Uint16 *) p = color;
00160                 break;
00161         case 3:
00162                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00163                         p[0] = (color >> 16) & 0xff;
00164                         p[1] = (color >> 8) & 0xff;
00165                         p[2] = color & 0xff;
00166                 } else {
00167                         p[0] = color & 0xff;
00168                         p[1] = (color >> 8) & 0xff;
00169                         p[2] = (color >> 16) & 0xff;
00170                 }
00171                 break;
00172         case 4:
00173                 *(Uint32 *) p = color;
00174                 break;
00175         }                               /* switch */
00176 
00177         return (0);
00178 }
00179 
00190 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00191 {
00192         int result;
00193 
00194         /*
00195         * Lock the surface 
00196         */
00197         if (SDL_MUSTLOCK(dst)) {
00198                 if (SDL_LockSurface(dst) < 0) {
00199                         return (-1);
00200                 }
00201         }
00202 
00203         result = fastPixelColorNolock(dst, x, y, color);
00204 
00205         /*
00206         * Unlock surface 
00207         */
00208         if (SDL_MUSTLOCK(dst)) {
00209                 SDL_UnlockSurface(dst);
00210         }
00211 
00212         return (result);
00213 }
00214 
00228 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00229 {
00230         Uint32 color;
00231 
00232         /*
00233         * Setup color 
00234         */
00235         color = SDL_MapRGBA(dst->format, r, g, b, a);
00236 
00237         /*
00238         * Draw 
00239         */
00240         return (fastPixelColor(dst, x, y, color));
00241 }
00242 
00256 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00257 {
00258         Uint32 color;
00259 
00260         /*
00261         * Setup color 
00262         */
00263         color = SDL_MapRGBA(dst->format, r, g, b, a);
00264 
00265         /*
00266         * Draw 
00267         */
00268         return (fastPixelColorNolock(dst, x, y, color));
00269 }
00270 
00286 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
00287 {
00288         SDL_PixelFormat *format;
00289         Uint32 Rmask, Gmask, Bmask, Amask;
00290         Uint32 Rshift, Gshift, Bshift, Ashift;
00291         Uint32 sR, sG, sB;
00292         Uint32 dR, dG, dB, dA;
00293 
00294         if (dst == NULL)
00295         {
00296                 return (-1);
00297         }
00298 
00299         if (x >= clip_xmin(dst) && x <= clip_xmax(dst) && 
00300                 y >= clip_ymin(dst) && y <= clip_ymax(dst)) 
00301         {
00302 
00303                 format = dst->format;
00304 
00305                 switch (format->BytesPerPixel) {
00306                 case 1:
00307                         {               /* Assuming 8-bpp */
00308                                 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
00309                                 if (alpha == 255) {
00310                                         *pixel = color;
00311                                 } else {
00312                                         Uint8 R, G, B;
00313                                         SDL_Palette *palette = format->palette;
00314                                         SDL_Color *colors = palette->colors;
00315                                         SDL_Color dColor = colors[*pixel];
00316                                         SDL_Color sColor = colors[color];
00317                                         dR = dColor.r;
00318                                         dG = dColor.g;
00319                                         dB = dColor.b;
00320                                         sR = sColor.r;
00321                                         sG = sColor.g;
00322                                         sB = sColor.b;
00323 
00324                                         R = dR + ((sR - dR) * alpha >> 8);
00325                                         G = dG + ((sG - dG) * alpha >> 8);
00326                                         B = dB + ((sB - dB) * alpha >> 8);
00327 
00328                                         *pixel = SDL_MapRGB(format, R, G, B);
00329                                 }
00330                         }
00331                         break;
00332 
00333                 case 2:
00334                         {               /* Probably 15-bpp or 16-bpp */
00335                                 Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
00336                                 if (alpha == 255) {
00337                                         *pixel = color;
00338                                 } else {
00339                                         Uint16 R, G, B, A;
00340                                         Uint16 dc = *pixel;
00341 
00342                                         Rmask = format->Rmask;
00343                                         Gmask = format->Gmask;
00344                                         Bmask = format->Bmask;
00345                                         Amask = format->Amask;
00346 
00347                                         dR = (dc & Rmask);
00348                                         dG = (dc & Gmask);
00349                                         dB = (dc & Bmask);
00350 
00351                                         R = (dR + (((color & Rmask) - dR) * alpha >> 8)) & Rmask;
00352                                         G = (dG + (((color & Gmask) - dG) * alpha >> 8)) & Gmask;
00353                                         B = (dB + (((color & Bmask) - dB) * alpha >> 8)) & Bmask;
00354                                         *pixel = R | G | B;
00355                                         if (Amask!=0) {
00356                                                 dA = (dc & Amask);
00357                                                 A = (dA + (((color & Amask) - dA) * alpha >> 8)) & Amask;
00358                                                 *pixel |= A;
00359                                         }
00360                                 }
00361                         }
00362                         break;
00363 
00364                 case 3: 
00365                         {               /* Slow 24-bpp mode, usually not used */
00366                                 Uint8 R, G, B;
00367                                 Uint8 Rshift8, Gshift8, Bshift8;
00368                                 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
00369 
00370                                 Rshift = format->Rshift;
00371                                 Gshift = format->Gshift;
00372                                 Bshift = format->Bshift;
00373 
00374                                 Rshift8 = Rshift >> 3;
00375                                 Gshift8 = Gshift >> 3;
00376                                 Bshift8 = Bshift >> 3;
00377 
00378                                 sR = (color >> Rshift) & 0xFF;
00379                                 sG = (color >> Gshift) & 0xFF;
00380                                 sB = (color >> Bshift) & 0xFF;
00381 
00382                                 if (alpha == 255) {
00383                                         *(pixel + Rshift8) = sR;
00384                                         *(pixel + Gshift8) = sG;
00385                                         *(pixel + Bshift8) = sB;
00386                                 } else {
00387                                         dR = *((pixel) + Rshift8);
00388                                         dG = *((pixel) + Gshift8);
00389                                         dB = *((pixel) + Bshift8);
00390 
00391                                         R = dR + ((sR - dR) * alpha >> 8);
00392                                         G = dG + ((sG - dG) * alpha >> 8);
00393                                         B = dB + ((sB - dB) * alpha >> 8);
00394 
00395                                         *((pixel) + Rshift8) = R;
00396                                         *((pixel) + Gshift8) = G;
00397                                         *((pixel) + Bshift8) = B;
00398                                 }
00399                         }
00400                         break;
00401 
00402 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
00403 
00404                 case 4:
00405                         {               /* Probably :-) 32-bpp */
00406                                 Uint32 R, G, B, A;
00407                                 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
00408                                 if (alpha == 255) {
00409                                         *pixel = color;
00410                                 } else {
00411                                         Uint32 dc = *pixel;
00412 
00413                                         Rmask = format->Rmask;
00414                                         Gmask = format->Gmask;
00415                                         Bmask = format->Bmask;
00416                                         Amask = format->Amask;
00417 
00418                                         Rshift = format->Rshift;
00419                                         Gshift = format->Gshift;
00420                                         Bshift = format->Bshift;
00421                                         Ashift = format->Ashift;
00422 
00423                                         dR = (dc & Rmask) >> Rshift;
00424                                         dG = (dc & Gmask) >> Gshift;
00425                                         dB = (dc & Bmask) >> Bshift;
00426 
00427 
00428                                         R = ((dR + ((((color & Rmask) >> Rshift) - dR) * alpha >> 8)) << Rshift) & Rmask;
00429                                         G = ((dG + ((((color & Gmask) >> Gshift) - dG) * alpha >> 8)) << Gshift) & Gmask;
00430                                         B = ((dB + ((((color & Bmask) >> Bshift) - dB) * alpha >> 8)) << Bshift) & Bmask;
00431                                         *pixel = R | G | B;
00432                                         if (Amask!=0) {
00433                                                 dA = (dc & Amask) >> Ashift;
00434 
00435 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
00436                                                 A = (dA | GFX_ALPHA_ADJUST_ARRAY[alpha & 255]) << Ashift; // make destination less transparent...
00437 #else
00438                                                 A = ((dA + ((((color & Amask) >> Ashift) - dA) * alpha >> 8)) << Ashift) & Amask;
00439 #endif
00440                                                 *pixel |= A;
00441                                         }
00442                                 }
00443                         }
00444                         break;
00445 #endif
00446 
00447 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00448 
00449                 case 4:{                /* Probably :-) 32-bpp */
00450                         if (alpha == 255) {
00451                                 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
00452                         } else {
00453                                 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
00454                                 Uint32 dR, dG, dB, dA;
00455                                 Uint32 dc = *pixel;
00456 
00457                                 Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
00458                                 Uint32 aTmp;
00459 
00460                                 Rmask = format->Rmask;
00461                                 Gmask = format->Gmask;
00462                                 Bmask = format->Bmask;
00463                                 Amask = format->Amask;
00464 
00465                                 dR = (color & Rmask);
00466                                 dG = (color & Gmask);
00467                                 dB = (color & Bmask);
00468                                 dA = (color & Amask);
00469 
00470                                 Rshift = format->Rshift;
00471                                 Gshift = format->Gshift;
00472                                 Bshift = format->Bshift;
00473                                 Ashift = format->Ashift;
00474 
00475                                 preMultR = (alpha * (dR >> Rshift));
00476                                 preMultG = (alpha * (dG >> Gshift));
00477                                 preMultB = (alpha * (dB >> Bshift));
00478 
00479                                 surfaceAlpha = ((dc & Amask) >> Ashift);
00480                                 aTmp = (255 - alpha);
00481                                 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
00482                                         aTmp *= surfaceAlpha;
00483                                         R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
00484                                         G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
00485                                         B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
00486                                 }
00487                                 *pixel = R | G | B | (A << Ashift & Amask);
00488 
00489                         }
00490                            }
00491                            break;
00492 #endif
00493                 }
00494         }
00495 
00496         return (0);
00497 }
00498 
00509 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00510 {
00511         Uint8 alpha;
00512         Uint32 mcolor;
00513         int result = 0;
00514 
00515         /*
00516         * Lock the surface 
00517         */
00518         if (SDL_MUSTLOCK(dst)) {
00519                 if (SDL_LockSurface(dst) < 0) {
00520                         return (-1);
00521                 }
00522         }
00523 
00524         /*
00525         * Setup color 
00526         */
00527         alpha = color & 0x000000ff;
00528         mcolor =
00529                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00530                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00531 
00532         /*
00533         * Draw 
00534         */
00535         result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00536 
00537         /*
00538         * Unlock the surface 
00539         */
00540         if (SDL_MUSTLOCK(dst)) {
00541                 SDL_UnlockSurface(dst);
00542         }
00543 
00544         return (result);
00545 }
00546 
00557 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
00558 {
00559         Uint8 alpha;
00560         Uint32 mcolor;
00561         int result = 0;
00562 
00563         /*
00564         * Setup color 
00565         */
00566         alpha = color & 0x000000ff;
00567         mcolor =
00568                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00569                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00570 
00571         /*
00572         * Draw 
00573         */
00574         result = _putPixelAlpha(dst, x, y, mcolor, alpha);
00575 
00576         return (result);
00577 }
00578 
00579 
00595 int _filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
00596 {
00597         SDL_PixelFormat *format;
00598         Uint32 Rmask, Gmask, Bmask, Amask;
00599         Uint32 Rshift, Gshift, Bshift, Ashift;
00600         Uint32 sR, sG, sB, sA;
00601         Uint32 dR, dG, dB, dA;
00602         Sint16 x, y;
00603 
00604         if (dst == NULL) {
00605                 return (-1);
00606         }
00607 
00608         format = dst->format;
00609         switch (format->BytesPerPixel) {
00610         case 1:
00611                 {                       /* Assuming 8-bpp */
00612                         Uint8 *row, *pixel;
00613                         Uint8 R, G, B;
00614                         SDL_Color *colors = format->palette->colors;
00615                         SDL_Color dColor;
00616                         SDL_Color sColor = colors[color];
00617                         sR = sColor.r;
00618                         sG = sColor.g;
00619                         sB = sColor.b;
00620 
00621                         for (y = y1; y <= y2; y++) {
00622                                 row = (Uint8 *) dst->pixels + y * dst->pitch;
00623                                 for (x = x1; x <= x2; x++) {
00624                                         if (alpha == 255) {
00625                                                 *(row + x) = color;
00626                                         } else {
00627                                                 pixel = row + x;
00628 
00629                                                 dColor = colors[*pixel];
00630                                                 dR = dColor.r;
00631                                                 dG = dColor.g;
00632                                                 dB = dColor.b;
00633 
00634                                                 R = dR + ((sR - dR) * alpha >> 8);
00635                                                 G = dG + ((sG - dG) * alpha >> 8);
00636                                                 B = dB + ((sB - dB) * alpha >> 8);
00637 
00638                                                 *pixel = SDL_MapRGB(format, R, G, B);
00639                                         }
00640                                 }
00641                         }
00642                 }
00643                 break;
00644 
00645         case 2:
00646                 {                       /* Probably 15-bpp or 16-bpp */
00647                         Uint16 *row, *pixel;
00648                         Uint16 R, G, B, A;
00649                         Uint16 dc;
00650                         Rmask = format->Rmask;
00651                         Gmask = format->Gmask;
00652                         Bmask = format->Bmask;
00653                         Amask = format->Amask;
00654 
00655                         sR = (color & Rmask); 
00656                         sG = (color & Gmask);
00657                         sB = (color & Bmask);
00658                         sA = (color & Amask);
00659 
00660                         for (y = y1; y <= y2; y++) {
00661                                 row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
00662                                 for (x = x1; x <= x2; x++) {
00663                                         if (alpha == 255) {
00664                                                 *(row + x) = color;
00665                                         } else {
00666                                                 pixel = row + x;
00667                                                 dc = *pixel;
00668 
00669                                                 dR = (dc & Rmask);
00670                                                 dG = (dc & Gmask);
00671                                                 dB = (dc & Bmask);
00672 
00673                                                 R = (dR + ((sR - dR) * alpha >> 8)) & Rmask;
00674                                                 G = (dG + ((sG - dG) * alpha >> 8)) & Gmask;
00675                                                 B = (dB + ((sB - dB) * alpha >> 8)) & Bmask;
00676                                                 *pixel = R | G | B;
00677                                                 if (Amask!=0) {
00678                                                         dA = (dc & Amask);
00679                                                         A = (dA + ((sA - dA) * alpha >> 8)) & Amask;
00680                                                         *pixel |= A;
00681                                                 } 
00682                                         }
00683                                 }
00684                         }
00685                 }
00686                 break;
00687 
00688         case 3:
00689                 {                       /* Slow 24-bpp mode, usually not used */
00690                         Uint8 *row, *pixel;
00691                         Uint8 R, G, B;
00692                         Uint8 Rshift8, Gshift8, Bshift8;
00693 
00694                         Rshift = format->Rshift;
00695                         Gshift = format->Gshift;
00696                         Bshift = format->Bshift;
00697 
00698                         Rshift8 = Rshift >> 3;
00699                         Gshift8 = Gshift >> 3;
00700                         Bshift8 = Bshift >> 3;
00701 
00702                         sR = (color >> Rshift) & 0xff;
00703                         sG = (color >> Gshift) & 0xff;
00704                         sB = (color >> Bshift) & 0xff;
00705 
00706                         for (y = y1; y <= y2; y++) {
00707                                 row = (Uint8 *) dst->pixels + y * dst->pitch;
00708                                 for (x = x1; x <= x2; x++) {
00709                                         pixel = row + x * 3;
00710 
00711                                         if (alpha == 255) {
00712                                                 *(pixel + Rshift8) = sR;
00713                                                 *(pixel + Gshift8) = sG;
00714                                                 *(pixel + Bshift8) = sB;
00715                                         } else {
00716                                                 dR = *((pixel) + Rshift8);
00717                                                 dG = *((pixel) + Gshift8);
00718                                                 dB = *((pixel) + Bshift8);
00719 
00720                                                 R = dR + ((sR - dR) * alpha >> 8);
00721                                                 G = dG + ((sG - dG) * alpha >> 8);
00722                                                 B = dB + ((sB - dB) * alpha >> 8);
00723 
00724                                                 *((pixel) + Rshift8) = R;
00725                                                 *((pixel) + Gshift8) = G;
00726                                                 *((pixel) + Bshift8) = B;
00727                                         }
00728                                 }
00729                         }
00730                 }
00731                 break;
00732 
00733 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
00734         case 4:
00735                 {                       /* Probably :-) 32-bpp */
00736                         Uint32 *row, *pixel;
00737                         Uint32 R, G, B, A;
00738                         Uint32 dc;
00739                         Rmask = format->Rmask;
00740                         Gmask = format->Gmask;
00741                         Bmask = format->Bmask;
00742                         Amask = format->Amask;
00743 
00744                         Rshift = format->Rshift;
00745                         Gshift = format->Gshift;
00746                         Bshift = format->Bshift;
00747                         Ashift = format->Ashift;
00748 
00749                         sR = (color & Rmask) >> Rshift;
00750                         sG = (color & Gmask) >> Gshift;
00751                         sB = (color & Bmask) >> Bshift;
00752                         sA = (color & Amask) >> Ashift;
00753 
00754                         for (y = y1; y <= y2; y++) {
00755                                 row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
00756                                 for (x = x1; x <= x2; x++) {
00757                                         if (alpha == 255) {
00758                                                 *(row + x) = color;
00759                                         } else {
00760                                                 pixel = row + x;
00761                                                 dc = *pixel;
00762 
00763                                                 dR = (dc & Rmask) >> Rshift;
00764                                                 dG = (dc & Gmask) >> Gshift;
00765                                                 dB = (dc & Bmask) >> Bshift;
00766 
00767                                                 R = ((dR + ((sR - dR) * alpha >> 8)) << Rshift) & Rmask;
00768                                                 G = ((dG + ((sG - dG) * alpha >> 8)) << Gshift) & Gmask;
00769                                                 B = ((dB + ((sB - dB) * alpha >> 8)) << Bshift) & Bmask;
00770                                                 *pixel = R | G | B;
00771                                                 if (Amask!=0) {
00772                                                         dA = (dc & Amask) >> Ashift;
00773 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
00774                                                         A = (dA | GFX_ALPHA_ADJUST_ARRAY[sA & 255]) << Ashift; // make destination less transparent...
00775 #else
00776                                                         A = ((dA + ((sA - dA) * alpha >> 8)) << Ashift) & Amask;
00777 #endif
00778                                                         *pixel |= A;
00779                                                 }
00780                                         }
00781                                 }
00782                         }
00783                 }
00784                 break;
00785 #endif
00786 
00787 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
00788         case 4:{                        /* Probably :-) 32-bpp */
00789                 Uint32 *row, *pixel;
00790                 Uint32 dR, dG, dB, dA;
00791                 Uint32 dc;
00792                 Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
00793                 Uint32 aTmp;
00794 
00795                 Rmask = format->Rmask;
00796                 Gmask = format->Gmask;
00797                 Bmask = format->Bmask;
00798                 Amask = format->Amask;
00799 
00800                 dR = (color & Rmask);
00801                 dG = (color & Gmask);
00802                 dB = (color & Bmask);
00803                 dA = (color & Amask);
00804 
00805                 Rshift = format->Rshift;
00806                 Gshift = format->Gshift;
00807                 Bshift = format->Bshift;
00808                 Ashift = format->Ashift;
00809 
00810                 preMultR = (alpha * (dR >> Rshift));
00811                 preMultG = (alpha * (dG >> Gshift));
00812                 preMultB = (alpha * (dB >> Bshift));
00813 
00814                 for (y = y1; y <= y2; y++) {
00815                         row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
00816                         for (x = x1; x <= x2; x++) {
00817                                 if (alpha == 255) {
00818                                         *(row + x) = color;
00819                                 } else {
00820                                         pixel = row + x;
00821                                         dc = *pixel;
00822 
00823                                         surfaceAlpha = ((dc & Amask) >> Ashift);
00824                                         aTmp = (255 - alpha);
00825                                         if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
00826                                                 aTmp *= surfaceAlpha;
00827                                                 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
00828                                                 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
00829                                                 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
00830                                         }
00831                                         *pixel = R | G | B | (A << Ashift & Amask);
00832                                 }
00833                         }
00834                 }
00835                    }
00836                    break;
00837 #endif
00838 
00839         }
00840 
00841         return (0);
00842 }
00843 
00856 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
00857 {
00858         Uint8 alpha;
00859         Uint32 mcolor;
00860         int result = 0;
00861 
00862         /*
00863         * Lock the surface 
00864         */
00865         if (SDL_MUSTLOCK(dst)) {
00866                 if (SDL_LockSurface(dst) < 0) {
00867                         return (-1);
00868                 }
00869         }
00870 
00871         /*
00872         * Setup color 
00873         */
00874         alpha = color & 0x000000ff;
00875         mcolor =
00876                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
00877                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
00878 
00879         /*
00880         * Draw 
00881         */
00882         result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
00883 
00884         /*
00885         * Unlock the surface 
00886         */
00887         if (SDL_MUSTLOCK(dst)) {
00888                 SDL_UnlockSurface(dst);
00889         }
00890 
00891         return (result);
00892 }
00893 
00905 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
00906 {
00907         return (filledRectAlpha(dst, x1, y, x2, y, color));
00908 }
00909 
00921 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
00922 {
00923         return (filledRectAlpha(dst, x, y1, x, y2, color));
00924 }
00925 
00937 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
00938 {
00939         Uint32 a;
00940 
00941         /*
00942         * Get alpha 
00943         */
00944         a = (color & (Uint32) 0x000000ff);
00945 
00946         /*
00947         * Modify Alpha by weight 
00948         */
00949         a = ((a * weight) >> 8);
00950 
00951         return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
00952 }
00953 
00965 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
00966 {
00967         Uint32 a;
00968 
00969         /*
00970         * Get alpha 
00971         */
00972         a = (color & (Uint32) 0x000000ff);
00973 
00974         /*
00975         * Modify Alpha by weight 
00976         */
00977         a = ((a * weight) >> 8);
00978 
00979         return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
00980 }
00981 
00995 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
00996 {
00997         Uint32 color;
00998 
00999         /*
01000         * Check Alpha 
01001         */
01002         if (a == 255) {
01003                 /*
01004                 * No alpha blending required 
01005                 */
01006                 /*
01007                 * Setup color 
01008                 */
01009                 color = SDL_MapRGBA(dst->format, r, g, b, a);
01010                 /*
01011                 * Draw 
01012                 */
01013                 return (fastPixelColor(dst, x, y, color));
01014         } else {
01015                 /*
01016                 * Alpha blending required 
01017                 */
01018                 /*
01019                 * Draw 
01020                 */
01021                 return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01022         }
01023 }
01024 
01025 
01041 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
01042 {
01043         Sint16 left, right, top, bottom;
01044         Uint8 *pixel, *pixellast;
01045         int dx;
01046         int pixx, pixy;
01047         Sint16 w;
01048         Sint16 xtmp;
01049         int result = -1;
01050 
01051         /*
01052         * Check visibility of clipping rectangle
01053         */
01054         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01055                 return(0);
01056         }
01057 
01058         /*
01059         * Swap x1, x2 if required to ensure x1<=x2
01060         */
01061         if (x1 > x2) {
01062                 xtmp = x1;
01063                 x1 = x2;
01064                 x2 = xtmp;
01065         }
01066 
01067         /*
01068         * Get clipping boundary and
01069         * check visibility of hline 
01070         */
01071         left = dst->clip_rect.x;
01072         if (x2<left) {
01073                 return(0);
01074         }
01075         right = dst->clip_rect.x + dst->clip_rect.w - 1;
01076         if (x1>right) {
01077                 return(0);
01078         }
01079         top = dst->clip_rect.y;
01080         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01081         if ((y<top) || (y>bottom)) {
01082                 return (0);
01083         }
01084 
01085         /*
01086         * Clip x 
01087         */
01088         if (x1 < left) {
01089                 x1 = left;
01090         }
01091         if (x2 > right) {
01092                 x2 = right;
01093         }
01094 
01095         /*
01096         * Calculate width 
01097         */
01098         w = x2 - x1;
01099 
01100         /*
01101         * Lock the surface 
01102         */
01103         if (SDL_MUSTLOCK(dst)) {
01104                 if (SDL_LockSurface(dst) < 0) {
01105                         return (-1);
01106                 }
01107         }
01108 
01109         /*
01110         * More variable setup 
01111         */
01112         dx = w;
01113         pixx = dst->format->BytesPerPixel;
01114         pixy = dst->pitch;
01115         pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
01116 
01117         /*
01118         * Draw 
01119         */
01120         switch (dst->format->BytesPerPixel) {
01121         case 1:
01122                 memset(pixel, color, dx+1);
01123                 break;
01124         case 2:
01125                 pixellast = pixel + dx + dx;
01126                 for (; pixel <= pixellast; pixel += pixx) {
01127                         *(Uint16 *) pixel = color;
01128                 }
01129                 break;
01130         case 3:
01131                 pixellast = pixel + dx + dx + dx;
01132                 for (; pixel <= pixellast; pixel += pixx) {
01133                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01134                                 pixel[0] = (color >> 16) & 0xff;
01135                                 pixel[1] = (color >> 8) & 0xff;
01136                                 pixel[2] = color & 0xff;
01137                         } else {
01138                                 pixel[0] = color & 0xff;
01139                                 pixel[1] = (color >> 8) & 0xff;
01140                                 pixel[2] = (color >> 16) & 0xff;
01141                         }
01142                 }
01143                 break;
01144         default:                /* case 4 */
01145                 dx = dx + dx;
01146                 pixellast = pixel + dx + dx;
01147                 for (; pixel <= pixellast; pixel += pixx) {
01148                         *(Uint32 *) pixel = color;
01149                 }
01150                 break;
01151         }
01152 
01153         /* 
01154         * Unlock surface 
01155         */
01156         if (SDL_MUSTLOCK(dst)) {
01157                 SDL_UnlockSurface(dst);
01158         }
01159 
01160         /*
01161         * Set result code 
01162         */
01163         result = 0;
01164 
01165         return (result);
01166 }
01167 
01185 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01186 {
01187         /*
01188         * Draw 
01189         */
01190         return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01191 }
01192 
01204 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
01205 {
01206         Sint16 left, right, top, bottom;
01207         Uint8 *pixel, *pixellast;
01208         int dx;
01209         int pixx, pixy;
01210         Sint16 xtmp;
01211         int result = -1;
01212         Uint8 *colorptr;
01213         Uint8 color3[3];
01214 
01215         /*
01216         * Check visibility of clipping rectangle
01217         */
01218         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01219                 return(0);
01220         }
01221 
01222         /*
01223         * Swap x1, x2 if required to ensure x1<=x2
01224         */
01225         if (x1 > x2) {
01226                 xtmp = x1;
01227                 x1 = x2;
01228                 x2 = xtmp;
01229         }
01230 
01231         /*
01232         * Get clipping boundary and
01233         * check visibility of hline 
01234         */
01235         left = dst->clip_rect.x;
01236         if (x2<left) {
01237                 return(0);
01238         }
01239         right = dst->clip_rect.x + dst->clip_rect.w - 1;
01240         if (x1>right) {
01241                 return(0);
01242         }
01243         top = dst->clip_rect.y;
01244         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01245         if ((y<top) || (y>bottom)) {
01246                 return (0);
01247         }
01248 
01249         /*
01250         * Clip x 
01251         */
01252         if (x1 < left) {
01253                 x1 = left;
01254         }
01255         if (x2 > right) {
01256                 x2 = right;
01257         }
01258 
01259         /*
01260         * Calculate width difference
01261         */
01262         dx = x2 - x1;
01263 
01264         /*
01265         * Alpha check 
01266         */
01267         if ((color & 255) == 255) {
01268 
01269                 /*
01270                 * No alpha-blending required 
01271                 */
01272 
01273                 /*
01274                 * Setup color 
01275                 */
01276                 colorptr = (Uint8 *) & color;
01277                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01278                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01279                 } else {
01280                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01281                 }
01282 
01283                 /*
01284                 * Lock the surface 
01285                 */
01286                 if (SDL_MUSTLOCK(dst)) {
01287                         if (SDL_LockSurface(dst) < 0) {
01288                                 return (-1);
01289                         }
01290                 }
01291 
01292                 /*
01293                 * More variable setup 
01294                 */
01295                 pixx = dst->format->BytesPerPixel;
01296                 pixy = dst->pitch;
01297                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
01298 
01299                 /*
01300                 * Draw 
01301                 */
01302                 switch (dst->format->BytesPerPixel) {
01303                 case 1:
01304                         memset(pixel, color, dx + 1);
01305                         break;
01306                 case 2:
01307                         pixellast = pixel + dx + dx;
01308                         for (; pixel <= pixellast; pixel += pixx) {
01309                                 *(Uint16 *) pixel = color;
01310                         }
01311                         break;
01312                 case 3:
01313                         pixellast = pixel + dx + dx + dx;
01314                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01315                                 color3[0] = (color >> 16) & 0xff;
01316                                 color3[1] = (color >> 8) & 0xff;
01317                                 color3[2] = color & 0xff;
01318                         } else {
01319                                 color3[0] = color & 0xff;
01320                                 color3[1] = (color >> 8) & 0xff;
01321                                 color3[2] = (color >> 16) & 0xff;
01322                         }
01323                         for (; pixel <= pixellast; pixel += pixx) {
01324                                 memcpy(pixel, color3, 3);
01325                         }
01326                         break;
01327                 default:                /* case 4 */
01328                         dx = dx + dx;
01329                         pixellast = pixel + dx + dx;
01330                         for (; pixel <= pixellast; pixel += pixx) {
01331                                 *(Uint32 *) pixel = color;
01332                         }
01333                         break;
01334                 }
01335 
01336                 /* 
01337                 * Unlock surface 
01338                 */
01339                 if (SDL_MUSTLOCK(dst)) {
01340                         SDL_UnlockSurface(dst);
01341                 }
01342 
01343                 /*
01344                 * Set result code 
01345                 */
01346                 result = 0;
01347 
01348         } else {
01349 
01350                 /*
01351                 * Alpha blending blit 
01352                 */
01353                 result = _HLineAlpha(dst, x1, x1 + dx, y, color);
01354         }
01355 
01356         return (result);
01357 }
01358 
01373 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01374 {
01375         /*
01376         * Draw 
01377         */
01378         return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01379 }
01380 
01392 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
01393 {
01394         Sint16 left, right, top, bottom;
01395         Uint8 *pixel, *pixellast;
01396         int dy;
01397         int pixx, pixy;
01398         Sint16 h;
01399         Sint16 ytmp;
01400         int result = -1;
01401         Uint8 *colorptr;
01402 
01403         /*
01404         * Check visibility of clipping rectangle
01405         */
01406         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01407                 return(0);
01408         }
01409 
01410         /*
01411         * Swap y1, y2 if required to ensure y1<=y2
01412         */
01413         if (y1 > y2) {
01414                 ytmp = y1;
01415                 y1 = y2;
01416                 y2 = ytmp;
01417         }
01418 
01419         /*
01420         * Get clipping boundary and
01421         * check visibility of vline 
01422         */
01423         left = dst->clip_rect.x;
01424         right = dst->clip_rect.x + dst->clip_rect.w - 1;
01425         if ((x<left) || (x>right)) {
01426                 return (0);
01427         }    
01428         top = dst->clip_rect.y;
01429         if (y2<top) {
01430                 return(0);
01431         }
01432         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
01433         if (y1>bottom) {
01434                 return(0);
01435         }
01436 
01437         /*
01438         * Clip x 
01439         */
01440         if (y1 < top) {
01441                 y1 = top;
01442         }
01443         if (y2 > bottom) {
01444                 y2 = bottom;
01445         }
01446 
01447         /*
01448         * Calculate height
01449         */
01450         h = y2 - y1;
01451 
01452         /*
01453         * Alpha check 
01454         */
01455         if ((color & 255) == 255) {
01456 
01457                 /*
01458                 * No alpha-blending required 
01459                 */
01460 
01461                 /*
01462                 * Setup color 
01463                 */
01464                 colorptr = (Uint8 *) & color;
01465                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01466                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
01467                 } else {
01468                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
01469                 }
01470 
01471                 /*
01472                 * Lock the surface 
01473                 */
01474                 if (SDL_MUSTLOCK(dst)) {
01475                         if (SDL_LockSurface(dst) < 0) {
01476                                 return (-1);
01477                         }
01478                 }
01479 
01480                 /*
01481                 * More variable setup 
01482                 */
01483                 dy = h;
01484                 pixx = dst->format->BytesPerPixel;
01485                 pixy = dst->pitch;
01486                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
01487                 pixellast = pixel + pixy * dy;
01488 
01489                 /*
01490                 * Draw 
01491                 */
01492                 switch (dst->format->BytesPerPixel) {
01493                 case 1:
01494                         for (; pixel <= pixellast; pixel += pixy) {
01495                                 *(Uint8 *) pixel = color;
01496                         }
01497                         break;
01498                 case 2:
01499                         for (; pixel <= pixellast; pixel += pixy) {
01500                                 *(Uint16 *) pixel = color;
01501                         }
01502                         break;
01503                 case 3:
01504                         for (; pixel <= pixellast; pixel += pixy) {
01505                                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
01506                                         pixel[0] = (color >> 16) & 0xff;
01507                                         pixel[1] = (color >> 8) & 0xff;
01508                                         pixel[2] = color & 0xff;
01509                                 } else {
01510                                         pixel[0] = color & 0xff;
01511                                         pixel[1] = (color >> 8) & 0xff;
01512                                         pixel[2] = (color >> 16) & 0xff;
01513                                 }
01514                         }
01515                         break;
01516                 default:                /* case 4 */
01517                         for (; pixel <= pixellast; pixel += pixy) {
01518                                 *(Uint32 *) pixel = color;
01519                         }
01520                         break;
01521                 }
01522 
01523                 /* Unlock surface */
01524                 if (SDL_MUSTLOCK(dst)) {
01525                         SDL_UnlockSurface(dst);
01526                 }
01527 
01528                 /*
01529                 * Set result code 
01530                 */
01531                 result = 0;
01532 
01533         } else {
01534 
01535                 /*
01536                 * Alpha blending blit 
01537                 */
01538 
01539                 result = _VLineAlpha(dst, x, y1, y1 + h, color);
01540 
01541         }
01542 
01543         return (result);
01544 }
01545 
01560 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01561 {
01562         /*
01563         * Draw 
01564         */
01565         return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01566 }
01567 
01580 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
01581 {
01582         int result;
01583         Sint16 tmp;
01584 
01585         /* Check destination surface */
01586         if (dst == NULL)
01587         {
01588                 return -1;
01589         }
01590 
01591         /*
01592         * Check visibility of clipping rectangle
01593         */
01594         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01595                 return 0;
01596         }
01597 
01598         /*
01599         * Test for special cases of straight lines or single point 
01600         */
01601         if (x1 == x2) {
01602                 if (y1 == y2) {
01603                         return (pixelColor(dst, x1, y1, color));
01604                 } else {
01605                         return (vlineColor(dst, x1, y1, y2, color));
01606                 }
01607         } else {
01608                 if (y1 == y2) {
01609                         return (hlineColor(dst, x1, x2, y1, color));
01610                 }
01611         }
01612 
01613         /*
01614         * Swap x1, x2 if required 
01615         */
01616         if (x1 > x2) {
01617                 tmp = x1;
01618                 x1 = x2;
01619                 x2 = tmp;
01620         }
01621 
01622         /*
01623         * Swap y1, y2 if required 
01624         */
01625         if (y1 > y2) {
01626                 tmp = y1;
01627                 y1 = y2;
01628                 y2 = tmp;
01629         }
01630 
01631         /*
01632         * Draw rectangle 
01633         */
01634         result = 0;
01635         result |= hlineColor(dst, x1, x2, y1, color);
01636         result |= hlineColor(dst, x1, x2, y2, color);
01637         y1 += 1;
01638         y2 -= 1;
01639         if (y1 <= y2) {
01640                 result |= vlineColor(dst, x1, y1, y2, color);
01641                 result |= vlineColor(dst, x2, y1, y2, color);
01642         }
01643 
01644         return (result);
01645 
01646 }
01647 
01663 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01664 {
01665         /*
01666         * Draw 
01667         */
01668         return (rectangleColor
01669                 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01670 }
01671 
01685 int roundedRectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
01686 {
01687         int result;
01688         Sint16 w, h, tmp;
01689         Sint16 xx1, xx2, yy1, yy2;
01690 
01691         /* 
01692         * Check destination surface 
01693         */
01694         if (dst == NULL)
01695         {
01696                 return -1;
01697         }
01698 
01699         /*
01700         * Check radius vor valid range
01701         */
01702         if (rad < 0) {
01703                 return -1;
01704         }
01705 
01706         /*
01707         * Special case - no rounding
01708         */
01709         if (rad == 0) {
01710                 return rectangleColor(dst, x1, y1, x2, y2, color);
01711         }
01712 
01713         /*
01714         * Check visibility of clipping rectangle
01715         */
01716         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01717                 return 0;
01718         }
01719 
01720         /*
01721         * Test for special cases of straight lines or single point 
01722         */
01723         if (x1 == x2) {
01724                 if (y1 == y2) {
01725                         return (pixelColor(dst, x1, y1, color));
01726                 } else {
01727                         return (vlineColor(dst, x1, y1, y2, color));
01728                 }
01729         } else {
01730                 if (y1 == y2) {
01731                         return (hlineColor(dst, x1, x2, y1, color));
01732                 }
01733         }
01734 
01735         /*
01736         * Swap x1, x2 if required 
01737         */
01738         if (x1 > x2) {
01739                 tmp = x1;
01740                 x1 = x2;
01741                 x2 = tmp;
01742         }
01743 
01744         /*
01745         * Swap y1, y2 if required 
01746         */
01747         if (y1 > y2) {
01748                 tmp = y1;
01749                 y1 = y2;
01750                 y2 = tmp;
01751         }
01752 
01753         /*
01754         * Calculate width&height 
01755         */
01756         w = x2 - x1;
01757         h = y2 - y1;
01758 
01759         /*
01760         * Maybe adjust radius
01761         */
01762         if ((rad * 2) > w)  
01763         {
01764                 rad = w / 2;
01765         }
01766         if ((rad * 2) > h)
01767         {
01768                 rad = h / 2;
01769         }
01770 
01771         /*
01772         * Draw corners
01773         */
01774         result = 0;
01775         xx1 = x1 + rad;
01776         xx2 = x2 - rad;
01777         yy1 = y1 + rad;
01778         yy2 = y2 - rad;
01779         result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
01780         result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
01781         result |= arcColor(dst, xx1, yy2, rad,  90, 180, color);
01782         result |= arcColor(dst, xx2, yy2, rad,   0,  90, color);
01783 
01784         /*
01785         * Draw lines
01786         */
01787         if (xx1 <= xx2) {
01788                 result |= hlineColor(dst, xx1, xx2, y1, color);
01789                 result |= hlineColor(dst, xx1, xx2, y2, color);
01790         }
01791         if (yy1 <= yy2) {
01792                 result |= vlineColor(dst, x1, yy1, yy2, color);
01793                 result |= vlineColor(dst, x2, yy1, yy2, color);
01794         }
01795 
01796         return result;
01797 }
01798 
01815 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01816 {
01817         /*
01818         * Draw 
01819         */
01820         return (roundedRectangleColor
01821                 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01822 }
01823 
01837 int roundedBoxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
01838 {
01839         int result;
01840         Sint16 w, h, tmp;
01841         Sint16 xx1, xx2, yy1, yy2;
01842 
01843         /* 
01844         * Check destination surface 
01845         */
01846         if (dst == NULL)
01847         {
01848                 return -1;
01849         }
01850 
01851         /*
01852         * Check radius vor valid range
01853         */
01854         if (rad < 0) {
01855                 return -1;
01856         }
01857 
01858         /*
01859         * Special case - no rounding
01860         */
01861         if (rad == 0) {
01862                 return rectangleColor(dst, x1, y1, x2, y2, color);
01863         }
01864 
01865         /*
01866         * Check visibility of clipping rectangle
01867         */
01868         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
01869                 return 0;
01870         }
01871 
01872         /*
01873         * Test for special cases of straight lines or single point 
01874         */
01875         if (x1 == x2) {
01876                 if (y1 == y2) {
01877                         return (pixelColor(dst, x1, y1, color));
01878                 } else {
01879                         return (vlineColor(dst, x1, y1, y2, color));
01880                 }
01881         } else {
01882                 if (y1 == y2) {
01883                         return (hlineColor(dst, x1, x2, y1, color));
01884                 }
01885         }
01886 
01887         /*
01888         * Swap x1, x2 if required 
01889         */
01890         if (x1 > x2) {
01891                 tmp = x1;
01892                 x1 = x2;
01893                 x2 = tmp;
01894         }
01895 
01896         /*
01897         * Swap y1, y2 if required 
01898         */
01899         if (y1 > y2) {
01900                 tmp = y1;
01901                 y1 = y2;
01902                 y2 = tmp;
01903         }
01904 
01905         /*
01906         * Calculate width&height 
01907         */
01908         w = x2 - x1;
01909         h = y2 - y1;
01910 
01911         /*
01912         * Maybe adjust radius
01913         */
01914         if ((rad * 2) > w)  
01915         {
01916                 rad = w / 2;
01917         }
01918         if ((rad * 2) > h)
01919         {
01920                 rad = h / 2;
01921         }
01922 
01923         /*
01924         * Draw corners
01925         */
01926         result = 0;
01927         xx1 = x1 + rad;
01928         xx2 = x2 - rad;
01929         yy1 = y1 + rad;
01930         yy2 = y2 - rad;
01931         result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
01932         result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
01933         result |= filledPieColor(dst, xx1, yy2, rad,  90, 180, color);
01934         result |= filledPieColor(dst, xx2, yy2, rad,   0,  90, color);
01935 
01936         /*
01937         * Draw body
01938         */
01939         xx1++;
01940         xx2--;
01941         yy1++;
01942         yy2--;
01943         if (xx1 <= xx2) {
01944                 result |= boxColor(dst, xx1, y1, xx2, y2, color);
01945         }
01946         if (yy1 <= yy2) {
01947                 result |= boxColor(dst, x1, yy1, xx1-1, yy2, color);
01948                 result |= boxColor(dst, xx2+1, yy1, x2, yy2, color);
01949         }
01950 
01951         return result;
01952 }
01953 
01970 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,
01971         Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
01972 {
01973         /*
01974         * Draw 
01975         */
01976         return (roundedBoxColor
01977                 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
01978 }
01979 
01980 /* --------- Clipping routines for line */
01981 
01982 /* Clipping based heavily on code from                       */
01983 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
01984 
01985 #define CLIP_LEFT_EDGE   0x1
01986 #define CLIP_RIGHT_EDGE  0x2
01987 #define CLIP_BOTTOM_EDGE 0x4
01988 #define CLIP_TOP_EDGE    0x8
01989 #define CLIP_INSIDE(a)   (!a)
01990 #define CLIP_REJECT(a,b) (a&b)
01991 #define CLIP_ACCEPT(a,b) (!(a|b))
01992 
02005 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
02006 {
02007         int code = 0;
02008 
02009         if (x < left) {
02010                 code |= CLIP_LEFT_EDGE;
02011         } else if (x > right) {
02012                 code |= CLIP_RIGHT_EDGE;
02013         }
02014         if (y < top) {
02015                 code |= CLIP_TOP_EDGE;
02016         } else if (y > bottom) {
02017                 code |= CLIP_BOTTOM_EDGE;
02018         }
02019         return code;
02020 }
02021 
02031 static int _clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
02032 {
02033         Sint16 left, right, top, bottom;
02034         int code1, code2;
02035         int draw = 0;
02036         Sint16 swaptmp;
02037         float m;
02038 
02039         /*
02040         * Get clipping boundary 
02041         */
02042         left = dst->clip_rect.x;
02043         right = dst->clip_rect.x + dst->clip_rect.w - 1;
02044         top = dst->clip_rect.y;
02045         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02046 
02047         while (1) {
02048                 code1 = _clipEncode(*x1, *y1, left, top, right, bottom);
02049                 code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
02050                 if (CLIP_ACCEPT(code1, code2)) {
02051                         draw = 1;
02052                         break;
02053                 } else if (CLIP_REJECT(code1, code2))
02054                         break;
02055                 else {
02056                         if (CLIP_INSIDE(code1)) {
02057                                 swaptmp = *x2;
02058                                 *x2 = *x1;
02059                                 *x1 = swaptmp;
02060                                 swaptmp = *y2;
02061                                 *y2 = *y1;
02062                                 *y1 = swaptmp;
02063                                 swaptmp = code2;
02064                                 code2 = code1;
02065                                 code1 = swaptmp;
02066                         }
02067                         if (*x2 != *x1) {
02068                                 m = (float)(*y2 - *y1) / (float)(*x2 - *x1);
02069                         } else {
02070                                 m = 1.0f;
02071                         }
02072                         if (code1 & CLIP_LEFT_EDGE) {
02073                                 *y1 += (Sint16) ((left - *x1) * m);
02074                                 *x1 = left;
02075                         } else if (code1 & CLIP_RIGHT_EDGE) {
02076                                 *y1 += (Sint16) ((right - *x1) * m);
02077                                 *x1 = right;
02078                         } else if (code1 & CLIP_BOTTOM_EDGE) {
02079                                 if (*x2 != *x1) {
02080                                         *x1 += (Sint16) ((bottom - *y1) / m);
02081                                 }
02082                                 *y1 = bottom;
02083                         } else if (code1 & CLIP_TOP_EDGE) {
02084                                 if (*x2 != *x1) {
02085                                         *x1 += (Sint16) ((top - *y1) / m);
02086                                 }
02087                                 *y1 = top;
02088                         }
02089                 }
02090         }
02091 
02092         return draw;
02093 }
02094 
02107 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
02108 {
02109         Sint16 left, right, top, bottom;
02110         Uint8 *pixel, *pixellast;
02111         int x, dx;
02112         int dy;
02113         int pixx, pixy;
02114         Sint16 w, h, tmp;
02115         int result;
02116         Uint8 *colorptr;
02117 
02118         /*
02119         * Check visibility of clipping rectangle
02120         */
02121         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02122                 return(0);
02123         }
02124 
02125         /*
02126         * Order coordinates to ensure that
02127         * x1<=x2 and y1<=y2 
02128         */
02129         if (x1 > x2) {
02130                 tmp = x1;
02131                 x1 = x2;
02132                 x2 = tmp;
02133         }
02134         if (y1 > y2) {
02135                 tmp = y1;
02136                 y1 = y2;
02137                 y2 = tmp;
02138         }
02139 
02140         /* 
02141         * Get clipping boundary and 
02142         * check visibility 
02143         */
02144         left = dst->clip_rect.x;
02145         if (x2<left) {
02146                 return(0);
02147         }
02148         right = dst->clip_rect.x + dst->clip_rect.w - 1;
02149         if (x1>right) {
02150                 return(0);
02151         }
02152         top = dst->clip_rect.y;
02153         if (y2<top) {
02154                 return(0);
02155         }
02156         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02157         if (y1>bottom) {
02158                 return(0);
02159         }
02160 
02161         /* Clip all points */
02162         if (x1<left) { 
02163                 x1=left; 
02164         } else if (x1>right) {
02165                 x1=right;
02166         }
02167         if (x2<left) { 
02168                 x2=left; 
02169         } else if (x2>right) {
02170                 x2=right;
02171         }
02172         if (y1<top) { 
02173                 y1=top; 
02174         } else if (y1>bottom) {
02175                 y1=bottom;
02176         }
02177         if (y2<top) { 
02178                 y2=top; 
02179         } else if (y2>bottom) {
02180                 y2=bottom;
02181         }
02182 
02183         /*
02184         * Test for special cases of straight line or single point 
02185         */
02186         if (x1 == x2) {
02187                 if (y1 == y2) {
02188                         return (pixelColor(dst, x1, y1, color));
02189                 } else { 
02190                         return (vlineColor(dst, x1, y1, y2, color));
02191                 }
02192         }
02193         if (y1 == y2) {
02194                 return (hlineColor(dst, x1, x2, y1, color));
02195         }
02196 
02197         /*
02198         * Calculate width&height 
02199         */
02200         w = x2 - x1;
02201         h = y2 - y1;
02202 
02203         /*
02204         * Alpha check 
02205         */
02206         if ((color & 255) == 255) {
02207 
02208                 /*
02209                 * No alpha-blending required 
02210                 */
02211 
02212                 /*
02213                 * Setup color 
02214                 */
02215                 colorptr = (Uint8 *) & color;
02216                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02217                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02218                 } else {
02219                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02220                 }
02221 
02222                 /*
02223                 * Lock the surface 
02224                 */
02225                 if (SDL_MUSTLOCK(dst)) {
02226                         if (SDL_LockSurface(dst) < 0) {
02227                                 return (-1);
02228                         }
02229                 }
02230 
02231                 /*
02232                 * More variable setup 
02233                 */
02234                 dx = w;
02235                 dy = h;
02236                 pixx = dst->format->BytesPerPixel;
02237                 pixy = dst->pitch;
02238                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
02239                 pixellast = pixel + pixx * dx + pixy * dy;
02240                 dx++;
02241 
02242                 /*
02243                 * Draw 
02244                 */
02245                 switch (dst->format->BytesPerPixel) {
02246                 case 1:
02247                         for (; pixel <= pixellast; pixel += pixy) {
02248                                 memset(pixel, (Uint8) color, dx);
02249                         }
02250                         break;
02251                 case 2:
02252                         pixy -= (pixx * dx);
02253                         for (; pixel <= pixellast; pixel += pixy) {
02254                                 for (x = 0; x < dx; x++) {
02255                                         *(Uint16*) pixel = color;
02256                                         pixel += pixx;
02257                                 }
02258                         }
02259                         break;
02260                 case 3:
02261                         pixy -= (pixx * dx);
02262                         for (; pixel <= pixellast; pixel += pixy) {
02263                                 for (x = 0; x < dx; x++) {
02264                                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02265                                                 pixel[0] = (color >> 16) & 0xff;
02266                                                 pixel[1] = (color >> 8) & 0xff;
02267                                                 pixel[2] = color & 0xff;
02268                                         } else {
02269                                                 pixel[0] = color & 0xff;
02270                                                 pixel[1] = (color >> 8) & 0xff;
02271                                                 pixel[2] = (color >> 16) & 0xff;
02272                                         }
02273                                         pixel += pixx;
02274                                 }
02275                         }
02276                         break;
02277                 default:                /* case 4 */
02278                         pixy -= (pixx * dx);
02279                         for (; pixel <= pixellast; pixel += pixy) {
02280                                 for (x = 0; x < dx; x++) {
02281                                         *(Uint32 *) pixel = color;
02282                                         pixel += pixx;
02283                                 }
02284                         }
02285                         break;
02286                 }
02287 
02288                 /* Unlock surface */
02289                 if (SDL_MUSTLOCK(dst)) {
02290                         SDL_UnlockSurface(dst);
02291                 }
02292 
02293                 result = 0;
02294 
02295         } else {
02296 
02297                 result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
02298 
02299         }
02300 
02301         return (result);
02302 }
02303 
02319 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02320 {
02321         /*
02322         * Draw 
02323         */
02324         return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02325 }
02326 
02327 /* ----- Line */
02328 
02329 /* Non-alpha line drawing code adapted from routine          */
02330 /* by Pete Shinners, pete@shinners.org                       */
02331 /* Originally from pygame, http://pygame.seul.org            */
02332 
02333 #define ABS(a) (((a)<0) ? -(a) : (a))
02334 
02347 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
02348 {
02349         int pixx, pixy;
02350         int x, y;
02351         int dx, dy;
02352         int ax, ay;
02353         int sx, sy;
02354         int swaptmp;
02355         Uint8 *pixel;
02356         Uint8 *colorptr;
02357 
02358         /*
02359         * Clip line and test if we have to draw 
02360         */
02361         if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
02362                 return (0);
02363         }
02364 
02365         /*
02366         * Test for special cases of straight lines or single point 
02367         */
02368         if (x1 == x2) {
02369                 if (y1 < y2) {
02370                         return (vlineColor(dst, x1, y1, y2, color));
02371                 } else if (y1 > y2) {
02372                         return (vlineColor(dst, x1, y2, y1, color));
02373                 } else {
02374                         return (pixelColor(dst, x1, y1, color));
02375                 }
02376         }
02377         if (y1 == y2) {
02378                 if (x1 < x2) {
02379                         return (hlineColor(dst, x1, x2, y1, color));
02380                 } else if (x1 > x2) {
02381                         return (hlineColor(dst, x2, x1, y1, color));
02382                 }
02383         }
02384 
02385         /*
02386         * Variable setup 
02387         */
02388         dx = x2 - x1;
02389         dy = y2 - y1;
02390         sx = (dx >= 0) ? 1 : -1;
02391         sy = (dy >= 0) ? 1 : -1;
02392 
02393         /* Lock surface */
02394         if (SDL_MUSTLOCK(dst)) {
02395                 if (SDL_LockSurface(dst) < 0) {
02396                         return (-1);
02397                 }
02398         }
02399 
02400         /*
02401         * Check for alpha blending 
02402         */
02403         if ((color & 255) == 255) {
02404 
02405                 /*
02406                 * No alpha blending - use fast pixel routines 
02407                 */
02408 
02409                 /*
02410                 * Setup color 
02411                 */
02412                 colorptr = (Uint8 *) & color;
02413                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02414                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02415                 } else {
02416                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02417                 }
02418 
02419                 /*
02420                 * More variable setup 
02421                 */
02422                 dx = sx * dx + 1;
02423                 dy = sy * dy + 1;
02424                 pixx = dst->format->BytesPerPixel;
02425                 pixy = dst->pitch;
02426                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
02427                 pixx *= sx;
02428                 pixy *= sy;
02429                 if (dx < dy) {
02430                         swaptmp = dx;
02431                         dx = dy;
02432                         dy = swaptmp;
02433                         swaptmp = pixx;
02434                         pixx = pixy;
02435                         pixy = swaptmp;
02436                 }
02437 
02438                 /*
02439                 * Draw 
02440                 */
02441                 x = 0;
02442                 y = 0;
02443                 switch (dst->format->BytesPerPixel) {
02444                 case 1:
02445                         for (; x < dx; x++, pixel += pixx) {
02446                                 *pixel = color;
02447                                 y += dy;
02448                                 if (y >= dx) {
02449                                         y -= dx;
02450                                         pixel += pixy;
02451                                 }
02452                         }
02453                         break;
02454                 case 2:
02455                         for (; x < dx; x++, pixel += pixx) {
02456                                 *(Uint16 *) pixel = color;
02457                                 y += dy;
02458                                 if (y >= dx) {
02459                                         y -= dx;
02460                                         pixel += pixy;
02461                                 }
02462                         }
02463                         break;
02464                 case 3:
02465                         for (; x < dx; x++, pixel += pixx) {
02466                                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02467                                         pixel[0] = (color >> 16) & 0xff;
02468                                         pixel[1] = (color >> 8) & 0xff;
02469                                         pixel[2] = color & 0xff;
02470                                 } else {
02471                                         pixel[0] = color & 0xff;
02472                                         pixel[1] = (color >> 8) & 0xff;
02473                                         pixel[2] = (color >> 16) & 0xff;
02474                                 }
02475                                 y += dy;
02476                                 if (y >= dx) {
02477                                         y -= dx;
02478                                         pixel += pixy;
02479                                 }
02480                         }
02481                         break;
02482                 default:                /* case 4 */
02483                         for (; x < dx; x++, pixel += pixx) {
02484                                 *(Uint32 *) pixel = color;
02485                                 y += dy;
02486                                 if (y >= dx) {
02487                                         y -= dx;
02488                                         pixel += pixy;
02489                                 }
02490                         }
02491                         break;
02492                 }
02493 
02494         } else {
02495 
02496                 /*
02497                 * Alpha blending required - use single-pixel blits 
02498                 */
02499 
02500                 ax = ABS(dx) << 1;
02501                 ay = ABS(dy) << 1;
02502                 x = x1;
02503                 y = y1;
02504                 if (ax > ay) {
02505                         int d = ay - (ax >> 1);
02506 
02507                         while (x != x2) {
02508                                 pixelColorNolock (dst, x, y, color);
02509                                 if (d > 0 || (d == 0 && sx == 1)) {
02510                                         y += sy;
02511                                         d -= ax;
02512                                 }
02513                                 x += sx;
02514                                 d += ay;
02515                         }
02516                 } else {
02517                         int d = ax - (ay >> 1);
02518 
02519                         while (y != y2) {
02520                                 pixelColorNolock (dst, x, y, color);
02521                                 if (d > 0 || ((d == 0) && (sy == 1))) {
02522                                         x += sx;
02523                                         d -= ay;
02524                                 }
02525                                 y += sy;
02526                                 d += ax;
02527                         }
02528                 }
02529                 pixelColorNolock (dst, x, y, color);
02530 
02531         }
02532 
02533         /* Unlock surface */
02534         if (SDL_MUSTLOCK(dst)) {
02535                 SDL_UnlockSurface(dst);
02536         }
02537 
02538         return (0);
02539 }
02540 
02556 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02557 {
02558         /*
02559         * Draw 
02560         */
02561         return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
02562 }
02563 
02564 /* AA Line */
02565 
02566 #define AAlevels 256
02567 #define AAbits 8
02568 
02589 int _aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
02590 {
02591         Sint32 xx0, yy0, xx1, yy1;
02592         int result;
02593         Uint32 intshift, erracc, erradj;
02594         Uint32 erracctmp, wgt, wgtcompmask;
02595         int dx, dy, tmp, xdir, y0p1, x0pxdir;
02596 
02597         /*
02598         * Check visibility of clipping rectangle
02599         */
02600         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02601                 return(0);
02602         }
02603 
02604         /*
02605         * Clip line and test if we have to draw 
02606         */
02607         if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
02608                 return (0);
02609         }
02610 
02611         /*
02612         * Keep on working with 32bit numbers 
02613         */
02614         xx0 = x1;
02615         yy0 = y1;
02616         xx1 = x2;
02617         yy1 = y2;
02618 
02619         /*
02620         * Reorder points if required 
02621         */
02622         if (yy0 > yy1) {
02623                 tmp = yy0;
02624                 yy0 = yy1;
02625                 yy1 = tmp;
02626                 tmp = xx0;
02627                 xx0 = xx1;
02628                 xx1 = tmp;
02629         }
02630 
02631         /*
02632         * Calculate distance 
02633         */
02634         dx = xx1 - xx0;
02635         dy = yy1 - yy0;
02636 
02637         /*
02638         * Check for special cases 
02639         */
02640         if (dx == 0) {
02641                 /*
02642                 * Vertical line 
02643                 */
02644                 if (draw_endpoint)
02645                 {
02646                         return (vlineColor(dst, x1, y1, y2, color));
02647                 } else {
02648                         if (dy>0) {
02649                                 return (vlineColor(dst, x1, yy0, yy0+dy, color));
02650                         } else {
02651                                 return (pixelColor(dst, x1, y1, color));
02652                         }
02653                 }
02654         } else if (dy == 0) {
02655                 /*
02656                 * Horizontal line 
02657                 */
02658                 if (draw_endpoint)
02659                 {
02660                         return (hlineColor(dst, x1, x2, y1, color));
02661                 } else {
02662                         if (dx!=0) {
02663                                 return (hlineColor(dst, xx0, xx0+dx, y1, color));
02664                         } else {
02665                                 return (pixelColor(dst, x1, y1, color));
02666                         }
02667                 }
02668         } else if ((dx == dy) && (draw_endpoint)) {
02669                 /*
02670                 * Diagonal line (with endpoint)
02671                 */
02672                 return (lineColor(dst, x1, y1, x2, y2, color));
02673         }
02674 
02675         /*
02676         * Adjust for negative dx and set xdir 
02677         */
02678         if (dx >= 0) {
02679                 xdir = 1;
02680         } else {
02681                 xdir = -1;
02682                 dx = (-dx);
02683         }
02684 
02685         /*
02686         * Line is not horizontal, vertical or diagonal (with endpoint)
02687         */
02688         result = 0;
02689 
02690         /*
02691         * Zero accumulator 
02692         */
02693         erracc = 0;
02694 
02695         /*
02696         * # of bits by which to shift erracc to get intensity level 
02697         */
02698         intshift = 32 - AAbits;
02699 
02700         /*
02701         * Mask used to flip all bits in an intensity weighting 
02702         */
02703         wgtcompmask = AAlevels - 1;
02704 
02705         /* Lock surface */
02706         if (SDL_MUSTLOCK(dst)) {
02707                 if (SDL_LockSurface(dst) < 0) {
02708                         return (-1);
02709                 }
02710         }
02711 
02712         /*
02713         * Draw the initial pixel in the foreground color 
02714         */
02715         result |= pixelColorNolock(dst, x1, y1, color);
02716 
02717         /*
02718         * x-major or y-major? 
02719         */
02720         if (dy > dx) {
02721 
02722                 /*
02723                 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
02724                 * X advances every time Y advances 1 pixel, truncating the result so that
02725                 * we won't overrun the endpoint along the X axis 
02726                 */
02727                 /*
02728                 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; 
02729                 */
02730                 erradj = ((dx << 16) / dy) << 16;
02731 
02732                 /*
02733                 * draw all pixels other than the first and last 
02734                 */
02735                 x0pxdir = xx0 + xdir;
02736                 while (--dy) {
02737                         erracctmp = erracc;
02738                         erracc += erradj;
02739                         if (erracc <= erracctmp) {
02740                                 /*
02741                                 * rollover in error accumulator, x coord advances 
02742                                 */
02743                                 xx0 = x0pxdir;
02744                                 x0pxdir += xdir;
02745                         }
02746                         yy0++;          /* y-major so always advance Y */
02747 
02748                         /*
02749                         * the AAbits most significant bits of erracc give us the intensity
02750                         * weighting for this pixel, and the complement of the weighting for
02751                         * the paired pixel. 
02752                         */
02753                         wgt = (erracc >> intshift) & 255;
02754                         result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
02755                         result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
02756                 }
02757 
02758         } else {
02759 
02760                 /*
02761                 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
02762                 * that Y advances each time X advances 1 pixel, truncating the result so
02763                 * that we won't overrun the endpoint along the X axis. 
02764                 */
02765                 /*
02766                 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; 
02767                 */
02768                 erradj = ((dy << 16) / dx) << 16;
02769 
02770                 /*
02771                 * draw all pixels other than the first and last 
02772                 */
02773                 y0p1 = yy0 + 1;
02774                 while (--dx) {
02775 
02776                         erracctmp = erracc;
02777                         erracc += erradj;
02778                         if (erracc <= erracctmp) {
02779                                 /*
02780                                 * Accumulator turned over, advance y 
02781                                 */
02782                                 yy0 = y0p1;
02783                                 y0p1++;
02784                         }
02785                         xx0 += xdir;    /* x-major so always advance X */
02786                         /*
02787                         * the AAbits most significant bits of erracc give us the intensity
02788                         * weighting for this pixel, and the complement of the weighting for
02789                         * the paired pixel. 
02790                         */
02791                         wgt = (erracc >> intshift) & 255;
02792                         result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
02793                         result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
02794                 }
02795         }
02796 
02797         /*
02798         * Do we have to draw the endpoint 
02799         */
02800         if (draw_endpoint) {
02801                 /*
02802                 * Draw final pixel, always exactly intersected by the line and doesn't
02803                 * need to be weighted. 
02804                 */
02805                 result |= pixelColorNolock (dst, x2, y2, color);
02806         }
02807 
02808         /* Unlock surface */
02809         if (SDL_MUSTLOCK(dst)) {
02810                 SDL_UnlockSurface(dst);
02811         }
02812 
02813         return (result);
02814 }
02815 
02828 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
02829 {
02830         return (_aalineColor(dst, x1, y1, x2, y2, color, 1));
02831 }
02832 
02848 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
02849 {
02850         return (_aalineColor
02851                 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
02852 }
02853 
02854 
02855 /* ----- Circle */
02856 
02872 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
02873 {
02874         Sint16 left, right, top, bottom;
02875         int result;
02876         Sint16 x1, y1, x2, y2;
02877         Sint16 cx = 0;
02878         Sint16 cy = rad;
02879         Sint16 df = 1 - rad;
02880         Sint16 d_e = 3;
02881         Sint16 d_se = -2 * rad + 5;
02882         Sint16 xpcx, xmcx, xpcy, xmcy;
02883         Sint16 ypcy, ymcy, ypcx, ymcx;
02884         Uint8 *colorptr;
02885 
02886         /*
02887         * Check visibility of clipping rectangle
02888         */
02889         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
02890                 return(0);
02891         }
02892 
02893         /*
02894         * Sanity check radius 
02895         */
02896         if (rad < 0) {
02897                 return (-1);
02898         }
02899 
02900         /*
02901         * Special case for rad=0 - draw a point 
02902         */
02903         if (rad == 0) {
02904                 return (pixelColor(dst, x, y, color));
02905         }
02906 
02907         /*
02908         * Get circle and clipping boundary and 
02909         * test if bounding box of circle is visible 
02910         */
02911         x2 = x + rad;
02912         left = dst->clip_rect.x;
02913         if (x2<left) {
02914                 return(0);
02915         } 
02916         x1 = x - rad;
02917         right = dst->clip_rect.x + dst->clip_rect.w - 1;
02918         if (x1>right) {
02919                 return(0);
02920         } 
02921         y2 = y + rad;
02922         top = dst->clip_rect.y;
02923         if (y2<top) {
02924                 return(0);
02925         } 
02926         y1 = y - rad;
02927         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
02928         if (y1>bottom) {
02929                 return(0);
02930         } 
02931 
02932         /*
02933         * Draw circle 
02934         */
02935         result = 0;
02936 
02937         /* Lock surface */
02938         if (SDL_MUSTLOCK(dst)) {
02939                 if (SDL_LockSurface(dst) < 0) {
02940                         return (-1);
02941                 }
02942         }
02943 
02944         /*
02945         * Alpha Check 
02946         */
02947         if ((color & 255) == 255) {
02948 
02949                 /*
02950                 * No Alpha - direct memory writes 
02951                 */
02952 
02953                 /*
02954                 * Setup color 
02955                 */
02956                 colorptr = (Uint8 *) & color;
02957                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
02958                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
02959                 } else {
02960                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
02961                 }
02962 
02963                 /*
02964                 * Draw 
02965                 */
02966                 do {
02967                         ypcy = y + cy;
02968                         ymcy = y - cy;
02969                         if (cx > 0) {
02970                                 xpcx = x + cx;
02971                                 xmcx = x - cx;
02972                                 result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
02973                                 result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
02974                                 result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
02975                                 result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
02976                         } else {
02977                                 result |= fastPixelColorNolock(dst, x, ymcy, color);
02978                                 result |= fastPixelColorNolock(dst, x, ypcy, color);
02979                         }
02980                         xpcy = x + cy;
02981                         xmcy = x - cy;
02982                         if ((cx > 0) && (cx != cy)) {
02983                                 ypcx = y + cx;
02984                                 ymcx = y - cx;
02985                                 result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
02986                                 result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
02987                                 result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
02988                                 result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
02989                         } else if (cx == 0) {
02990                                 result |= fastPixelColorNolock(dst, xmcy, y, color);
02991                                 result |= fastPixelColorNolock(dst, xpcy, y, color);
02992                         }
02993                         /*
02994                         * Update 
02995                         */
02996                         if (df < 0) {
02997                                 df += d_e;
02998                                 d_e += 2;
02999                                 d_se += 2;
03000                         } else {
03001                                 df += d_se;
03002                                 d_e += 2;
03003                                 d_se += 4;
03004                                 cy--;
03005                         }
03006                         cx++;
03007                 } while (cx <= cy);
03008 
03009                 /*
03010                 * Unlock surface 
03011                 */
03012                 SDL_UnlockSurface(dst);
03013 
03014         } else {
03015 
03016                 /*
03017                 * Using Alpha - blended pixel blits 
03018                 */
03019 
03020                 do {
03021                         /*
03022                         * Draw 
03023                         */
03024                         ypcy = y + cy;
03025                         ymcy = y - cy;
03026                         if (cx > 0) {
03027                                 xpcx = x + cx;
03028                                 xmcx = x - cx;
03029                                 result |= pixelColorNolock (dst, xmcx, ypcy, color);
03030                                 result |= pixelColorNolock (dst, xpcx, ypcy, color);
03031                                 result |= pixelColorNolock (dst, xmcx, ymcy, color);
03032                                 result |= pixelColorNolock (dst, xpcx, ymcy, color);
03033                         } else {
03034                                 result |= pixelColorNolock (dst, x, ymcy, color);
03035                                 result |= pixelColorNolock (dst, x, ypcy, color);
03036                         }
03037                         xpcy = x + cy;
03038                         xmcy = x - cy;
03039                         if ((cx > 0) && (cx != cy)) {
03040                                 ypcx = y + cx;
03041                                 ymcx = y - cx;
03042                                 result |= pixelColorNolock (dst, xmcy, ypcx, color);
03043                                 result |= pixelColorNolock (dst, xpcy, ypcx, color);
03044                                 result |= pixelColorNolock (dst, xmcy, ymcx, color);
03045                                 result |= pixelColorNolock (dst, xpcy, ymcx, color);
03046                         } else if (cx == 0) {
03047                                 result |= pixelColorNolock (dst, xmcy, y, color);
03048                                 result |= pixelColorNolock (dst, xpcy, y, color);
03049                         }
03050                         /*
03051                         * Update 
03052                         */
03053                         if (df < 0) {
03054                                 df += d_e;
03055                                 d_e += 2;
03056                                 d_se += 2;
03057                         } else {
03058                                 df += d_se;
03059                                 d_e += 2;
03060                                 d_se += 4;
03061                                 cy--;
03062                         }
03063                         cx++;
03064                 } while (cx <= cy);
03065 
03066         }                               /* Alpha check */
03067 
03068         /* Unlock surface */
03069         if (SDL_MUSTLOCK(dst)) {
03070                 SDL_UnlockSurface(dst);
03071         }
03072 
03073         return (result);
03074 }
03075 
03090 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03091 {
03092         /*
03093         * Draw 
03094         */
03095         return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03096 }
03097 
03098 /* ----- Arc */
03099 
03117 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
03118 {
03119         Sint16 left, right, top, bottom;
03120         int result;
03121         Sint16 x1, y1, x2, y2;
03122         Sint16 cx = 0;
03123         Sint16 cy = rad;
03124         Sint16 df = 1 - rad;
03125         Sint16 d_e = 3;
03126         Sint16 d_se = -2 * rad + 5;
03127         Sint16 xpcx, xmcx, xpcy, xmcy;
03128         Sint16 ypcy, ymcy, ypcx, ymcx;
03129         Uint8 *colorptr;
03130         Uint8 drawoct;
03131         int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
03132         double dstart, dend, temp = 0.;
03133 
03134         /*
03135         * Check visibility of clipping rectangle
03136         */
03137         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03138                 return(0);
03139         }
03140 
03141         /*
03142         * Sanity check radius 
03143         */
03144         if (rad < 0) {
03145                 return (-1);
03146         }
03147 
03148         /*
03149         * Special case for rad=0 - draw a point 
03150         */
03151         if (rad == 0) {
03152                 return (pixelColor(dst, x, y, color));
03153         }
03154 
03155         /*
03156         * Get arc's circle and clipping boundary and 
03157         * test if bounding box of circle is visible 
03158         */
03159         x2 = x + rad;
03160         left = dst->clip_rect.x;
03161         if (x2<left) {
03162                 return(0);
03163         } 
03164         x1 = x - rad;
03165         right = dst->clip_rect.x + dst->clip_rect.w - 1;
03166         if (x1>right) {
03167                 return(0);
03168         } 
03169         y2 = y + rad;
03170         top = dst->clip_rect.y;
03171         if (y2<top) {
03172                 return(0);
03173         } 
03174         y1 = y - rad;
03175         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03176         if (y1>bottom) {
03177                 return(0);
03178         }  
03179 
03180         // Octant labelling
03181         //      
03182         //  \ 5 | 6 /
03183         //   \  |  /
03184         //  4 \ | / 7
03185         //     \|/
03186         //------+------ +x
03187         //     /|\
03188         //  3 / | \ 0
03189         //   /  |  \
03190         //  / 2 | 1 \
03191         //      +y
03192 
03193         // Initially reset bitmask to 0x00000000
03194         // the set whether or not to keep drawing a given octant.
03195         // For example: 0x00111100 means we're drawing in octants 2-5
03196         drawoct = 0; 
03197 
03198         /*
03199         * Fixup angles
03200         */
03201         start %= 360;
03202         end %= 360;
03203         // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
03204         while (start < 0) start += 360;
03205         while (end < 0) end += 360;
03206         start %= 360;
03207         end %= 360;
03208 
03209         // now, we find which octants we're drawing in.
03210         startoct = start / 45;
03211         endoct = end / 45;
03212         oct = startoct - 1; // we increment as first step in loop
03213 
03214         // stopval_start, stopval_end; 
03215         // what values of cx to stop at.
03216         do {
03217                 oct = (oct + 1) % 8;
03218 
03219                 if (oct == startoct) {
03220                         // need to compute stopval_start for this octant.  Look at picture above if this is unclear
03221                         dstart = (double)start;
03222                         switch (oct) 
03223                         {
03224                         case 0:
03225                         case 3:
03226                                 temp = sin(dstart * M_PI / 180.);
03227                                 break;
03228                         case 1:
03229                         case 6:
03230                                 temp = cos(dstart * M_PI / 180.);
03231                                 break;
03232                         case 2:
03233                         case 5:
03234                                 temp = -cos(dstart * M_PI / 180.);
03235                                 break;
03236                         case 4:
03237                         case 7:
03238                                 temp = -sin(dstart * M_PI / 180.);
03239                                 break;
03240                         }
03241                         temp *= rad;
03242                         stopval_start = (int)temp; // always round down.
03243                         // This isn't arbitrary, but requires graph paper to explain well.
03244                         // The basic idea is that we're always changing drawoct after we draw, so we
03245                         // stop immediately after we render the last sensible pixel at x = ((int)temp).
03246 
03247                         // and whether to draw in this octant initially
03248                         if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
03249                         else             drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
03250                 }
03251                 if (oct == endoct) {
03252                         // need to compute stopval_end for this octant
03253                         dend = (double)end;
03254                         switch (oct)
03255                         {
03256                         case 0:
03257                         case 3:
03258                                 temp = sin(dend * M_PI / 180);
03259                                 break;
03260                         case 1:
03261                         case 6:
03262                                 temp = cos(dend * M_PI / 180);
03263                                 break;
03264                         case 2:
03265                         case 5:
03266                                 temp = -cos(dend * M_PI / 180);
03267                                 break;
03268                         case 4:
03269                         case 7:
03270                                 temp = -sin(dend * M_PI / 180);
03271                                 break;
03272                         }
03273                         temp *= rad;
03274                         stopval_end = (int)temp;
03275 
03276                         // and whether to draw in this octant initially
03277                         if (startoct == endoct) {
03278                                 // note:      we start drawing, stop, then start again in this case
03279                                 // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
03280                                 if (start > end) {
03281                                         // unfortunately, if we're in the same octant and need to draw over the whole circle, 
03282                                         // we need to set the rest to true, because the while loop will end at the bottom.
03283                                         drawoct = 255;
03284                                 } else {
03285                                         drawoct &= 255 - (1 << oct);
03286                                 }
03287                         } 
03288                         else if (oct % 2) drawoct &= 255 - (1 << oct);
03289                         else                      drawoct |= (1 << oct);
03290                 } else if (oct != startoct) { // already verified that it's != endoct
03291                         drawoct |= (1 << oct); // draw this entire segment
03292                 }
03293         } while (oct != endoct);
03294 
03295         // so now we have what octants to draw and when to draw them.  all that's left is the actual raster code.
03296 
03297         /* Lock surface */
03298         if (SDL_MUSTLOCK(dst)) {
03299                 if (SDL_LockSurface(dst) < 0) {
03300                         return (-1);
03301                 }
03302         }
03303 
03304         /*
03305         * Draw arc 
03306         */
03307         result = 0;
03308 
03309         /*
03310         * Alpha Check 
03311         */
03312         if ((color & 255) == 255) {
03313 
03314                 /*
03315                 * No Alpha - direct memory writes 
03316                 */
03317 
03318                 /*
03319                 * Setup color 
03320                 */
03321                 colorptr = (Uint8 *) & color;
03322                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
03323                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
03324                 } else {
03325                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
03326                 }
03327 
03328                 /*
03329                 * Draw 
03330                 */
03331                 do {
03332                         ypcy = y + cy;
03333                         ymcy = y - cy;
03334                         if (cx > 0) {
03335                                 xpcx = x + cx;
03336                                 xmcx = x - cx;
03337                                 // always check if we're drawing a certain octant before adding a pixel to that octant.
03338                                 if (drawoct & 4)  result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2]
03339                                 if (drawoct & 2)  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
03340                                 if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
03341                                 if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
03342                         } else {
03343                                 if (drawoct & 6)  result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1]
03344                                 if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64
03345                         }
03346 
03347                         xpcy = x + cy;
03348                         xmcy = x - cy;
03349                         if (cx > 0 && cx != cy) {
03350                                 ypcx = y + cx;
03351                                 ymcx = y - cx;
03352                                 if (drawoct & 8)   result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
03353                                 if (drawoct & 1)   result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
03354                                 if (drawoct & 16)  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
03355                                 if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
03356                         } else if (cx == 0) {
03357                                 if (drawoct & 24)  result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16
03358                                 if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128
03359                         }
03360 
03361                         /*
03362                         * Update whether we're drawing an octant
03363                         */
03364                         if (stopval_start == cx) {
03365                                 // works like an on-off switch because start & end may be in the same octant.
03366                                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);                
03367                                 else drawoct |= (1 << startoct);
03368                         }
03369                         if (stopval_end == cx) {
03370                                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
03371                                 else drawoct |= (1 << endoct);
03372                         }
03373 
03374                         /*
03375                         * Update pixels
03376                         */
03377                         if (df < 0) {
03378                                 df += d_e;
03379                                 d_e += 2;
03380                                 d_se += 2;
03381                         } else {
03382                                 df += d_se;
03383                                 d_e += 2;
03384                                 d_se += 4;
03385                                 cy--;
03386                         }
03387                         cx++;
03388                 } while (cx <= cy);
03389 
03390                 /*
03391                 * Unlock surface 
03392                 */
03393                 SDL_UnlockSurface(dst);
03394 
03395         } else {
03396 
03397                 /*
03398                 * Using Alpha - blended pixel blits 
03399                 */
03400 
03401                 do {
03402                         ypcy = y + cy;
03403                         ymcy = y - cy;
03404                         if (cx > 0) {
03405                                 xpcx = x + cx;
03406                                 xmcx = x - cx;
03407 
03408                                 // always check if we're drawing a certain octant before adding a pixel to that octant.
03409                                 if (drawoct & 4)  result |= pixelColorNolock(dst, xmcx, ypcy, color);
03410                                 if (drawoct & 2)  result |= pixelColorNolock(dst, xpcx, ypcy, color);
03411                                 if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
03412                                 if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
03413                         } else {
03414                                 if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
03415                                 if (drawoct & 6)  result |= pixelColorNolock(dst, x, ypcy, color);
03416                         }
03417 
03418                         xpcy = x + cy;
03419                         xmcy = x - cy;
03420                         if (cx > 0 && cx != cy) {
03421                                 ypcx = y + cx;
03422                                 ymcx = y - cx;
03423                                 if (drawoct & 8)   result |= pixelColorNolock(dst, xmcy, ypcx, color);
03424                                 if (drawoct & 1)   result |= pixelColorNolock(dst, xpcy, ypcx, color);
03425                                 if (drawoct & 16)  result |= pixelColorNolock(dst, xmcy, ymcx, color);
03426                                 if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
03427                         } else if (cx == 0) {
03428                                 if (drawoct & 24)  result |= pixelColorNolock(dst, xmcy, y, color);
03429                                 if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
03430                         }
03431 
03432                         /*
03433                         * Update whether we're drawing an octant
03434                         */
03435                         if (stopval_start == cx) {
03436                                 // works like an on-off switch.  
03437                                 // This is just in case start & end are in the same octant.
03438                                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);                
03439                                 else                                               drawoct |= (1 << startoct);
03440                         }
03441                         if (stopval_end == cx) {
03442                                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
03443                                 else                                             drawoct |= (1 << endoct);
03444                         }
03445 
03446                         /*
03447                         * Update pixels
03448                         */
03449                         if (df < 0) {
03450                                 df += d_e;
03451                                 d_e += 2;
03452                                 d_se += 2;
03453                         } else {
03454                                 df += d_se;
03455                                 d_e += 2;
03456                                 d_se += 4;
03457                                 cy--;
03458                         }
03459                         cx++;
03460                 } while (cx <= cy);
03461 
03462         }                               /* Alpha check */
03463 
03464         /* Unlock surface */
03465         if (SDL_MUSTLOCK(dst)) {
03466                 SDL_UnlockSurface(dst);
03467         }
03468 
03469         return (result);
03470 }
03471 
03488 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03489 {
03490         /*
03491         * Draw 
03492         */
03493         return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03494 }
03495 
03496 /* ----- AA Circle */
03497 
03498 
03512 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
03513 {
03514         return (aaellipseColor(dst, x, y, rad, rad, color));
03515 }
03516 
03531 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03532 {
03533         /*
03534         * Draw 
03535         */
03536         return (aaellipseColor
03537                 (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03538 }
03539 
03540 /* ----- Filled Circle */
03541 
03556 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
03557 {
03558         Sint16 left, right, top, bottom;
03559         int result;
03560         Sint16 x1, y1, x2, y2;
03561         Sint16 cx = 0;
03562         Sint16 cy = rad;
03563         Sint16 ocx = (Sint16) 0xffff;
03564         Sint16 ocy = (Sint16) 0xffff;
03565         Sint16 df = 1 - rad;
03566         Sint16 d_e = 3;
03567         Sint16 d_se = -2 * rad + 5;
03568         Sint16 xpcx, xmcx, xpcy, xmcy;
03569         Sint16 ypcy, ymcy, ypcx, ymcx;
03570 
03571         /*
03572         * Check visibility of clipping rectangle
03573         */
03574         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03575                 return(0);
03576         }
03577 
03578         /*
03579         * Sanity check radius 
03580         */
03581         if (rad < 0) {
03582                 return (-1);
03583         }
03584 
03585         /*
03586         * Special case for rad=0 - draw a point 
03587         */
03588         if (rad == 0) {
03589                 return (pixelColor(dst, x, y, color));
03590         }
03591 
03592         /*
03593         * Get circle and clipping boundary and 
03594         * test if bounding box of circle is visible 
03595         */
03596         x2 = x + rad;
03597         left = dst->clip_rect.x;
03598         if (x2<left) {
03599                 return(0);
03600         } 
03601         x1 = x - rad;
03602         right = dst->clip_rect.x + dst->clip_rect.w - 1;
03603         if (x1>right) {
03604                 return(0);
03605         } 
03606         y2 = y + rad;
03607         top = dst->clip_rect.y;
03608         if (y2<top) {
03609                 return(0);
03610         } 
03611         y1 = y - rad;
03612         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03613         if (y1>bottom) {
03614                 return(0);
03615         } 
03616 
03617         /*
03618         * Draw 
03619         */
03620         result = 0;
03621         do {
03622                 xpcx = x + cx;
03623                 xmcx = x - cx;
03624                 xpcy = x + cy;
03625                 xmcy = x - cy;
03626                 if (ocy != cy) {
03627                         if (cy > 0) {
03628                                 ypcy = y + cy;
03629                                 ymcy = y - cy;
03630                                 result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
03631                                 result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
03632                         } else {
03633                                 result |= hlineColor(dst, xmcx, xpcx, y, color);
03634                         }
03635                         ocy = cy;
03636                 }
03637                 if (ocx != cx) {
03638                         if (cx != cy) {
03639                                 if (cx > 0) {
03640                                         ypcx = y + cx;
03641                                         ymcx = y - cx;
03642                                         result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
03643                                         result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
03644                                 } else {
03645                                         result |= hlineColor(dst, xmcy, xpcy, y, color);
03646                                 }
03647                         }
03648                         ocx = cx;
03649                 }
03650                 /*
03651                 * Update 
03652                 */
03653                 if (df < 0) {
03654                         df += d_e;
03655                         d_e += 2;
03656                         d_se += 2;
03657                 } else {
03658                         df += d_se;
03659                         d_e += 2;
03660                         d_se += 4;
03661                         cy--;
03662                 }
03663                 cx++;
03664         } while (cx <= cy);
03665 
03666         return (result);
03667 }
03668 
03683 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
03684 {
03685         /*
03686         * Draw 
03687         */
03688         return (filledCircleColor
03689                 (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
03690 }
03691 
03692 /* ----- Ellipse */
03693 
03709 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
03710 {
03711         Sint16 left, right, top, bottom;
03712         int result;
03713         Sint16 x1, y1, x2, y2;
03714         int ix, iy;
03715         int h, i, j, k;
03716         int oh, oi, oj, ok;
03717         int xmh, xph, ypk, ymk;
03718         int xmi, xpi, ymj, ypj;
03719         int xmj, xpj, ymi, ypi;
03720         int xmk, xpk, ymh, yph;
03721         Uint8 *colorptr;
03722 
03723         /*
03724         * Check visibility of clipping rectangle
03725         */
03726         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
03727                 return(0);
03728         }
03729 
03730         /*
03731         * Sanity check radii 
03732         */
03733         if ((rx < 0) || (ry < 0)) {
03734                 return (-1);
03735         }
03736 
03737         /*
03738         * Special case for rx=0 - draw a vline 
03739         */
03740         if (rx == 0) {
03741                 return (vlineColor(dst, x, y - ry, y + ry, color));
03742         }
03743         /*
03744         * Special case for ry=0 - draw a hline 
03745         */
03746         if (ry == 0) {
03747                 return (hlineColor(dst, x - rx, x + rx, y, color));
03748         }
03749 
03750         /*
03751         * Get circle and clipping boundary and 
03752         * test if bounding box of circle is visible 
03753         */
03754         x2 = x + rx;
03755         left = dst->clip_rect.x;
03756         if (x2<left) {
03757                 return(0);
03758         } 
03759         x1 = x - rx;
03760         right = dst->clip_rect.x + dst->clip_rect.w - 1;
03761         if (x1>right) {
03762                 return(0);
03763         } 
03764         y2 = y + ry;
03765         top = dst->clip_rect.y;
03766         if (y2<top) {
03767                 return(0);
03768         } 
03769         y1 = y - ry;
03770         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
03771         if (y1>bottom) {
03772                 return(0);
03773         } 
03774 
03775         /*
03776         * Init vars 
03777         */
03778         oh = oi = oj = ok = 0xFFFF;
03779 
03780         /*
03781         * Draw 
03782         */
03783         result = 0;
03784 
03785         /* Lock surface */
03786         if (SDL_MUSTLOCK(dst)) {
03787                 if (SDL_LockSurface(dst) < 0) {
03788                         return (-1);
03789                 }
03790         }
03791 
03792         /*
03793         * Check alpha 
03794         */
03795         if ((color & 255) == 255) {
03796 
03797                 /*
03798                 * No Alpha - direct memory writes 
03799                 */
03800 
03801                 /*
03802                 * Setup color 
03803                 */
03804                 colorptr = (Uint8 *) & color;
03805                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
03806                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
03807                 } else {
03808                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
03809                 }
03810 
03811 
03812                 if (rx > ry) {
03813                         ix = 0;
03814                         iy = rx * 64;
03815 
03816                         do {
03817                                 h = (ix + 32) >> 6;
03818                                 i = (iy + 32) >> 6;
03819                                 j = (h * ry) / rx;
03820                                 k = (i * ry) / rx;
03821 
03822                                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
03823                                         xph = x + h;
03824                                         xmh = x - h;
03825                                         if (k > 0) {
03826                                                 ypk = y + k;
03827                                                 ymk = y - k;
03828                                                 result |= fastPixelColorNolock(dst, xmh, ypk, color);
03829                                                 result |= fastPixelColorNolock(dst, xph, ypk, color);
03830                                                 result |= fastPixelColorNolock(dst, xmh, ymk, color);
03831                                                 result |= fastPixelColorNolock(dst, xph, ymk, color);
03832                                         } else {
03833                                                 result |= fastPixelColorNolock(dst, xmh, y, color);
03834                                                 result |= fastPixelColorNolock(dst, xph, y, color);
03835                                         }
03836                                         ok = k;
03837                                         xpi = x + i;
03838                                         xmi = x - i;
03839                                         if (j > 0) {
03840                                                 ypj = y + j;
03841                                                 ymj = y - j;
03842                                                 result |= fastPixelColorNolock(dst, xmi, ypj, color);
03843                                                 result |= fastPixelColorNolock(dst, xpi, ypj, color);
03844                                                 result |= fastPixelColorNolock(dst, xmi, ymj, color);
03845                                                 result |= fastPixelColorNolock(dst, xpi, ymj, color);
03846                                         } else {
03847                                                 result |= fastPixelColorNolock(dst, xmi, y, color);
03848                                                 result |= fastPixelColorNolock(dst, xpi, y, color);
03849                                         }
03850                                         oj = j;
03851                                 }
03852 
03853                                 ix = ix + iy / rx;
03854                                 iy = iy - ix / rx;
03855 
03856                         } while (i > h);
03857                 } else {
03858                         ix = 0;
03859                         iy = ry * 64;
03860 
03861                         do {
03862                                 h = (ix + 32) >> 6;
03863                                 i = (iy + 32) >> 6;
03864                                 j = (h * rx) / ry;
03865                                 k = (i * rx) / ry;
03866 
03867                                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
03868                                         xmj = x - j;
03869                                         xpj = x + j;
03870                                         if (i > 0) {
03871                                                 ypi = y + i;
03872                                                 ymi = y - i;
03873                                                 result |= fastPixelColorNolock(dst, xmj, ypi, color);
03874                                                 result |= fastPixelColorNolock(dst, xpj, ypi, color);
03875                                                 result |= fastPixelColorNolock(dst, xmj, ymi, color);
03876                                                 result |= fastPixelColorNolock(dst, xpj, ymi, color);
03877                                         } else {
03878                                                 result |= fastPixelColorNolock(dst, xmj, y, color);
03879                                                 result |= fastPixelColorNolock(dst, xpj, y, color);
03880                                         }
03881                                         oi = i;
03882                                         xmk = x - k;
03883                                         xpk = x + k;
03884                                         if (h > 0) {
03885                                                 yph = y + h;
03886                                                 ymh = y - h;
03887                                                 result |= fastPixelColorNolock(dst, xmk, yph, color);
03888                                                 result |= fastPixelColorNolock(dst, xpk, yph, color);
03889                                                 result |= fastPixelColorNolock(dst, xmk, ymh, color);
03890                                                 result |= fastPixelColorNolock(dst, xpk, ymh, color);
03891                                         } else {
03892                                                 result |= fastPixelColorNolock(dst, xmk, y, color);
03893                                                 result |= fastPixelColorNolock(dst, xpk, y, color);
03894                                         }
03895                                         oh = h;
03896                                 }
03897 
03898                                 ix = ix + iy / ry;
03899                                 iy = iy - ix / ry;
03900 
03901                         } while (i > h);
03902                 }
03903 
03904         } else {
03905 
03906                 if (rx > ry) {
03907                         ix = 0;
03908                         iy = rx * 64;
03909 
03910                         do {
03911                                 h = (ix + 32) >> 6;
03912                                 i = (iy + 32) >> 6;
03913                                 j = (h * ry) / rx;
03914                                 k = (i * ry) / rx;
03915 
03916                                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
03917                                         xph = x + h;
03918                                         xmh = x - h;
03919                                         if (k > 0) {
03920                                                 ypk = y + k;
03921                                                 ymk = y - k;
03922                                                 result |= pixelColorNolock (dst, xmh, ypk, color);
03923                                                 result |= pixelColorNolock (dst, xph, ypk, color);
03924                                                 result |= pixelColorNolock (dst, xmh, ymk, color);
03925                                                 result |= pixelColorNolock (dst, xph, ymk, color);
03926                                         } else {
03927                                                 result |= pixelColorNolock (dst, xmh, y, color);
03928                                                 result |= pixelColorNolock (dst, xph, y, color);
03929                                         }
03930                                         ok = k;
03931                                         xpi = x + i;
03932                                         xmi = x - i;
03933                                         if (j > 0) {
03934                                                 ypj = y + j;
03935                                                 ymj = y - j;
03936                                                 result |= pixelColorNolock (dst, xmi, ypj, color);
03937                                                 result |= pixelColorNolock (dst, xpi, ypj, color);
03938                                                 result |= pixelColorNolock (dst, xmi, ymj, color);
03939                                                 result |= pixelColor(dst, xpi, ymj, color);
03940                                         } else {
03941                                                 result |= pixelColorNolock (dst, xmi, y, color);
03942                                                 result |= pixelColorNolock (dst, xpi, y, color);
03943                                         }
03944                                         oj = j;
03945                                 }
03946 
03947                                 ix = ix + iy / rx;
03948                                 iy = iy - ix / rx;
03949 
03950                         } while (i > h);
03951                 } else {
03952                         ix = 0;
03953                         iy = ry * 64;
03954 
03955                         do {
03956                                 h = (ix + 32) >> 6;
03957                                 i = (iy + 32) >> 6;
03958                                 j = (h * rx) / ry;
03959                                 k = (i * rx) / ry;
03960 
03961                                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
03962                                         xmj = x - j;
03963                                         xpj = x + j;
03964                                         if (i > 0) {
03965                                                 ypi = y + i;
03966                                                 ymi = y - i;
03967                                                 result |= pixelColorNolock (dst, xmj, ypi, color);
03968                                                 result |= pixelColorNolock (dst, xpj, ypi, color);
03969                                                 result |= pixelColorNolock (dst, xmj, ymi, color);
03970                                                 result |= pixelColorNolock (dst, xpj, ymi, color);
03971                                         } else {
03972                                                 result |= pixelColorNolock (dst, xmj, y, color);
03973                                                 result |= pixelColorNolock (dst, xpj, y, color);
03974                                         }
03975                                         oi = i;
03976                                         xmk = x - k;
03977                                         xpk = x + k;
03978                                         if (h > 0) {
03979                                                 yph = y + h;
03980                                                 ymh = y - h;
03981                                                 result |= pixelColorNolock (dst, xmk, yph, color);
03982                                                 result |= pixelColorNolock (dst, xpk, yph, color);
03983                                                 result |= pixelColorNolock (dst, xmk, ymh, color);
03984                                                 result |= pixelColorNolock (dst, xpk, ymh, color);
03985                                         } else {
03986                                                 result |= pixelColorNolock (dst, xmk, y, color);
03987                                                 result |= pixelColorNolock (dst, xpk, y, color);
03988                                         }
03989                                         oh = h;
03990                                 }
03991 
03992                                 ix = ix + iy / ry;
03993                                 iy = iy - ix / ry;
03994 
03995                         } while (i > h);
03996                 }
03997 
03998         }                               /* Alpha check */
03999 
04000         /* Unlock surface */
04001         if (SDL_MUSTLOCK(dst)) {
04002                 SDL_UnlockSurface(dst);
04003         }
04004 
04005         return (result);
04006 }
04007 
04023 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04024 {
04025         /*
04026         * Draw 
04027         */
04028         return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04029 }
04030 
04031 /* ----- AA Ellipse */
04032 
04033 /* Windows targets do not have lrint, so provide a local inline version */
04034 #if defined(_MSC_VER)
04035 /* Detect 64bit and use intrinsic version */
04036 #ifdef _M_X64
04037 #include <emmintrin.h>
04038 static __inline long 
04039         lrint(float f) 
04040 {
04041         return _mm_cvtss_si32(_mm_load_ss(&f));
04042 }
04043 #elif defined(_M_IX86)
04044 __inline long int
04045         lrint (double flt)
04046 {       
04047         int intgr;
04048         _asm
04049         {
04050                 fld flt
04051                         fistp intgr
04052         };
04053         return intgr;
04054 }
04055 #elif defined(_M_ARM)
04056 #include <armintr.h>
04057 #pragma warning(push)
04058 #pragma warning(disable: 4716)
04059 __declspec(naked) long int
04060         lrint (double flt)
04061 {
04062         __emit(0xEC410B10); // fmdrr  d0, r0, r1
04063         __emit(0xEEBD0B40); // ftosid s0, d0
04064         __emit(0xEE100A10); // fmrs   r0, s0
04065         __emit(0xE12FFF1E); // bx     lr
04066 }
04067 #pragma warning(pop)
04068 #else
04069 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
04070 #endif
04071 #endif
04072 
04088 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
04089 {
04090         Sint16 left, right, top, bottom;
04091         Sint16 x1,y1,x2,y2;
04092         int i;
04093         int a2, b2, ds, dt, dxt, t, s, d;
04094         Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
04095         float cp;
04096         double sab;
04097         Uint8 weight, iweight;
04098         int result;
04099 
04100         /*
04101         * Check visibility of clipping rectangle
04102         */
04103         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04104                 return(0);
04105         }
04106 
04107         /*
04108         * Sanity check radii 
04109         */
04110         if ((rx < 0) || (ry < 0)) {
04111                 return (-1);
04112         }
04113 
04114         /*
04115         * Special case for rx=0 - draw a vline 
04116         */
04117         if (rx == 0) {
04118                 return (vlineColor(dst, x, y - ry, y + ry, color));
04119         }
04120         /*
04121         * Special case for ry=0 - draw an hline 
04122         */
04123         if (ry == 0) {
04124                 return (hlineColor(dst, x - rx, x + rx, y, color));
04125         }
04126 
04127         /*
04128         * Get circle and clipping boundary and 
04129         * test if bounding box of circle is visible 
04130         */
04131         x2 = x + rx;
04132         left = dst->clip_rect.x;
04133         if (x2<left) {
04134                 return(0);
04135         } 
04136         x1 = x - rx;
04137         right = dst->clip_rect.x + dst->clip_rect.w - 1;
04138         if (x1>right) {
04139                 return(0);
04140         } 
04141         y2 = y + ry;
04142         top = dst->clip_rect.y;
04143         if (y2<top) {
04144                 return(0);
04145         } 
04146         y1 = y - ry;
04147         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04148         if (y1>bottom) {
04149                 return(0);
04150         } 
04151 
04152         /* Variable setup */
04153         a2 = rx * rx;
04154         b2 = ry * ry;
04155 
04156         ds = 2 * a2;
04157         dt = 2 * b2;
04158 
04159         xc2 = 2 * x;
04160         yc2 = 2 * y;
04161 
04162         sab = sqrt((double)(a2 + b2));
04163         od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
04164         dxt = (Sint16)lrint((double)a2 / sab) + od;
04165 
04166         t = 0;
04167         s = -2 * a2 * ry;
04168         d = 0;
04169 
04170         xp = x;
04171         yp = y - ry;
04172 
04173         /* Lock surface */
04174         if (SDL_MUSTLOCK(dst)) {
04175                 if (SDL_LockSurface(dst) < 0) {
04176                         return (-1);
04177                 }
04178         }
04179 
04180         /* Draw */
04181         result = 0;
04182 
04183         /* "End points" */
04184         result |= pixelColorNolock(dst, xp, yp, color);
04185         result |= pixelColorNolock(dst, xc2 - xp, yp, color);
04186         result |= pixelColorNolock(dst, xp, yc2 - yp, color);
04187         result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
04188 
04189         for (i = 1; i <= dxt; i++) {
04190                 xp--;
04191                 d += t - b2;
04192 
04193                 if (d >= 0)
04194                         ys = yp - 1;
04195                 else if ((d - s - a2) > 0) {
04196                         if ((2 * d - s - a2) >= 0)
04197                                 ys = yp + 1;
04198                         else {
04199                                 ys = yp;
04200                                 yp++;
04201                                 d -= s + a2;
04202                                 s += ds;
04203                         }
04204                 } else {
04205                         yp++;
04206                         ys = yp + 1;
04207                         d -= s + a2;
04208                         s += ds;
04209                 }
04210 
04211                 t -= dt;
04212 
04213                 /* Calculate alpha */
04214                 if (s != 0) {
04215                         cp = (float) abs(d) / (float) abs(s);
04216                         if (cp > 1.0) {
04217                                 cp = 1.0;
04218                         }
04219                 } else {
04220                         cp = 1.0;
04221                 }
04222 
04223                 /* Calculate weights */
04224                 weight = (Uint8) (cp * 255);
04225                 iweight = 255 - weight;
04226 
04227                 /* Upper half */
04228                 xx = xc2 - xp;
04229                 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
04230                 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
04231 
04232                 result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
04233                 result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
04234 
04235                 /* Lower half */
04236                 yy = yc2 - yp;
04237                 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
04238                 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
04239 
04240                 yy = yc2 - ys;
04241                 result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
04242                 result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
04243         }
04244 
04245         /* Replaces original approximation code dyt = abs(yp - yc); */
04246         dyt = (Sint16)lrint((double)b2 / sab ) + od;    
04247 
04248         for (i = 1; i <= dyt; i++) {
04249                 yp++;
04250                 d -= s + a2;
04251 
04252                 if (d <= 0)
04253                         xs = xp + 1;
04254                 else if ((d + t - b2) < 0) {
04255                         if ((2 * d + t - b2) <= 0)
04256                                 xs = xp - 1;
04257                         else {
04258                                 xs = xp;
04259                                 xp--;
04260                                 d += t - b2;
04261                                 t -= dt;
04262                         }
04263                 } else {
04264                         xp--;
04265                         xs = xp - 1;
04266                         d += t - b2;
04267                         t -= dt;
04268                 }
04269 
04270                 s += ds;
04271 
04272                 /* Calculate alpha */
04273                 if (t != 0) {
04274                         cp = (float) abs(d) / (float) abs(t);
04275                         if (cp > 1.0) {
04276                                 cp = 1.0;
04277                         }
04278                 } else {
04279                         cp = 1.0;
04280                 }
04281 
04282                 /* Calculate weight */
04283                 weight = (Uint8) (cp * 255);
04284                 iweight = 255 - weight;
04285 
04286                 /* Left half */
04287                 xx = xc2 - xp;
04288                 yy = yc2 - yp;
04289                 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
04290                 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
04291 
04292                 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
04293                 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
04294 
04295                 /* Right half */
04296                 xx = xc2 - xs;
04297                 result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
04298                 result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
04299 
04300                 result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
04301                 result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
04302 
04303         }
04304 
04305         /* Unlock surface */
04306         if (SDL_MUSTLOCK(dst)) {
04307                 SDL_UnlockSurface(dst);
04308         }
04309 
04310         return (result);
04311 }
04312 
04328 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04329 {
04330         /*
04331         * Draw 
04332         */
04333         return (aaellipseColor
04334                 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04335 }
04336 
04337 /* ---- Filled Ellipse */
04338 
04339 /* Note: */
04340 /* Based on algorithm from sge library with multiple-hline draw removal */
04341 /* and other speedup changes. */
04342 
04358 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
04359 {
04360         Sint16 left, right, top, bottom;
04361         int result;
04362         Sint16 x1, y1, x2, y2;
04363         int ix, iy;
04364         int h, i, j, k;
04365         int oh, oi, oj, ok;
04366         int xmh, xph;
04367         int xmi, xpi;
04368         int xmj, xpj;
04369         int xmk, xpk;
04370 
04371         /*
04372         * Check visibility of clipping rectangle
04373         */
04374         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04375                 return(0);
04376         }
04377 
04378         /*
04379         * Sanity check radii 
04380         */
04381         if ((rx < 0) || (ry < 0)) {
04382                 return (-1);
04383         }
04384 
04385         /*
04386         * Special case for rx=0 - draw a vline 
04387         */
04388         if (rx == 0) {
04389                 return (vlineColor(dst, x, y - ry, y + ry, color));
04390         }
04391         /*
04392         * Special case for ry=0 - draw a hline 
04393         */
04394         if (ry == 0) {
04395                 return (hlineColor(dst, x - rx, x + rx, y, color));
04396         }
04397 
04398         /*
04399         * Get circle and clipping boundary and 
04400         * test if bounding box of circle is visible 
04401         */
04402         x2 = x + rx;
04403         left = dst->clip_rect.x;
04404         if (x2<left) {
04405                 return(0);
04406         } 
04407         x1 = x - rx;
04408         right = dst->clip_rect.x + dst->clip_rect.w - 1;
04409         if (x1>right) {
04410                 return(0);
04411         } 
04412         y2 = y + ry;
04413         top = dst->clip_rect.y;
04414         if (y2<top) {
04415                 return(0);
04416         } 
04417         y1 = y - ry;
04418         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04419         if (y1>bottom) {
04420                 return(0);
04421         } 
04422 
04423         /*
04424         * Init vars 
04425         */
04426         oh = oi = oj = ok = 0xFFFF;
04427 
04428         /*
04429         * Draw 
04430         */
04431         result = 0;
04432         if (rx > ry) {
04433                 ix = 0;
04434                 iy = rx * 64;
04435 
04436                 do {
04437                         h = (ix + 32) >> 6;
04438                         i = (iy + 32) >> 6;
04439                         j = (h * ry) / rx;
04440                         k = (i * ry) / rx;
04441 
04442                         if ((ok != k) && (oj != k)) {
04443                                 xph = x + h;
04444                                 xmh = x - h;
04445                                 if (k > 0) {
04446                                         result |= hlineColor(dst, xmh, xph, y + k, color);
04447                                         result |= hlineColor(dst, xmh, xph, y - k, color);
04448                                 } else {
04449                                         result |= hlineColor(dst, xmh, xph, y, color);
04450                                 }
04451                                 ok = k;
04452                         }
04453                         if ((oj != j) && (ok != j) && (k != j)) {
04454                                 xmi = x - i;
04455                                 xpi = x + i;
04456                                 if (j > 0) {
04457                                         result |= hlineColor(dst, xmi, xpi, y + j, color);
04458                                         result |= hlineColor(dst, xmi, xpi, y - j, color);
04459                                 } else {
04460                                         result |= hlineColor(dst, xmi, xpi, y, color);
04461                                 }
04462                                 oj = j;
04463                         }
04464 
04465                         ix = ix + iy / rx;
04466                         iy = iy - ix / rx;
04467 
04468                 } while (i > h);
04469         } else {
04470                 ix = 0;
04471                 iy = ry * 64;
04472 
04473                 do {
04474                         h = (ix + 32) >> 6;
04475                         i = (iy + 32) >> 6;
04476                         j = (h * rx) / ry;
04477                         k = (i * rx) / ry;
04478 
04479                         if ((oi != i) && (oh != i)) {
04480                                 xmj = x - j;
04481                                 xpj = x + j;
04482                                 if (i > 0) {
04483                                         result |= hlineColor(dst, xmj, xpj, y + i, color);
04484                                         result |= hlineColor(dst, xmj, xpj, y - i, color);
04485                                 } else {
04486                                         result |= hlineColor(dst, xmj, xpj, y, color);
04487                                 }
04488                                 oi = i;
04489                         }
04490                         if ((oh != h) && (oi != h) && (i != h)) {
04491                                 xmk = x - k;
04492                                 xpk = x + k;
04493                                 if (h > 0) {
04494                                         result |= hlineColor(dst, xmk, xpk, y + h, color);
04495                                         result |= hlineColor(dst, xmk, xpk, y - h, color);
04496                                 } else {
04497                                         result |= hlineColor(dst, xmk, xpk, y, color);
04498                                 }
04499                                 oh = h;
04500                         }
04501 
04502                         ix = ix + iy / ry;
04503                         iy = iy - ix / ry;
04504 
04505                 } while (i > h);
04506         }
04507 
04508         return (result);
04509 }
04510 
04526 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04527 {
04528         /*
04529         * Draw 
04530         */
04531         return (filledEllipseColor
04532                 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
04533 }
04534 
04535 /* ----- pie */
04536 
04553 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
04554 {
04555         Sint16 left, right, top, bottom;
04556         Sint16 x1, y1, x2, y2;
04557         int result;
04558         double angle, start_angle, end_angle;
04559         double deltaAngle;
04560         double dr;
04561         int numpoints, i;
04562         Sint16 *vx, *vy;
04563 
04564         /*
04565         * Check visibility of clipping rectangle
04566         */
04567         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04568                 return(0);
04569         }
04570 
04571         /*
04572         * Sanity check radii 
04573         */
04574         if (rad < 0) {
04575                 return (-1);
04576         }
04577 
04578         /*
04579         * Fixup angles
04580         */
04581         start = start % 360;
04582         end = end % 360;
04583 
04584         /*
04585         * Special case for rad=0 - draw a point 
04586         */
04587         if (rad == 0) {
04588                 return (pixelColor(dst, x, y, color));
04589         }
04590 
04591         /*
04592         * Clip against circle, not pie (not 100% optimal).
04593         * Get pie's circle and clipping boundary and 
04594         * test if bounding box of circle is visible
04595         */
04596         x2 = x + rad;
04597         left = dst->clip_rect.x;
04598         if (x2<left) {
04599                 return(0);
04600         } 
04601         x1 = x - rad;
04602         right = dst->clip_rect.x + dst->clip_rect.w - 1;
04603         if (x1>right) {
04604                 return(0);
04605         } 
04606         y2 = y + rad;
04607         top = dst->clip_rect.y;
04608         if (y2<top) {
04609                 return(0);
04610         } 
04611         y1 = y - rad;
04612         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
04613         if (y1>bottom) {
04614                 return(0);
04615         } 
04616 
04617         /*
04618         * Variable setup 
04619         */
04620         dr = (double) rad;
04621         deltaAngle = 3.0 / dr;
04622         start_angle = (double) start *(2.0 * M_PI / 360.0);
04623         end_angle = (double) end *(2.0 * M_PI / 360.0);
04624         if (start > end) {
04625                 end_angle += (2.0 * M_PI);
04626         }
04627 
04628         /* We will always have at least 2 points */
04629         numpoints = 2;
04630 
04631         /* Count points (rather than calculating it) */
04632         angle = start_angle;
04633         while (angle < end_angle) {
04634                 angle += deltaAngle;
04635                 numpoints++;
04636         }
04637 
04638         /* Allocate combined vertex array */
04639         vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
04640         if (vx == NULL) {
04641                 return (-1);
04642         }
04643 
04644         /* Update point to start of vy */
04645         vy += numpoints;
04646 
04647         /* Center */
04648         vx[0] = x;
04649         vy[0] = y;
04650 
04651         /* First vertex */
04652         angle = start_angle;
04653         vx[1] = x + (int) (dr * cos(angle));
04654         vy[1] = y + (int) (dr * sin(angle));
04655 
04656         if (numpoints<3)
04657         {
04658                 result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
04659         }
04660         else
04661         {
04662                 /* Calculate other vertices */
04663                 i = 2;
04664                 angle = start_angle;
04665                 while (angle < end_angle) {
04666                         angle += deltaAngle;
04667                         if (angle>end_angle)
04668                         {
04669                                 angle = end_angle;
04670                         }
04671                         vx[i] = x + (int) (dr * cos(angle));
04672                         vy[i] = y + (int) (dr * sin(angle));
04673                         i++;
04674                 }
04675 
04676                 /* Draw */
04677                 if (filled) {
04678                         result = filledPolygonColor(dst, vx, vy, numpoints, color);
04679                 } else {
04680                         result = polygonColor(dst, vx, vy, numpoints, color);
04681                 }
04682         }
04683 
04684         /* Free combined vertex array */
04685         free(vx);
04686 
04687         return (result);
04688 }
04689 
04703 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 
04704         Sint16 start, Sint16 end, Uint32 color) 
04705 {
04706         return (_pieColor(dst, x, y, rad, start, end, color, 0));
04707 
04708 }
04709 
04726 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
04727         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04728 {
04729         return (_pieColor(dst, x, y, rad, start, end,
04730                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
04731 
04732 }
04733 
04747 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
04748 {
04749         return (_pieColor(dst, x, y, rad, start, end, color, 1));
04750 }
04751 
04768 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
04769         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04770 {
04771         return (_pieColor(dst, x, y, rad, start, end,
04772                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
04773 }
04774 
04775 /* ------ Trigon */
04776 
04793 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04794 {
04795         Sint16 vx[3]; 
04796         Sint16 vy[3];
04797 
04798         vx[0]=x1;
04799         vx[1]=x2;
04800         vx[2]=x3;
04801         vy[0]=y1;
04802         vy[1]=y2;
04803         vy[2]=y3;
04804 
04805         return(polygonColor(dst,vx,vy,3,color));
04806 }
04807 
04825 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04826         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04827 {
04828         Sint16 vx[3]; 
04829         Sint16 vy[3];
04830 
04831         vx[0]=x1;
04832         vx[1]=x2;
04833         vx[2]=x3;
04834         vy[0]=y1;
04835         vy[1]=y2;
04836         vy[2]=y3;
04837 
04838         return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
04839 }                                
04840 
04841 /* ------ AA-Trigon */
04842 
04859 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04860 {
04861         Sint16 vx[3]; 
04862         Sint16 vy[3];
04863 
04864         vx[0]=x1;
04865         vx[1]=x2;
04866         vx[2]=x3;
04867         vy[0]=y1;
04868         vy[1]=y2;
04869         vy[2]=y3;
04870 
04871         return(aapolygonColor(dst,vx,vy,3,color));
04872 }
04873 
04891 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04892         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04893 {
04894         Sint16 vx[3]; 
04895         Sint16 vy[3];
04896 
04897         vx[0]=x1;
04898         vx[1]=x2;
04899         vx[2]=x3;
04900         vy[0]=y1;
04901         vy[1]=y2;
04902         vy[2]=y3;
04903 
04904         return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
04905 }                                  
04906 
04907 /* ------ Filled Trigon */
04908 
04925 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
04926 {
04927         Sint16 vx[3]; 
04928         Sint16 vy[3];
04929 
04930         vx[0]=x1;
04931         vx[1]=x2;
04932         vx[2]=x3;
04933         vy[0]=y1;
04934         vy[1]=y2;
04935         vy[2]=y3;
04936 
04937         return(filledPolygonColor(dst,vx,vy,3,color));
04938 }
04939 
04959 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
04960         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
04961 {
04962         Sint16 vx[3]; 
04963         Sint16 vy[3];
04964 
04965         vx[0]=x1;
04966         vx[1]=x2;
04967         vx[2]=x3;
04968         vy[0]=y1;
04969         vy[1]=y2;
04970         vy[2]=y3;
04971 
04972         return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
04973 }
04974 
04975 /* ---- Polygon */
04976 
04988 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
04989 {
04990         int result;
04991         int i;
04992         const Sint16 *x1, *y1, *x2, *y2;
04993 
04994         /*
04995         * Check visibility of clipping rectangle
04996         */
04997         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
04998                 return(0);
04999         }
05000 
05001         /*
05002         * Vertex array NULL check 
05003         */
05004         if (vx == NULL) {
05005                 return (-1);
05006         }
05007         if (vy == NULL) {
05008                 return (-1);
05009         }
05010 
05011         /*
05012         * Sanity check 
05013         */
05014         if (n < 3) {
05015                 return (-1);
05016         }
05017 
05018         /*
05019         * Pointer setup 
05020         */
05021         x1 = x2 = vx;
05022         y1 = y2 = vy;
05023         x2++;
05024         y2++;
05025 
05026         /*
05027         * Draw 
05028         */
05029         result = 0;
05030         for (i = 1; i < n; i++) {
05031                 result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
05032                 x1 = x2;
05033                 y1 = y2;
05034                 x2++;
05035                 y2++;
05036         }
05037         result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
05038 
05039         return (result);
05040 }
05041 
05056 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05057 {
05058         /*
05059         * Draw 
05060         */
05061         return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
05062 }
05063 
05064 /* ---- AA-Polygon */
05065 
05077 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
05078 {
05079         int result;
05080         int i;
05081         const Sint16 *x1, *y1, *x2, *y2;
05082 
05083         /*
05084         * Check visibility of clipping rectangle
05085         */
05086         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05087                 return(0);
05088         }
05089 
05090         /*
05091         * Vertex array NULL check 
05092         */
05093         if (vx == NULL) {
05094                 return (-1);
05095         }
05096         if (vy == NULL) {
05097                 return (-1);
05098         }
05099 
05100         /*
05101         * Sanity check 
05102         */
05103         if (n < 3) {
05104                 return (-1);
05105         }
05106 
05107         /*
05108         * Pointer setup 
05109         */
05110         x1 = x2 = vx;
05111         y1 = y2 = vy;
05112         x2++;
05113         y2++;
05114 
05115         /*
05116         * Draw 
05117         */
05118         result = 0;
05119         for (i = 1; i < n; i++) {
05120                 result |= _aalineColor(dst, *x1, *y1, *x2, *y2, color, 0);
05121                 x1 = x2;
05122                 y1 = y2;
05123                 x2++;
05124                 y2++;
05125         }
05126         result |= _aalineColor(dst, *x1, *y1, *vx, *vy, color, 0);
05127 
05128         return (result);
05129 }
05130 
05145 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05146 {
05147         /*
05148         * Draw 
05149         */
05150         return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
05151 }
05152 
05153 /* ---- Filled Polygon */
05154 
05163 int _gfxPrimitivesCompareInt(const void *a, const void *b)
05164 {
05165         return (*(const int *) a) - (*(const int *) b);
05166 }
05167 
05173 static int *gfxPrimitivesPolyIntsGlobal = NULL;
05174 
05180 static int gfxPrimitivesPolyAllocatedGlobal = 0;
05181 
05197 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
05198 {
05199         int result;
05200         int i;
05201         int y, xa, xb;
05202         int miny, maxy;
05203         int x1, y1;
05204         int x2, y2;
05205         int ind1, ind2;
05206         int ints;
05207         int *gfxPrimitivesPolyInts = NULL;
05208         int *gfxPrimitivesPolyIntsNew = NULL;
05209         int gfxPrimitivesPolyAllocated = 0;
05210 
05211         /*
05212         * Check visibility of clipping rectangle
05213         */
05214         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05215                 return(0);
05216         }
05217 
05218         /*
05219         * Vertex array NULL check 
05220         */
05221         if (vx == NULL) {
05222                 return (-1);
05223         }
05224         if (vy == NULL) {
05225                 return (-1);
05226         }
05227 
05228         /*
05229         * Sanity check number of edges
05230         */
05231         if (n < 3) {
05232                 return -1;
05233         }
05234 
05235         /*
05236         * Map polygon cache  
05237         */
05238         if ((polyInts==NULL) || (polyAllocated==NULL)) {
05239                 /* Use global cache */
05240                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
05241                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
05242         } else {
05243                 /* Use local cache */
05244                 gfxPrimitivesPolyInts = *polyInts;
05245                 gfxPrimitivesPolyAllocated = *polyAllocated;
05246         }
05247 
05248         /*
05249         * Allocate temp array, only grow array 
05250         */
05251         if (!gfxPrimitivesPolyAllocated) {
05252                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
05253                 gfxPrimitivesPolyAllocated = n;
05254         } else {
05255                 if (gfxPrimitivesPolyAllocated < n) {
05256                         gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
05257                         if (!gfxPrimitivesPolyIntsNew) {
05258                                 if (!gfxPrimitivesPolyInts) {
05259                                         free(gfxPrimitivesPolyInts);
05260                                         gfxPrimitivesPolyInts = NULL;
05261                                 }
05262                                 gfxPrimitivesPolyAllocated = 0;
05263                         } else {
05264                                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
05265                                 gfxPrimitivesPolyAllocated = n;
05266                         }
05267                 }
05268         }
05269 
05270         /*
05271         * Check temp array
05272         */
05273         if (gfxPrimitivesPolyInts==NULL) {        
05274                 gfxPrimitivesPolyAllocated = 0;
05275         }
05276 
05277         /*
05278         * Update cache variables
05279         */
05280         if ((polyInts==NULL) || (polyAllocated==NULL)) { 
05281                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
05282                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
05283         } else {
05284                 *polyInts = gfxPrimitivesPolyInts;
05285                 *polyAllocated = gfxPrimitivesPolyAllocated;
05286         }
05287 
05288         /*
05289         * Check temp array again
05290         */
05291         if (gfxPrimitivesPolyInts==NULL) {        
05292                 return(-1);
05293         }
05294 
05295         /*
05296         * Determine Y maxima 
05297         */
05298         miny = vy[0];
05299         maxy = vy[0];
05300         for (i = 1; (i < n); i++) {
05301                 if (vy[i] < miny) {
05302                         miny = vy[i];
05303                 } else if (vy[i] > maxy) {
05304                         maxy = vy[i];
05305                 }
05306         }
05307 
05308         /*
05309         * Draw, scanning y 
05310         */
05311         result = 0;
05312         for (y = miny; (y <= maxy); y++) {
05313                 ints = 0;
05314                 for (i = 0; (i < n); i++) {
05315                         if (!i) {
05316                                 ind1 = n - 1;
05317                                 ind2 = 0;
05318                         } else {
05319                                 ind1 = i - 1;
05320                                 ind2 = i;
05321                         }
05322                         y1 = vy[ind1];
05323                         y2 = vy[ind2];
05324                         if (y1 < y2) {
05325                                 x1 = vx[ind1];
05326                                 x2 = vx[ind2];
05327                         } else if (y1 > y2) {
05328                                 y2 = vy[ind1];
05329                                 y1 = vy[ind2];
05330                                 x2 = vx[ind1];
05331                                 x1 = vx[ind2];
05332                         } else {
05333                                 continue;
05334                         }
05335                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
05336                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
05337                         }           
05338                 }
05339 
05340                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
05341 
05342                 for (i = 0; (i < ints); i += 2) {
05343                         xa = gfxPrimitivesPolyInts[i] + 1;
05344                         xa = (xa >> 16) + ((xa & 32768) >> 15);
05345                         xb = gfxPrimitivesPolyInts[i+1] - 1;
05346                         xb = (xb >> 16) + ((xb & 32768) >> 15);
05347                         result |= hlineColor(dst, xa, xb, y, color);
05348                 }
05349         }
05350 
05351         return (result);
05352 }
05353 
05372 int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
05373 {
05374         /*
05375         * Draw 
05376         */
05377         return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
05378 }
05379 
05394 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
05395 {
05396         /*
05397         * Draw 
05398         */
05399         return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
05400 }
05401 
05416 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
05417 {
05418         /*
05419         * Draw 
05420         */
05421         return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
05422 }
05423 
05437 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy)
05438 {
05439         Sint16 left, right, top, bottom;
05440         Sint16 w;
05441         Sint16 xtmp;
05442         int result = 0;
05443         int texture_x_walker;    
05444         int texture_y_start;    
05445         SDL_Rect source_rect,dst_rect;
05446         int pixels_written,write_width;
05447 
05448         /*
05449         * Check visibility of clipping rectangle
05450         */
05451         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05452                 return(0);
05453         }
05454 
05455         /*
05456         * Swap x1, x2 if required to ensure x1<=x2
05457         */
05458         if (x1 > x2) {
05459                 xtmp = x1;
05460                 x1 = x2;
05461                 x2 = xtmp;
05462         }
05463 
05464         /*
05465         * Get clipping boundary and
05466         * check visibility of hline 
05467         */
05468         left = dst->clip_rect.x;
05469         if (x2<left) {
05470                 return(0);
05471         }
05472         right = dst->clip_rect.x + dst->clip_rect.w - 1;
05473         if (x1>right) {
05474                 return(0);
05475         }
05476         top = dst->clip_rect.y;
05477         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
05478         if ((y<top) || (y>bottom)) {
05479                 return (0);
05480         }
05481 
05482         /*
05483         * Clip x 
05484         */
05485         if (x1 < left) {
05486                 x1 = left;
05487         }
05488         if (x2 > right) {
05489                 x2 = right;
05490         }
05491 
05492         /*
05493         * Calculate width to draw
05494         */
05495         w = x2 - x1 + 1;
05496 
05497         /*
05498         * Determine where in the texture we start drawing
05499         */
05500         texture_x_walker =   (x1 - texture_dx)  % texture->w;
05501         if (texture_x_walker < 0){
05502                 texture_x_walker = texture->w + texture_x_walker ;
05503         }
05504 
05505         texture_y_start = (y + texture_dy) % texture->h;
05506         if (texture_y_start < 0){
05507                 texture_y_start = texture->h + texture_y_start;
05508         }
05509 
05510         // setup the source rectangle; we are only drawing one horizontal line
05511         source_rect.y = texture_y_start;
05512         source_rect.x = texture_x_walker;
05513         source_rect.h = 1;
05514 
05515         // we will draw to the current y
05516         dst_rect.y = y;
05517 
05518         // if there are enough pixels left in the current row of the texture
05519         // draw it all at once
05520         if (w <= texture->w -texture_x_walker){
05521                 source_rect.w = w;
05522                 source_rect.x = texture_x_walker;
05523                 dst_rect.x= x1;
05524                 result = (SDL_BlitSurface  (texture, &source_rect , dst, &dst_rect) == 0);
05525         } else { // we need to draw multiple times
05526                 // draw the first segment
05527                 pixels_written = texture->w  - texture_x_walker;
05528                 source_rect.w = pixels_written;
05529                 source_rect.x = texture_x_walker;
05530                 dst_rect.x= x1;
05531                 result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
05532                 write_width = texture->w;
05533 
05534                 // now draw the rest
05535                 // set the source x to 0
05536                 source_rect.x = 0;
05537                 while (pixels_written < w){
05538                         if (write_width >= w - pixels_written) {
05539                                 write_width =  w - pixels_written;
05540                         }
05541                         source_rect.w = write_width;
05542                         dst_rect.x = x1 + pixels_written;
05543                         result  |= (SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) == 0);
05544                         pixels_written += write_width;
05545                 }
05546         }
05547 
05548         return result;
05549 }
05550 
05574 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, 
05575         SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
05576 {
05577         int result;
05578         int i;
05579         int y, xa, xb;
05580         int minx,maxx,miny, maxy;
05581         int x1, y1;
05582         int x2, y2;
05583         int ind1, ind2;
05584         int ints;
05585         int *gfxPrimitivesPolyInts = NULL;
05586         int gfxPrimitivesPolyAllocated = 0;
05587 
05588         /*
05589         * Check visibility of clipping rectangle
05590         */
05591         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05592                 return(0);
05593         }
05594 
05595         /*
05596         * Sanity check number of edges
05597         */
05598         if (n < 3) {
05599                 return -1;
05600         }
05601 
05602         /*
05603         * Map polygon cache  
05604         */
05605         if ((polyInts==NULL) || (polyAllocated==NULL)) {
05606                 /* Use global cache */
05607                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
05608                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
05609         } else {
05610                 /* Use local cache */
05611                 gfxPrimitivesPolyInts = *polyInts;
05612                 gfxPrimitivesPolyAllocated = *polyAllocated;
05613         }
05614 
05615         /*
05616         * Allocate temp array, only grow array 
05617         */
05618         if (!gfxPrimitivesPolyAllocated) {
05619                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
05620                 gfxPrimitivesPolyAllocated = n;
05621         } else {
05622                 if (gfxPrimitivesPolyAllocated < n) {
05623                         gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
05624                         gfxPrimitivesPolyAllocated = n;
05625                 }
05626         }
05627 
05628         /*
05629         * Check temp array
05630         */
05631         if (gfxPrimitivesPolyInts==NULL) {        
05632                 gfxPrimitivesPolyAllocated = 0;
05633         }
05634 
05635         /*
05636         * Update cache variables
05637         */
05638         if ((polyInts==NULL) || (polyAllocated==NULL)) { 
05639                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
05640                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
05641         } else {
05642                 *polyInts = gfxPrimitivesPolyInts;
05643                 *polyAllocated = gfxPrimitivesPolyAllocated;
05644         }
05645 
05646         /*
05647         * Check temp array again
05648         */
05649         if (gfxPrimitivesPolyInts==NULL) {        
05650                 return(-1);
05651         }
05652 
05653         /*
05654         * Determine X,Y minima,maxima 
05655         */
05656         miny = vy[0];
05657         maxy = vy[0];
05658         minx = vx[0];
05659         maxx = vx[0];
05660         for (i = 1; (i < n); i++) {
05661                 if (vy[i] < miny) {
05662                         miny = vy[i];
05663                 } else if (vy[i] > maxy) {
05664                         maxy = vy[i];
05665                 }
05666                 if (vx[i] < minx) {
05667                         minx = vx[i];
05668                 } else if (vx[i] > maxx) {
05669                         maxx = vx[i];
05670                 }
05671         }
05672         if (maxx <0 || minx > dst->w){
05673                 return -1;
05674         }
05675         if (maxy <0 || miny > dst->h){
05676                 return -1;
05677         }
05678 
05679         /*
05680         * Draw, scanning y 
05681         */
05682         result = 0;
05683         for (y = miny; (y <= maxy); y++) {
05684                 ints = 0;
05685                 for (i = 0; (i < n); i++) {
05686                         if (!i) {
05687                                 ind1 = n - 1;
05688                                 ind2 = 0;
05689                         } else {
05690                                 ind1 = i - 1;
05691                                 ind2 = i;
05692                         }
05693                         y1 = vy[ind1];
05694                         y2 = vy[ind2];
05695                         if (y1 < y2) {
05696                                 x1 = vx[ind1];
05697                                 x2 = vx[ind2];
05698                         } else if (y1 > y2) {
05699                                 y2 = vy[ind1];
05700                                 y1 = vy[ind2];
05701                                 x2 = vx[ind1];
05702                                 x1 = vx[ind2];
05703                         } else {
05704                                 continue;
05705                         }
05706                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
05707                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
05708                         } 
05709                 }
05710 
05711                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
05712 
05713                 for (i = 0; (i < ints); i += 2) {
05714                         xa = gfxPrimitivesPolyInts[i] + 1;
05715                         xa = (xa >> 16) + ((xa & 32768) >> 15);
05716                         xb = gfxPrimitivesPolyInts[i+1] - 1;
05717                         xb = (xb >> 16) + ((xb & 32768) >> 15);
05718                         result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
05719                 }
05720         }
05721 
05722         return (result);
05723 }
05724 
05741 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
05742 {
05743         /*
05744         * Draw
05745         */
05746         return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
05747 }
05748 
05749 
05750 /* ---- Character */
05751 
05755 static SDL_Surface *gfxPrimitivesFont[256];
05756 
05760 static Uint32 gfxPrimitivesFontColor[256];
05761 
05765 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
05766 
05770 static Uint32 charWidth = 8;
05771 
05775 static Uint32 charHeight = 8;
05776 
05780 static Uint32 charWidthLocal = 8;
05781 
05785 static Uint32 charHeightLocal = 8;
05786 
05790 static Uint32 charPitch = 1;
05791 
05795 static Uint32 charRotation = 0;
05796 
05800 static Uint32 charSize = 8;
05801 
05815 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
05816 {
05817         int i;
05818 
05819         if ((fontdata) && (cw) && (ch)) {
05820                 currentFontdata = fontdata;
05821                 charWidth = cw;
05822                 charHeight = ch;
05823         } else {
05824                 currentFontdata = gfxPrimitivesFontdata;
05825                 charWidth = 8;
05826                 charHeight = 8;
05827         }
05828 
05829         charPitch = (charWidth+7)/8;
05830         charSize = charPitch * charHeight;
05831 
05832         /* Maybe flip width/height for rendering */
05833         if ((charRotation==1) || (charRotation==3))
05834         {
05835                 charWidthLocal = charHeight;
05836                 charHeightLocal = charWidth;
05837         }
05838         else
05839         {
05840                 charWidthLocal = charWidth;
05841                 charHeightLocal = charHeight;
05842         }
05843 
05844         /* Clear character cache */
05845         for (i = 0; i < 256; i++) {
05846                 if (gfxPrimitivesFont[i]) {
05847                         SDL_FreeSurface(gfxPrimitivesFont[i]);
05848                         gfxPrimitivesFont[i] = NULL;
05849                 }
05850         }
05851 }
05852 
05861 void gfxPrimitivesSetFontRotation(Uint32 rotation)
05862 {
05863         int i;
05864 
05865         rotation = rotation & 3;
05866         if (charRotation != rotation)
05867         {
05868                 /* Store rotation */
05869                 charRotation = rotation;
05870 
05871                 /* Maybe flip width/height for rendering */
05872                 if ((charRotation==1) || (charRotation==3))
05873                 {
05874                         charWidthLocal = charHeight;
05875                         charHeightLocal = charWidth;
05876                 }
05877                 else
05878                 {
05879                         charWidthLocal = charWidth;
05880                         charHeightLocal = charHeight;
05881                 }
05882 
05883                 /* Clear character cache */
05884                 for (i = 0; i < 256; i++) {
05885                         if (gfxPrimitivesFont[i]) {
05886                                 SDL_FreeSurface(gfxPrimitivesFont[i]);
05887                                 gfxPrimitivesFont[i] = NULL;
05888                         }
05889                 }
05890         }
05891 }
05892 
05908 int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color)
05909 {
05910         Sint16 left, right, top, bottom;
05911         Sint16 x1, y1, x2, y2;
05912         SDL_Rect srect;
05913         SDL_Rect drect;
05914         int result;
05915         Uint32 ix, iy;
05916         const unsigned char *charpos;
05917         Uint8 *curpos;
05918         int forced_redraw;
05919         Uint8 patt, mask;
05920         Uint8 *linepos;
05921         Uint32 pitch;
05922         SDL_Surface *rotatedCharacter;
05923         Uint32 ci;
05924 
05925         /*
05926         * Check visibility of clipping rectangle
05927         */
05928         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
05929                 return(0);
05930         }
05931 
05932         /*
05933         * Get text and clipping boundary and
05934         * test if bounding box of character is visible 
05935         */
05936 
05937         left = dst->clip_rect.x;
05938         x2 = x + charWidthLocal;
05939         if (x2<left) {
05940                 return(0);
05941         } 
05942         right = dst->clip_rect.x + dst->clip_rect.w - 1;
05943         x1 = x;
05944         if (x1>right) {
05945                 return(0);
05946         } 
05947         top = dst->clip_rect.y;
05948         y2 = y + charHeightLocal;
05949         if (y2<top) {
05950                 return(0);
05951         } 
05952         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
05953         y1 = y;
05954         if (y1>bottom) {
05955                 return(0);
05956         } 
05957 
05958         /*
05959         * Setup source rectangle
05960         */
05961         srect.x = 0;
05962         srect.y = 0;
05963         srect.w = charWidthLocal;
05964         srect.h = charHeightLocal;
05965 
05966         /*
05967         * Setup destination rectangle
05968         */
05969         drect.x = x;
05970         drect.y = y;
05971         drect.w = charWidthLocal;
05972         drect.h = charHeightLocal;
05973 
05974         /* Character index in cache */
05975         ci = (unsigned char) c;
05976 
05977         /*
05978         * Create new charWidth x charHeight bitmap surface if not already present.
05979         * Might get rotated later.
05980         */
05981         if (gfxPrimitivesFont[ci] == NULL) {
05982                 gfxPrimitivesFont[ci] =
05983                         SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA,
05984                         charWidth, charHeight, 32,
05985                         0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
05986                 /*
05987                 * Check pointer 
05988                 */
05989                 if (gfxPrimitivesFont[ci] == NULL) {
05990                         return (-1);
05991                 }
05992                 /*
05993                 * Definitely redraw 
05994                 */
05995                 forced_redraw = 1;
05996         } else {
05997                 forced_redraw = 0;
05998         }
05999 
06000         /*
06001         * Check if color has changed 
06002         */
06003         if ((gfxPrimitivesFontColor[ci] != color) || (forced_redraw)) {
06004                 /*
06005                 * Redraw character 
06006                 */
06007                 SDL_SetAlpha(gfxPrimitivesFont[ci], SDL_SRCALPHA, 255);
06008                 gfxPrimitivesFontColor[ci] = color;
06009 
06010                 /* Lock font-surface */
06011                 if (SDL_LockSurface(gfxPrimitivesFont[ci]) != 0)
06012                         return (-1);
06013 
06014                 /*
06015                 * Variable setup 
06016                 */
06017                 charpos = currentFontdata + ci * charSize;
06018                 linepos = (Uint8 *) gfxPrimitivesFont[ci]->pixels;
06019                 pitch = gfxPrimitivesFont[ci]->pitch;
06020 
06021                 /*
06022                 * Drawing loop 
06023                 */
06024                 patt = 0;
06025                 for (iy = 0; iy < charHeight; iy++) {
06026                         mask = 0x00;
06027                         curpos = linepos;
06028                         for (ix = 0; ix < charWidth; ix++) {
06029                                 if (!(mask >>= 1)) {
06030                                         patt = *charpos++;
06031                                         mask = 0x80;
06032                                 }
06033 
06034                                 if (patt & mask)
06035                                         *(Uint32 *)curpos = color;
06036                                 else
06037                                         *(Uint32 *)curpos = 0;
06038                                 curpos += 4;
06039                         }
06040                         linepos += pitch;
06041                 }
06042 
06043                 /* Unlock font-surface */
06044                 SDL_UnlockSurface(gfxPrimitivesFont[ci]);
06045 
06046                 /* Maybe rotate and replace cached image */
06047                 if (charRotation>0)
06048                 {
06049                         rotatedCharacter = rotateSurface90Degrees(gfxPrimitivesFont[ci], charRotation);
06050                         SDL_FreeSurface(gfxPrimitivesFont[ci]);
06051                         gfxPrimitivesFont[ci] = rotatedCharacter;
06052                 }
06053         }
06054 
06055         /*
06056         * Draw bitmap onto destination surface 
06057         */
06058         result = SDL_BlitSurface(gfxPrimitivesFont[ci], &srect, dst, &drect);
06059 
06060         return (result);
06061 }
06062 
06077 int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
06078 {
06079         /*
06080         * Draw 
06081         */
06082         return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
06083 }
06084 
06099 int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color)
06100 {
06101         int result = 0;
06102         Sint16 curx = x;
06103         Sint16 cury = y;
06104         const char *curchar = s;
06105 
06106         while (*curchar && !result) {
06107                 result |= characterColor(dst, curx, cury, *curchar, color);
06108                 switch (charRotation)
06109                 {
06110                 case 0:
06111                         curx += charWidthLocal;
06112                         break;
06113                 case 2:
06114                         curx -= charWidthLocal;
06115                         break;
06116                 case 1:
06117                         cury += charHeightLocal;
06118                         break;
06119                 case 3:
06120                         cury -= charHeightLocal;
06121                         break;
06122                 }
06123                 curchar++;
06124         }
06125 
06126         return (result);
06127 }
06128 
06143 int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
06144 {
06145         /*
06146         * Draw 
06147         */
06148         return (stringColor(dst, x, y, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
06149 }
06150 
06151 /* ---- Bezier curve */
06152 
06162 double _evaluateBezier (double *data, int ndata, double t) 
06163 {
06164         double mu, result;
06165         int n,k,kn,nn,nkn;
06166         double blend,muk,munk;
06167 
06168         /* Sanity check bounds */
06169         if (t<0.0) {
06170                 return(data[0]);
06171         }
06172         if (t>=(double)ndata) {
06173                 return(data[ndata-1]);
06174         }
06175 
06176         /* Adjust t to the range 0.0 to 1.0 */ 
06177         mu=t/(double)ndata;
06178 
06179         /* Calculate interpolate */
06180         n=ndata-1;
06181         result=0.0;
06182         muk = 1;
06183         munk = pow(1-mu,(double)n);
06184         for (k=0;k<=n;k++) {
06185                 nn = n;
06186                 kn = k;
06187                 nkn = n - k;
06188                 blend = muk * munk;
06189                 muk *= mu;
06190                 munk /= (1-mu);
06191                 while (nn >= 1) {
06192                         blend *= nn;
06193                         nn--;
06194                         if (kn > 1) {
06195                                 blend /= (double)kn;
06196                                 kn--;
06197                         }
06198                         if (nkn > 1) {
06199                                 blend /= (double)nkn;
06200                                 nkn--;
06201                         }
06202                 }
06203                 result += data[k] * blend;
06204         }
06205 
06206         return (result);
06207 }
06208 
06221 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
06222 {
06223         int result;
06224         int i;
06225         double *x, *y, t, stepsize;
06226         Sint16 x1, y1, x2, y2;
06227 
06228         /*
06229         * Sanity check 
06230         */
06231         if (n < 3) {
06232                 return (-1);
06233         }
06234         if (s < 2) {
06235                 return (-1);
06236         }
06237 
06238         /*
06239         * Variable setup 
06240         */
06241         stepsize=(double)1.0/(double)s;
06242 
06243         /* Transfer vertices into float arrays */
06244         if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
06245                 return(-1);
06246         }
06247         if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
06248                 free(x);
06249                 return(-1);
06250         }    
06251         for (i=0; i<n; i++) {
06252                 x[i]=(double)vx[i];
06253                 y[i]=(double)vy[i];
06254         }      
06255         x[n]=(double)vx[0];
06256         y[n]=(double)vy[0];
06257 
06258         /*
06259         * Draw 
06260         */
06261         result = 0;
06262         t=0.0;
06263         x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
06264         y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
06265         for (i = 0; i <= (n*s); i++) {
06266                 t += stepsize;
06267                 x2=(Sint16)_evaluateBezier(x,n,t);
06268                 y2=(Sint16)_evaluateBezier(y,n,t);
06269                 result |= lineColor(dst, x1, y1, x2, y2, color);
06270                 x1 = x2;
06271                 y1 = y2;
06272         }
06273 
06274         /* Clean up temporary array */
06275         free(x);
06276         free(y);
06277 
06278         return (result);
06279 }
06280 
06296 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
06297 {
06298         /*
06299         * Draw 
06300         */
06301         return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
06302 }
06303 
06304 
06323 int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
06324 {
06325         int temp;
06326 
06327         if (b==NULL) {
06328                 return(-1);
06329         }
06330 
06331         b->x = x1;
06332         b->y = y1;
06333 
06334         /* dx = abs(x2-x1), s1 = sign(x2-x1) */
06335         if ((b->dx = x2 - x1) != 0) {
06336                 if (b->dx < 0) {
06337                         b->dx = -b->dx;
06338                         b->s1 = -1;
06339                 } else {
06340                         b->s1 = 1;
06341                 }
06342         } else {
06343                 b->s1 = 0;      
06344         }
06345 
06346         /* dy = abs(y2-y1), s2 = sign(y2-y1)    */
06347         if ((b->dy = y2 - y1) != 0) {
06348                 if (b->dy < 0) {
06349                         b->dy = -b->dy;
06350                         b->s2 = -1;
06351                 } else {
06352                         b->s2 = 1;
06353                 }
06354         } else {
06355                 b->s2 = 0;      
06356         }
06357 
06358         if (b->dy > b->dx) {
06359                 temp = b->dx;
06360                 b->dx = b->dy;
06361                 b->dy = temp;
06362                 b->swapdir = 1;
06363         } else {
06364                 b->swapdir = 0;
06365         }
06366 
06367         b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
06368         b->dy <<= 1;
06369         b->error = b->dy - b->dx;
06370         b->dx <<= 1;    
06371 
06372         return(0);
06373 }
06374 
06375 
06385 int _bresenhamIterate(SDL_gfxBresenhamIterator *b)
06386 {       
06387         if (b==NULL) {
06388                 return (-1);
06389         }
06390 
06391         /* last point check */
06392         if (b->count==0) {
06393                 return (2);
06394         }
06395 
06396         while (b->error >= 0) {
06397                 if (b->swapdir) {
06398                         b->x += b->s1;
06399                 } else  {
06400                         b->y += b->s2;
06401                 }
06402 
06403                 b->error -= b->dx;
06404         }
06405 
06406         if (b->swapdir) {
06407                 b->y += b->s2;
06408         } else {
06409                 b->x += b->s1;
06410         }
06411 
06412         b->error += b->dy;      
06413         b->count--;             
06414 
06415         /* count==0 indicates "end-of-line" */
06416         return ((b->count) ? 0 : 1);
06417 }
06418 
06419 
06428 void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
06429 {
06430         int p;
06431         d1 = -d1;
06432 
06433         /*
06434         * Lock the surface 
06435         */
06436         if (SDL_MUSTLOCK(m->dst)) {
06437                 SDL_LockSurface(m->dst);
06438         }
06439 
06440         for (p = 0; p <= m->u; p++) {
06441 
06442                 pixelColorNolock(m->dst, x, y, m->color);
06443 
06444                 if (d1 <= m->kt) {
06445                         if (m->oct2 == 0) {
06446                                 x++;
06447                         } else {
06448                                 if (m->quad4 == 0) {
06449                                         y++;
06450                                 } else {
06451                                         y--;
06452                                 }
06453                         }
06454                         d1 += m->kv;
06455                 } else {        
06456                         x++;
06457                         if (m->quad4 == 0) {
06458                                 y++;
06459                         } else {
06460                                 y--;
06461                         }
06462                         d1 += m->kd;
06463                 }
06464         }
06465 
06466         /* Unlock surface */
06467         if (SDL_MUSTLOCK(m->dst)) {
06468                 SDL_UnlockSurface(m->dst);
06469         }
06470 
06471         m->tempx = x;
06472         m->tempy = y;
06473 }
06474 
06490 void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter, 
06491         Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by, 
06492         Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
06493 {
06494         int atemp1, atemp2;
06495         int ftmp1, ftmp2;
06496         Uint16 m1x, m1y, m2x, m2y;      
06497         Uint16 fix, fiy, lax, lay, curx, cury;
06498         Uint16 px[4], py[4];
06499         SDL_gfxBresenhamIterator b;
06500 
06501         if (miter > 1) {
06502                 if (m->first1x != -32768) {
06503                         fix = (m->first1x + m->first2x) / 2;
06504                         fiy = (m->first1y + m->first2y) / 2;
06505                         lax = (m->last1x + m->last2x) / 2;
06506                         lay = (m->last1y + m->last2y) / 2;
06507                         curx = (ml1x + ml2x) / 2;
06508                         cury = (ml1y + ml2y) / 2;
06509 
06510                         atemp1 = (fix - curx);
06511                         atemp2 = (fiy - cury);
06512                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
06513                         atemp1 = (lax - curx);
06514                         atemp2 = (lay - cury);
06515                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
06516 
06517                         if (ftmp1 <= ftmp2) {
06518                                 m1x = m->first1x;
06519                                 m1y = m->first1y;
06520                                 m2x = m->first2x;
06521                                 m2y = m->first2y;
06522                         } else {
06523                                 m1x = m->last1x;
06524                                 m1y = m->last1y;
06525                                 m2x = m->last2x;
06526                                 m2y = m->last2y;
06527                         }
06528 
06529                         atemp1 = (m2x - ml2x);
06530                         atemp2 = (m2y - ml2y);
06531                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
06532                         atemp1 = (m2x - ml2bx);
06533                         atemp2 = (m2y - ml2by);
06534                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
06535 
06536                         if (ftmp2 >= ftmp1) {
06537                                 ftmp1 = ml2bx;
06538                                 ftmp2 = ml2by;
06539                                 ml2bx = ml2x;
06540                                 ml2by = ml2y;
06541                                 ml2x = ftmp1;
06542                                 ml2y = ftmp2;
06543                                 ftmp1 = ml1bx;
06544                                 ftmp2 = ml1by;
06545                                 ml1bx = ml1x;
06546                                 ml1by = ml1y;
06547                                 ml1x = ftmp1;
06548                                 ml1y = ftmp2;
06549                         }
06550 
06551                         /*
06552                         * Lock the surface 
06553                         */
06554                         if (SDL_MUSTLOCK(m->dst)) {
06555                                 SDL_LockSurface(m->dst);
06556                         }
06557 
06558                         _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
06559                         do {
06560                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06561                         } while (_bresenhamIterate(&b)==0);
06562 
06563                         _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
06564                         do {
06565                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06566                         } while (_bresenhamIterate(&b)==0);
06567 
06568                         _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
06569                         do {
06570                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06571                         } while (_bresenhamIterate(&b)==0);
06572 
06573                         _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
06574                         do {
06575                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
06576                         } while (_bresenhamIterate(&b)==0);
06577 
06578                         /* Unlock surface */
06579                         if (SDL_MUSTLOCK(m->dst)) {
06580                                 SDL_UnlockSurface(m->dst);
06581                         }
06582 
06583                         px[0] = m1x;
06584                         px[1] = m2x;
06585                         px[2] = ml1bx;
06586                         px[3] = ml2bx;
06587                         py[0] = m1y;
06588                         py[1] = m2y;
06589                         py[2] = ml1by;
06590                         py[3] = ml2by;                  
06591                         polygonColor(m->dst, px, py, 4, m->color);                                              
06592                 }
06593         }
06594 
06595         m->last1x = ml1x;
06596         m->last1y = ml1y;
06597         m->last2x = ml2x;
06598         m->last2y = ml2y;
06599         m->first1x = ml1bx;
06600         m->first1y = ml1by;
06601         m->first2x = ml2bx;
06602         m->first2y = ml2by;
06603 }
06604 
06605 
06606 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y)) 
06607 
06622 void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
06623 {       
06624         float offset = (float)width / 2.f;
06625 
06626         Sint16 temp;
06627         Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
06628 
06629         int d0, d1;             /* difference terms d0=perpendicular to line, d1=along line */
06630 
06631         int q;                  /* pel counter,q=perpendicular to line */
06632         int tmp;
06633 
06634         int dd;                 /* distance along line */
06635         int tk;                 /* thickness threshold */
06636         double ang;             /* angle for initial point calculation */
06637         double sang, cang;
06638 
06639         /* Initialisation */
06640         m->u = x2 - x1; /* delta x */
06641         m->v = y2 - y1; /* delta y */
06642 
06643         if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
06644                 temp = x1;
06645                 x1 = x2;
06646                 x2 = temp;
06647                 temp = y1;
06648                 y1 = y2;
06649                 y2 = temp;              
06650                 m->u *= -1;
06651                 m->v *= -1;
06652         }
06653 
06654         if (m->v < 0) { /* swap to 1st quadrant and flag */
06655                 m->v *= -1;
06656                 m->quad4 = 1;
06657         } else {
06658                 m->quad4 = 0;
06659         }
06660 
06661         if (m->v > m->u) {      /* swap things if in 2 octant */
06662                 tmp = m->u;
06663                 m->u = m->v;
06664                 m->v = tmp;
06665                 m->oct2 = 1;
06666         } else {
06667                 m->oct2 = 0;
06668         }
06669 
06670         m->ku = m->u + m->u;    /* change in l for square shift */
06671         m->kv = m->v + m->v;    /* change in d for square shift */
06672         m->kd = m->kv - m->ku;  /* change in d for diagonal shift */
06673         m->kt = m->u - m->kv;   /* diag/square decision threshold */
06674 
06675         d0 = 0;
06676         d1 = 0;
06677         dd = 0;
06678 
06679         ang = atan((double) m->v / (double) m->u);      /* calc new initial point - offset both sides of ideal */       
06680         sang = sin(ang);
06681         cang = cos(ang);
06682 
06683         if (m->oct2 == 0) {
06684                 ptx = x1 + (Sint16)lrint(offset * sang);
06685                 if (m->quad4 == 0) {
06686                         pty = y1 - (Sint16)lrint(offset * cang);
06687                 } else {
06688                         pty = y1 + (Sint16)lrint(offset * cang);
06689                 }
06690         } else {
06691                 ptx = x1 - (Sint16)lrint(offset * cang);
06692                 if (m->quad4 == 0) {
06693                         pty = y1 + (Sint16)lrint(offset * sang);
06694                 } else {
06695                         pty = y1 - (Sint16)lrint(offset * sang);
06696                 }
06697         }
06698 
06699         /* used here for constant thickness line */
06700         tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
06701 
06702         if (miter == 0) {
06703                 m->first1x = -32768;
06704                 m->first1y = -32768;
06705                 m->first2x = -32768;
06706                 m->first2y = -32768;
06707                 m->last1x = -32768;
06708                 m->last1y = -32768;
06709                 m->last2x = -32768;
06710                 m->last2y = -32768;
06711         }
06712         ptxx = ptx;
06713         ptxy = pty;
06714 
06715         for (q = 0; dd <= tk; q++) {    /* outer loop, stepping perpendicular to line */
06716 
06717                 _murphyParaline(m, ptx, pty, d1);       /* call to inner loop - right edge */
06718                 if (q == 0) {
06719                         ml1x = ptx;
06720                         ml1y = pty;
06721                         ml1bx = m->tempx;
06722                         ml1by = m->tempy;
06723                 } else {
06724                         ml2x = ptx;
06725                         ml2y = pty;
06726                         ml2bx = m->tempx;
06727                         ml2by = m->tempy;
06728                 }
06729                 if (d0 < m->kt) {       /* square move */
06730                         if (m->oct2 == 0) {
06731                                 if (m->quad4 == 0) {
06732                                         pty++;
06733                                 } else {
06734                                         pty--;
06735                                 }
06736                         } else {
06737                                 ptx++;
06738                         }
06739                 } else {        /* diagonal move */
06740                         dd += m->kv;
06741                         d0 -= m->ku;
06742                         if (d1 < m->kt) {       /* normal diagonal */
06743                                 if (m->oct2 == 0) {
06744                                         ptx--;
06745                                         if (m->quad4 == 0) {
06746                                                 pty++;
06747                                         } else {
06748                                                 pty--;
06749                                         }
06750                                 } else {
06751                                         ptx++;
06752                                         if (m->quad4 == 0) {
06753                                                 pty--;
06754                                         } else {
06755                                                 pty++;
06756                                         }
06757                                 }
06758                                 d1 += m->kv;
06759                         } else {        /* double square move, extra parallel line */
06760                                 if (m->oct2 == 0) {
06761                                         ptx--;
06762                                 } else {
06763                                         if (m->quad4 == 0) {
06764                                                 pty--;
06765                                         } else {
06766                                                 pty++;
06767                                         }
06768                                 }
06769                                 d1 += m->kd;
06770                                 if (dd > tk) {
06771                                         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
06772                                         return; /* breakout on the extra line */
06773                                 }
06774                                 _murphyParaline(m, ptx, pty, d1);
06775                                 if (m->oct2 == 0) {
06776                                         if (m->quad4 == 0) {
06777                                                 pty++;
06778                                         } else {
06779 
06780                                                 pty--;
06781                                         }
06782                                 } else {
06783                                         ptx++;
06784                                 }
06785                         }
06786                 }
06787                 dd += m->ku;
06788                 d0 += m->kv;
06789         }
06790 
06791         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
06792 }
06793 
06794 
06808 int thickLineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
06809 {       
06810         int wh;
06811         SDL_gfxMurphyIterator m;
06812 
06813         if (dst == NULL) return -1;
06814         if (width < 1) return -1;
06815 
06816         /* Special case: thick "point" */
06817         if ((x1 == x2) && (y1 == y2)) {
06818                 wh = width / 2;
06819                 return boxColor(dst, x1 - wh, y1 - wh, x2 + width, y2 + width, color);          
06820         }
06821 
06822         m.dst = dst;
06823         m.color = color;
06824 
06825         _murphyWideline(&m, x1, y1, x2, y2, width, 0);
06826         _murphyWideline(&m, x1, y1, x2, y2, width, 1);
06827 
06828         return(0);
06829 }
06830 
06847 int thickLineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
06848 {
06849         return (thickLineColor(dst, x1, y1, x2, y2, width, 
06850                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
06851 }