SDL_gfx: SDL_gfxPrimitives.c Source File

- Main Page
- Data Structures
- Files

- File List
- Globals

# SDL_gfxPrimitives.c

Go to the documentation of this file.

    00001 /*
    00002
    00003 SDL_gfxPrimitives - Graphics primitives for SDL surfaces
    00004
    00005 LGPL (c) A. Schiffler
    00006
    00007 */
    00008
    00009 #include <stdio.h>
    00010 #include <stdlib.h>
    00011 #include <math.h>
    00012 #include <string.h>
    00013
    00014 #include "SDL_gfxPrimitives.h"
    00015 #include "SDL_rotozoom.h"
    00016 #include "SDL_gfxPrimitives_font.h"
    00017
    00018 /* -===================- */
    00019
    00020 #define DEFAULT_ALPHA_PIXEL_ROUTINE
    00021 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
    00022
    00023 /* ---- Structures */
    00024
    00028 typedef struct {
    00029         Sint16 x, y;
    00030         int dx, dy, s1, s2, swapdir, error;
    00031         Uint32 count;
    00032 } SDL_gfxBresenhamIterator;
    00033
    00037 typedef struct {
    00038         Uint32 color;
    00039         SDL_Surface *dst;
    00040         int u, v;               /* delta x , delta y */
    00041         int ku, kt, kv, kd;     /* loop constants */
    00042         int oct2;
    00043         int quad4;
    00044         Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
    00045 } SDL_gfxMurphyIterator;
    00046
    00047 /* ----- Defines for pixel clipping tests */
    00048
    00049 #define clip_xmin(surface) surface->clip_rect.x
    00050 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
    00051 #define clip_ymin(surface) surface->clip_rect.y
    00052 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
    00053
    00064 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
    00065 {
    00066         int bpp;
    00067         Uint8 *p;
    00068
    00069         /*
    00070         * Honor clipping setup at pixel level
    00071         */
    00072         if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
    00073
    00074                 /*
    00075                 * Get destination format
    00076                 */
    00077                 bpp = dst->format->BytesPerPixel;
    00078                 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
    00079                 switch (bpp) {
    00080         case 1:
    00081                 *p = color;
    00082                 break;
    00083         case 2:
    00084                 *(Uint16 *) p = color;
    00085                 break;
    00086         case 3:
    00087                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    00088                         p[0] = (color >> 16) & 0xff;
    00089                         p[1] = (color >> 8) & 0xff;
    00090                         p[2] = color & 0xff;
    00091                 } else {
    00092                         p[0] = color & 0xff;
    00093                         p[1] = (color >> 8) & 0xff;
    00094                         p[2] = (color >> 16) & 0xff;
    00095                 }
    00096                 break;
    00097         case 4:
    00098                 *(Uint32 *) p = color;
    00099                 break;
    00100                 }                       /* switch */
    00101
    00102
    00103         }
    00104
    00105         return (0);
    00106 }
    00107
    00121 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
    00122 {
    00123         int bpp;
    00124         Uint8 *p;
    00125
    00126         /*
    00127         * Get destination format
    00128         */
    00129         bpp = dst->format->BytesPerPixel;
    00130         p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
    00131         switch (bpp) {
    00132         case 1:
    00133                 *p = color;
    00134                 break;
    00135         case 2:
    00136                 *(Uint16 *) p = color;
    00137                 break;
    00138         case 3:
    00139                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    00140                         p[0] = (color >> 16) & 0xff;
    00141                         p[1] = (color >> 8) & 0xff;
    00142                         p[2] = color & 0xff;
    00143                 } else {
    00144                         p[0] = color & 0xff;
    00145                         p[1] = (color >> 8) & 0xff;
    00146                         p[2] = (color >> 16) & 0xff;
    00147                 }
    00148                 break;
    00149         case 4:
    00150                 *(Uint32 *) p = color;
    00151                 break;
    00152         }                               /* switch */
    00153
    00154         return (0);
    00155 }
    00156
    00167 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
    00168 {
    00169         int result;
    00170
    00171         /*
    00172         * Lock the surface
    00173         */
    00174         if (SDL_MUSTLOCK(dst)) {
    00175                 if (SDL_LockSurface(dst) < 0) {
    00176                         return (-1);
    00177                 }
    00178         }
    00179
    00180         result = fastPixelColorNolock(dst, x, y, color);
    00181
    00182         /*
    00183         * Unlock surface
    00184         */
    00185         if (SDL_MUSTLOCK(dst)) {
    00186                 SDL_UnlockSurface(dst);
    00187         }
    00188
    00189         return (result);
    00190 }
    00191
    00205 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00206 {
    00207         Uint32 color;
    00208
    00209         /*
    00210         * Setup color
    00211         */
    00212         color = SDL_MapRGBA(dst->format, r, g, b, a);
    00213
    00214         /*
    00215         * Draw
    00216         */
    00217         return (fastPixelColor(dst, x, y, color));
    00218 }
    00219
    00233 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00234 {
    00235         Uint32 color;
    00236
    00237         /*
    00238         * Setup color
    00239         */
    00240         color = SDL_MapRGBA(dst->format, r, g, b, a);
    00241
    00242         /*
    00243         * Draw
    00244         */
    00245         return (fastPixelColorNolock(dst, x, y, color));
    00246 }
    00247
    00263 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
    00264 {
    00265         SDL_PixelFormat *format;
    00266         Uint32 Rmask, Gmask, Bmask, Amask;
    00267         Uint32 Rshift, Gshift, Bshift, Ashift;
    00268         Uint32 R, G, B, A;
    00269
    00270         if (dst == NULL)
    00271         {
    00272                 return (-1);
    00273         }
    00274
    00275         if (x >= clip_xmin(dst) && x <= clip_xmax(dst) &&
    00276                 y >= clip_ymin(dst) && y <= clip_ymax(dst))
    00277         {
    00278
    00279                 format = dst->format;
    00280
    00281                 switch (format->BytesPerPixel) {
    00282         case 1:
    00283                 {               /* Assuming 8-bpp */
    00284                         if (alpha == 255) {
    00285                                 *((Uint8 *) dst->pixels + y * dst->pitch + x) = color;
    00286                         } else {
    00287                                 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
    00288                                 SDL_Palette *palette = format->palette;
    00289                                 SDL_Color *colors = palette->colors;
    00290                                 SDL_Color dColor = colors[*pixel];
    00291                                 SDL_Color sColor = colors[color];
    00292                                 Uint8 dR = dColor.r;
    00293                                 Uint8 dG = dColor.g;
    00294                                 Uint8 dB = dColor.b;
    00295                                 Uint8 sR = sColor.r;
    00296                                 Uint8 sG = sColor.g;
    00297                                 Uint8 sB = sColor.b;
    00298
    00299                                 dR = dR + ((sR - dR) * alpha >> 8);
    00300                                 dG = dG + ((sG - dG) * alpha >> 8);
    00301                                 dB = dB + ((sB - dB) * alpha >> 8);
    00302
    00303                                 *pixel = SDL_MapRGB(format, dR, dG, dB);
    00304                         }
    00305                 }
    00306                 break;
    00307
    00308         case 2:
    00309                 {               /* Probably 15-bpp or 16-bpp */
    00310                         if (alpha == 255) {
    00311                                 *((Uint16 *) dst->pixels + y * dst->pitch / 2 + x) = color;
    00312                         } else {
    00313                                 Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
    00314                                 Uint32 dc = *pixel;
    00315
    00316                                 Rmask = format->Rmask;
    00317                                 Gmask = format->Gmask;
    00318                                 Bmask = format->Bmask;
    00319                                 Amask = format->Amask;
    00320                                 R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
    00321                                 G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
    00322                                 B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
    00323                                 if (Amask) {
    00324                                         A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
    00325                                 }
    00326                                 *pixel = R | G | B | A;
    00327                         }
    00328                 }
    00329                 break;
    00330
    00331         case 3:
    00332                 {               /* Slow 24-bpp mode, usually not used */
    00333                         Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
    00334                         Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
    00335
    00336                         Rshift = format->Rshift;
    00337                         Gshift = format->Gshift;
    00338                         Bshift = format->Bshift;
    00339                         Ashift = format->Ashift;
    00340
    00341                         Rshift8 = Rshift / 8;
    00342                         Gshift8 = Gshift / 8;
    00343                         Bshift8 = Bshift / 8;
    00344                         Ashift8 = Ashift / 8;
    00345
    00346                         if (alpha == 255) {
    00347                                 *(pixel + Rshift8) = color >> Rshift;
    00348                                 *(pixel + Gshift8) = color >> Gshift;
    00349                                 *(pixel + Bshift8) = color >> Bshift;
    00350                                 *(pixel + Ashift8) = color >> Ashift;
    00351                         } else {
    00352                                 Uint8 dR, dG, dB, dA = 0;
    00353                                 Uint8 sR, sG, sB, sA = 0;
    00354
    00355                                 dR = *((pixel) + Rshift8);
    00356                                 dG = *((pixel) + Gshift8);
    00357                                 dB = *((pixel) + Bshift8);
    00358                                 dA = *((pixel) + Ashift8);
    00359
    00360                                 sR = (color >> Rshift) & 0xff;
    00361                                 sG = (color >> Gshift) & 0xff;
    00362                                 sB = (color >> Bshift) & 0xff;
    00363                                 sA = (color >> Ashift) & 0xff;
    00364
    00365                                 dR = dR + ((sR - dR) * alpha >> 8);
    00366                                 dG = dG + ((sG - dG) * alpha >> 8);
    00367                                 dB = dB + ((sB - dB) * alpha >> 8);
    00368                                 dA = dA + ((sA - dA) * alpha >> 8);
    00369
    00370                                 *((pixel) + Rshift8) = dR;
    00371                                 *((pixel) + Gshift8) = dG;
    00372                                 *((pixel) + Bshift8) = dB;
    00373                                 *((pixel) + Ashift8) = dA;
    00374                         }
    00375                 }
    00376                 break;
    00377
    00378 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
    00379
    00380         case 4:
    00381                 {               /* Probably :-) 32-bpp */
    00382                         if (alpha == 255) {
    00383                                 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
    00384                         } else {
    00385                                 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
    00386                                 Uint32 dc = *pixel;
    00387
    00388                                 Rmask = format->Rmask;
    00389                                 Gmask = format->Gmask;
    00390                                 Bmask = format->Bmask;
    00391                                 Amask = format->Amask;
    00392
    00393                                 Rshift = format->Rshift;
    00394                                 Gshift = format->Gshift;
    00395                                 Bshift = format->Bshift;
    00396                                 Ashift = format->Ashift;
    00397
    00398                                 A = 0;
    00399                                 R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
    00400                                 G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
    00401                                 B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
    00402                                 if (Amask) {
    00403                                         A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
    00404                                 }
    00405                                 *pixel = R | G | B | A;
    00406                         }
    00407                 }
    00408                 break;
    00409 #endif
    00410
    00411 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
    00412
    00413         case 4:{                /* Probably :-) 32-bpp */
    00414                 if (alpha == 255) {
    00415                         *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
    00416                 } else {
    00417                         Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
    00418                         Uint32 dR, dG, dB, dA;
    00419                         Uint32 dc = *pixel;
    00420
    00421                         Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
    00422                         Uint32 aTmp;
    00423
    00424                         Rmask = format->Rmask;
    00425                         Gmask = format->Gmask;
    00426                         Bmask = format->Bmask;
    00427                         Amask = format->Amask;
    00428
    00429                         dR = (color & Rmask);
    00430                         dG = (color & Gmask);
    00431                         dB = (color & Bmask);
    00432                         dA = (color & Amask);
    00433
    00434                         Rshift = format->Rshift;
    00435                         Gshift = format->Gshift;
    00436                         Bshift = format->Bshift;
    00437                         Ashift = format->Ashift;
    00438
    00439                         preMultR = (alpha * (dR >> Rshift));
    00440                         preMultG = (alpha * (dG >> Gshift));
    00441                         preMultB = (alpha * (dB >> Bshift));
    00442
    00443                         surfaceAlpha = ((dc & Amask) >> Ashift);
    00444                         aTmp = (255 - alpha);
    00445                         if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
    00446                                 aTmp *= surfaceAlpha;
    00447                                 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
    00448                                 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
    00449                                 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
    00450                         }
    00451                         *pixel = R | G | B | (A << Ashift & Amask);
    00452
    00453                 }
    00454                    }
    00455                    break;
    00456 #endif
    00457                 }
    00458         }
    00459
    00460         return (0);
    00461 }
    00462
    00473 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
    00474 {
    00475         Uint8 alpha;
    00476         Uint32 mcolor;
    00477         int result = 0;
    00478
    00479         /*
    00480         * Lock the surface
    00481         */
    00482         if (SDL_MUSTLOCK(dst)) {
    00483                 if (SDL_LockSurface(dst) < 0) {
    00484                         return (-1);
    00485                 }
    00486         }
    00487
    00488         /*
    00489         * Setup color
    00490         */
    00491         alpha = color & 0x000000ff;
    00492         mcolor =
    00493                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
    00494                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
    00495
    00496         /*
    00497         * Draw
    00498         */
    00499         result = _putPixelAlpha(dst, x, y, mcolor, alpha);
    00500
    00501         /*
    00502         * Unlock the surface
    00503         */
    00504         if (SDL_MUSTLOCK(dst)) {
    00505                 SDL_UnlockSurface(dst);
    00506         }
    00507
    00508         return (result);
    00509 }
    00510
    00521 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
    00522 {
    00523         Uint8 alpha;
    00524         Uint32 mcolor;
    00525         int result = 0;
    00526
    00527         /*
    00528         * Setup color
    00529         */
    00530         alpha = color & 0x000000ff;
    00531         mcolor =
    00532                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
    00533                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
    00534
    00535         /*
    00536         * Draw
    00537         */
    00538         result = _putPixelAlpha(dst, x, y, mcolor, alpha);
    00539
    00540         return (result);
    00541 }
    00542
    00543
    00559 int _filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
    00560 {
    00561         SDL_PixelFormat *format;
    00562         Uint32 Rmask, Bmask, Gmask, Amask;
    00563         Uint32 Rshift, Bshift, Gshift, Ashift;
    00564         Uint8 sR, sG, sB, sA;
    00565         Uint32 R, G, B, A;
    00566         Sint16 x, y;
    00567
    00568         format = dst->format;
    00569         switch (format->BytesPerPixel) {
    00570         case 1:
    00571                 {                       /* Assuming 8-bpp */
    00572                         Uint8 *row, *pixel;
    00573                         Uint8 dR, dG, dB;
    00574                         SDL_Palette *palette = format->palette;
    00575                         SDL_Color *colors = palette->colors;
    00576                         sR = colors[color].r;
    00577                         sG = colors[color].g;
    00578                         sB = colors[color].b;
    00579
    00580                         for (y = y1; y <= y2; y++) {
    00581                                 row = (Uint8 *) dst->pixels + y * dst->pitch;
    00582                                 for (x = x1; x <= x2; x++) {
    00583                                         pixel = row + x;
    00584
    00585                                         dR = colors[*pixel].r;
    00586                                         dG = colors[*pixel].g;
    00587                                         dB = colors[*pixel].b;
    00588
    00589                                         dR = dR + ((sR - dR) * alpha >> 8);
    00590                                         dG = dG + ((sG - dG) * alpha >> 8);
    00591                                         dB = dB + ((sB - dB) * alpha >> 8);
    00592
    00593                                         *pixel = SDL_MapRGB(format, dR, dG, dB);
    00594                                 }
    00595                         }
    00596                 }
    00597                 break;
    00598
    00599         case 2:
    00600                 {                       /* Probably 15-bpp or 16-bpp */
    00601                         Uint16 *row, *pixel;
    00602                         Uint32 dR, dG, dB, dA;
    00603                         Rmask = format->Rmask;
    00604                         Gmask = format->Gmask;
    00605                         Bmask = format->Bmask;
    00606                         Amask = format->Amask;
    00607
    00608                         dR = (color & Rmask);
    00609                         dG = (color & Gmask);
    00610                         dB = (color & Bmask);
    00611                         dA = (color & Amask);
    00612
    00613                         A = 0;
    00614
    00615                         for (y = y1; y <= y2; y++) {
    00616                                 row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
    00617                                 for (x = x1; x <= x2; x++) {
    00618                                         pixel = row + x;
    00619
    00620                                         R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
    00621                                         G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
    00622                                         B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
    00623                                         if (Amask)
    00624                                         {
    00625                                                 A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
    00626                                                 *pixel = R | G | B | A;
    00627                                         } else {
    00628                                                 *pixel = R | G | B;
    00629                                         }
    00630                                 }
    00631                         }
    00632                 }
    00633                 break;
    00634
    00635         case 3:
    00636                 {                       /* Slow 24-bpp mode, usually not used */
    00637                         Uint8 *row, *pix;
    00638                         Uint8 dR, dG, dB, dA;
    00639                         Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
    00640
    00641                         Rshift = format->Rshift;
    00642                         Gshift = format->Gshift;
    00643                         Bshift = format->Bshift;
    00644                         Ashift = format->Ashift;
    00645
    00646                         Rshift8 = Rshift / 8;
    00647                         Gshift8 = Gshift / 8;
    00648                         Bshift8 = Bshift / 8;
    00649                         Ashift8 = Ashift / 8;
    00650
    00651                         sR = (color >> Rshift) & 0xff;
    00652                         sG = (color >> Gshift) & 0xff;
    00653                         sB = (color >> Bshift) & 0xff;
    00654                         sA = (color >> Ashift) & 0xff;
    00655
    00656                         for (y = y1; y <= y2; y++) {
    00657                                 row = (Uint8 *) dst->pixels + y * dst->pitch;
    00658                                 for (x = x1; x <= x2; x++) {
    00659                                         pix = row + x * 3;
    00660
    00661                                         dR = *((pix) + Rshift8);
    00662                                         dG = *((pix) + Gshift8);
    00663                                         dB = *((pix) + Bshift8);
    00664                                         dA = *((pix) + Ashift8);
    00665
    00666                                         dR = dR + ((sR - dR) * alpha >> 8);
    00667                                         dG = dG + ((sG - dG) * alpha >> 8);
    00668                                         dB = dB + ((sB - dB) * alpha >> 8);
    00669                                         dA = dA + ((sA - dA) * alpha >> 8);
    00670
    00671                                         *((pix) + Rshift8) = dR;
    00672                                         *((pix) + Gshift8) = dG;
    00673                                         *((pix) + Bshift8) = dB;
    00674                                         *((pix) + Ashift8) = dA;
    00675                                 }
    00676                         }
    00677                 }
    00678                 break;
    00679
    00680 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
    00681         case 4:
    00682                 {                       /* Probably :-) 32-bpp */
    00683                         Uint32 *row, *pixel;
    00684                         Uint32 dR, dG, dB, dA;
    00685
    00686                         Rmask = format->Rmask;
    00687                         Gmask = format->Gmask;
    00688                         Bmask = format->Bmask;
    00689                         Amask = format->Amask;
    00690
    00691                         Rshift = format->Rshift;
    00692                         Gshift = format->Gshift;
    00693                         Bshift = format->Bshift;
    00694                         Ashift = format->Ashift;
    00695
    00696                         dR = (color & Rmask);
    00697                         dG = (color & Gmask);
    00698                         dB = (color & Bmask);
    00699                         dA = (color & Amask);
    00700
    00701                         for (y = y1; y <= y2; y++) {
    00702                                 row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
    00703                                 for (x = x1; x <= x2; x++) {
    00704                                         pixel = row + x;
    00705
    00706                                         R = ((*pixel & Rmask) + ((((dR - (*pixel & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
    00707                                         G = ((*pixel & Gmask) + ((((dG - (*pixel & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
    00708                                         B = ((*pixel & Bmask) + ((((dB - (*pixel & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
    00709                                         if (Amask)
    00710                                         {
    00711                                                 A = ((*pixel & Amask) + ((((dA - (*pixel & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
    00712                                                 *pixel = R | G | B | A;
    00713                                         } else {
    00714                                                 *pixel = R | G | B;
    00715                                         }
    00716                                 }
    00717                         }
    00718                 }
    00719                 break;
    00720 #endif
    00721
    00722 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
    00723         case 4:{                        /* Probably :-) 32-bpp */
    00724                 Uint32 *row, *pixel;
    00725                 Uint32 dR, dG, dB, dA;
    00726                 Uint32 dc;
    00727                 Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
    00728                 Uint32 aTmp;
    00729
    00730                 Rmask = format->Rmask;
    00731                 Gmask = format->Gmask;
    00732                 Bmask = format->Bmask;
    00733                 Amask = format->Amask;
    00734
    00735                 dR = (color & Rmask);
    00736                 dG = (color & Gmask);
    00737                 dB = (color & Bmask);
    00738                 dA = (color & Amask);
    00739
    00740                 Rshift = format->Rshift;
    00741                 Gshift = format->Gshift;
    00742                 Bshift = format->Bshift;
    00743                 Ashift = format->Ashift;
    00744
    00745                 preMultR = (alpha * (dR >> Rshift));
    00746                 preMultG = (alpha * (dG >> Gshift));
    00747                 preMultB = (alpha * (dB >> Bshift));
    00748
    00749                 for (y = y1; y <= y2; y++) {
    00750                         row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
    00751                         for (x = x1; x <= x2; x++) {
    00752                                 pixel = row + x;
    00753                                 dc = *pixel;
    00754
    00755                                 surfaceAlpha = ((dc & Amask) >> Ashift);
    00756                                 aTmp = (255 - alpha);
    00757                                 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
    00758                                         aTmp *= surfaceAlpha;
    00759                                         R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
    00760                                         G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
    00761                                         B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
    00762                                 }
    00763                                 *pixel = R | G | B | (A << Ashift & Amask);
    00764
    00765                         }
    00766                 }
    00767                    }
    00768                    break;
    00769 #endif
    00770
    00771         }
    00772
    00773         return (0);
    00774 }
    00775
    00788 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00789 {
    00790         Uint8 alpha;
    00791         Uint32 mcolor;
    00792         int result = 0;
    00793
    00794         /*
    00795         * Lock the surface
    00796         */
    00797         if (SDL_MUSTLOCK(dst)) {
    00798                 if (SDL_LockSurface(dst) < 0) {
    00799                         return (-1);
    00800                 }
    00801         }
    00802
    00803         /*
    00804         * Setup color
    00805         */
    00806         alpha = color & 0x000000ff;
    00807         mcolor =
    00808                 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
    00809                 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
    00810
    00811         /*
    00812         * Draw
    00813         */
    00814         result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
    00815
    00816         /*
    00817         * Unlock the surface
    00818         */
    00819         if (SDL_MUSTLOCK(dst)) {
    00820                 SDL_UnlockSurface(dst);
    00821         }
    00822
    00823         return (result);
    00824 }
    00825
    00837 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
    00838 {
    00839         return (filledRectAlpha(dst, x1, y, x2, y, color));
    00840 }
    00841
    00853 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
    00854 {
    00855         return (filledRectAlpha(dst, x, y1, x, y2, color));
    00856 }
    00857
    00869 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
    00870 {
    00871         Uint32 a;
    00872
    00873         /*
    00874         * Get alpha
    00875         */
    00876         a = (color & (Uint32) 0x000000ff);
    00877
    00878         /*
    00879         * Modify Alpha by weight
    00880         */
    00881         a = ((a * weight) >> 8);
    00882
    00883         return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
    00884 }
    00885
    00897 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
    00898 {
    00899         Uint32 a;
    00900
    00901         /*
    00902         * Get alpha
    00903         */
    00904         a = (color & (Uint32) 0x000000ff);
    00905
    00906         /*
    00907         * Modify Alpha by weight
    00908         */
    00909         a = ((a * weight) >> 8);
    00910
    00911         return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
    00912 }
    00913
    00927 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00928 {
    00929         Uint32 color;
    00930
    00931         /*
    00932         * Check Alpha
    00933         */
    00934         if (a == 255) {
    00935                 /*
    00936                 * No alpha blending required
    00937                 */
    00938                 /*
    00939                 * Setup color
    00940                 */
    00941                 color = SDL_MapRGBA(dst->format, r, g, b, a);
    00942                 /*
    00943                 * Draw
    00944                 */
    00945                 return (fastPixelColor(dst, x, y, color));
    00946         } else {
    00947                 /*
    00948                 * Alpha blending required
    00949                 */
    00950                 /*
    00951                 * Draw
    00952                 */
    00953                 return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    00954         }
    00955 }
    00956
    00957
    00973 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
    00974 {
    00975         Sint16 left, right, top, bottom;
    00976         Uint8 *pixel, *pixellast;
    00977         int dx;
    00978         int pixx, pixy;
    00979         Sint16 w;
    00980         Sint16 xtmp;
    00981         int result = -1;
    00982
    00983         /*
    00984         * Check visibility of clipping rectangle
    00985         */
    00986         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    00987                 return(0);
    00988         }
    00989
    00990         /*
    00991         * Swap x1, x2 if required to ensure x1<=x2
    00992         */
    00993         if (x1 > x2) {
    00994                 xtmp = x1;
    00995                 x1 = x2;
    00996                 x2 = xtmp;
    00997         }
    00998
    00999         /*
    01000         * Get clipping boundary and
    01001         * check visibility of hline
    01002         */
    01003         left = dst->clip_rect.x;
    01004         if (x2<left) {
    01005                 return(0);
    01006         }
    01007         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    01008         if (x1>right) {
    01009                 return(0);
    01010         }
    01011         top = dst->clip_rect.y;
    01012         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    01013         if ((y<top) || (y>bottom)) {
    01014                 return (0);
    01015         }
    01016
    01017         /*
    01018         * Clip x
    01019         */
    01020         if (x1 < left) {
    01021                 x1 = left;
    01022         }
    01023         if (x2 > right) {
    01024                 x2 = right;
    01025         }
    01026
    01027         /*
    01028         * Calculate width
    01029         */
    01030         w = x2 - x1;
    01031
    01032         /*
    01033         * Lock the surface
    01034         */
    01035         if (SDL_MUSTLOCK(dst)) {
    01036                 if (SDL_LockSurface(dst) < 0) {
    01037                         return (-1);
    01038                 }
    01039         }
    01040
    01041         /*
    01042         * More variable setup
    01043         */
    01044         dx = w;
    01045         pixx = dst->format->BytesPerPixel;
    01046         pixy = dst->pitch;
    01047         pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
    01048
    01049         /*
    01050         * Draw
    01051         */
    01052         switch (dst->format->BytesPerPixel) {
    01053         case 1:
    01054                 memset(pixel, color, dx+1);
    01055                 break;
    01056         case 2:
    01057                 pixellast = pixel + dx + dx;
    01058                 for (; pixel <= pixellast; pixel += pixx) {
    01059                         *(Uint16 *) pixel = color;
    01060                 }
    01061                 break;
    01062         case 3:
    01063                 pixellast = pixel + dx + dx + dx;
    01064                 for (; pixel <= pixellast; pixel += pixx) {
    01065                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    01066                                 pixel[0] = (color >> 16) & 0xff;
    01067                                 pixel[1] = (color >> 8) & 0xff;
    01068                                 pixel[2] = color & 0xff;
    01069                         } else {
    01070                                 pixel[0] = color & 0xff;
    01071                                 pixel[1] = (color >> 8) & 0xff;
    01072                                 pixel[2] = (color >> 16) & 0xff;
    01073                         }
    01074                 }
    01075                 break;
    01076         default:                /* case 4 */
    01077                 dx = dx + dx;
    01078                 pixellast = pixel + dx + dx;
    01079                 for (; pixel <= pixellast; pixel += pixx) {
    01080                         *(Uint32 *) pixel = color;
    01081                 }
    01082                 break;
    01083         }
    01084
    01085         /*
    01086         * Unlock surface
    01087         */
    01088         if (SDL_MUSTLOCK(dst)) {
    01089                 SDL_UnlockSurface(dst);
    01090         }
    01091
    01092         /*
    01093         * Set result code
    01094         */
    01095         result = 0;
    01096
    01097         return (result);
    01098 }
    01099
    01117 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01118 {
    01119         /*
    01120         * Draw
    01121         */
    01122         return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01123 }
    01124
    01136 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
    01137 {
    01138         Sint16 left, right, top, bottom;
    01139         Uint8 *pixel, *pixellast;
    01140         int dx;
    01141         int pixx, pixy;
    01142         Sint16 xtmp;
    01143         int result = -1;
    01144         Uint8 *colorptr;
    01145         Uint8 color3[3];
    01146
    01147         /*
    01148         * Check visibility of clipping rectangle
    01149         */
    01150         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    01151                 return(0);
    01152         }
    01153
    01154         /*
    01155         * Swap x1, x2 if required to ensure x1<=x2
    01156         */
    01157         if (x1 > x2) {
    01158                 xtmp = x1;
    01159                 x1 = x2;
    01160                 x2 = xtmp;
    01161         }
    01162
    01163         /*
    01164         * Get clipping boundary and
    01165         * check visibility of hline
    01166         */
    01167         left = dst->clip_rect.x;
    01168         if (x2<left) {
    01169                 return(0);
    01170         }
    01171         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    01172         if (x1>right) {
    01173                 return(0);
    01174         }
    01175         top = dst->clip_rect.y;
    01176         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    01177         if ((y<top) || (y>bottom)) {
    01178                 return (0);
    01179         }
    01180
    01181         /*
    01182         * Clip x
    01183         */
    01184         if (x1 < left) {
    01185                 x1 = left;
    01186         }
    01187         if (x2 > right) {
    01188                 x2 = right;
    01189         }
    01190
    01191         /*
    01192         * Calculate width difference
    01193         */
    01194         dx = x2 - x1;
    01195
    01196         /*
    01197         * Alpha check
    01198         */
    01199         if ((color & 255) == 255) {
    01200
    01201                 /*
    01202                 * No alpha-blending required
    01203                 */
    01204
    01205                 /*
    01206                 * Setup color
    01207                 */
    01208                 colorptr = (Uint8 *) & color;
    01209                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    01210                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    01211                 } else {
    01212                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    01213                 }
    01214
    01215                 /*
    01216                 * Lock the surface
    01217                 */
    01218                 if (SDL_MUSTLOCK(dst)) {
    01219                         if (SDL_LockSurface(dst) < 0) {
    01220                                 return (-1);
    01221                         }
    01222                 }
    01223
    01224                 /*
    01225                 * More variable setup
    01226                 */
    01227                 pixx = dst->format->BytesPerPixel;
    01228                 pixy = dst->pitch;
    01229                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
    01230
    01231                 /*
    01232                 * Draw
    01233                 */
    01234                 switch (dst->format->BytesPerPixel) {
    01235         case 1:
    01236                 memset(pixel, color, dx + 1);
    01237                 break;
    01238         case 2:
    01239                 pixellast = pixel + dx + dx;
    01240                 for (; pixel <= pixellast; pixel += pixx) {
    01241                         *(Uint16 *) pixel = color;
    01242                 }
    01243                 break;
    01244         case 3:
    01245                 pixellast = pixel + dx + dx + dx;
    01246                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    01247                         color3[0] = (color >> 16) & 0xff;
    01248                         color3[1] = (color >> 8) & 0xff;
    01249                         color3[2] = color & 0xff;
    01250                 } else {
    01251                         color3[0] = color & 0xff;
    01252                         color3[1] = (color >> 8) & 0xff;
    01253                         color3[2] = (color >> 16) & 0xff;
    01254                 }
    01255                 for (; pixel <= pixellast; pixel += pixx) {
    01256                         memcpy(pixel, color3, 3);
    01257                 }
    01258                 break;
    01259         default:                /* case 4 */
    01260                 dx = dx + dx;
    01261                 pixellast = pixel + dx + dx;
    01262                 for (; pixel <= pixellast; pixel += pixx) {
    01263                         *(Uint32 *) pixel = color;
    01264                 }
    01265                 break;
    01266                 }
    01267
    01268                 /*
    01269                 * Unlock surface
    01270                 */
    01271                 if (SDL_MUSTLOCK(dst)) {
    01272                         SDL_UnlockSurface(dst);
    01273                 }
    01274
    01275                 /*
    01276                 * Set result code
    01277                 */
    01278                 result = 0;
    01279
    01280         } else {
    01281
    01282                 /*
    01283                 * Alpha blending blit
    01284                 */
    01285                 result = _HLineAlpha(dst, x1, x1 + dx, y, color);
    01286         }
    01287
    01288         return (result);
    01289 }
    01290
    01305 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01306 {
    01307         /*
    01308         * Draw
    01309         */
    01310         return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01311 }
    01312
    01324 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
    01325 {
    01326         Sint16 left, right, top, bottom;
    01327         Uint8 *pixel, *pixellast;
    01328         int dy;
    01329         int pixx, pixy;
    01330         Sint16 h;
    01331         Sint16 ytmp;
    01332         int result = -1;
    01333         Uint8 *colorptr;
    01334
    01335         /*
    01336         * Check visibility of clipping rectangle
    01337         */
    01338         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    01339                 return(0);
    01340         }
    01341
    01342         /*
    01343         * Swap y1, y2 if required to ensure y1<=y2
    01344         */
    01345         if (y1 > y2) {
    01346                 ytmp = y1;
    01347                 y1 = y2;
    01348                 y2 = ytmp;
    01349         }
    01350
    01351         /*
    01352         * Get clipping boundary and
    01353         * check visibility of vline
    01354         */
    01355         left = dst->clip_rect.x;
    01356         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    01357         if ((x<left) || (x>right)) {
    01358                 return (0);
    01359         }
    01360         top = dst->clip_rect.y;
    01361         if (y2<top) {
    01362                 return(0);
    01363         }
    01364         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    01365         if (y1>bottom) {
    01366                 return(0);
    01367         }
    01368
    01369         /*
    01370         * Clip x
    01371         */
    01372         if (y1 < top) {
    01373                 y1 = top;
    01374         }
    01375         if (y2 > bottom) {
    01376                 y2 = bottom;
    01377         }
    01378
    01379         /*
    01380         * Calculate height
    01381         */
    01382         h = y2 - y1;
    01383
    01384         /*
    01385         * Alpha check
    01386         */
    01387         if ((color & 255) == 255) {
    01388
    01389                 /*
    01390                 * No alpha-blending required
    01391                 */
    01392
    01393                 /*
    01394                 * Setup color
    01395                 */
    01396                 colorptr = (Uint8 *) & color;
    01397                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    01398                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    01399                 } else {
    01400                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    01401                 }
    01402
    01403                 /*
    01404                 * Lock the surface
    01405                 */
    01406                 if (SDL_MUSTLOCK(dst)) {
    01407                         if (SDL_LockSurface(dst) < 0) {
    01408                                 return (-1);
    01409                         }
    01410                 }
    01411
    01412                 /*
    01413                 * More variable setup
    01414                 */
    01415                 dy = h;
    01416                 pixx = dst->format->BytesPerPixel;
    01417                 pixy = dst->pitch;
    01418                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
    01419                 pixellast = pixel + pixy * dy;
    01420
    01421                 /*
    01422                 * Draw
    01423                 */
    01424                 switch (dst->format->BytesPerPixel) {
    01425         case 1:
    01426                 for (; pixel <= pixellast; pixel += pixy) {
    01427                         *(Uint8 *) pixel = color;
    01428                 }
    01429                 break;
    01430         case 2:
    01431                 for (; pixel <= pixellast; pixel += pixy) {
    01432                         *(Uint16 *) pixel = color;
    01433                 }
    01434                 break;
    01435         case 3:
    01436                 for (; pixel <= pixellast; pixel += pixy) {
    01437                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    01438                                 pixel[0] = (color >> 16) & 0xff;
    01439                                 pixel[1] = (color >> 8) & 0xff;
    01440                                 pixel[2] = color & 0xff;
    01441                         } else {
    01442                                 pixel[0] = color & 0xff;
    01443                                 pixel[1] = (color >> 8) & 0xff;
    01444                                 pixel[2] = (color >> 16) & 0xff;
    01445                         }
    01446                 }
    01447                 break;
    01448         default:                /* case 4 */
    01449                 for (; pixel <= pixellast; pixel += pixy) {
    01450                         *(Uint32 *) pixel = color;
    01451                 }
    01452                 break;
    01453                 }
    01454
    01455                 /* Unlock surface */
    01456                 if (SDL_MUSTLOCK(dst)) {
    01457                         SDL_UnlockSurface(dst);
    01458                 }
    01459
    01460                 /*
    01461                 * Set result code
    01462                 */
    01463                 result = 0;
    01464
    01465         } else {
    01466
    01467                 /*
    01468                 * Alpha blending blit
    01469                 */
    01470
    01471                 result = _VLineAlpha(dst, x, y1, y1 + h, color);
    01472
    01473         }
    01474
    01475         return (result);
    01476 }
    01477
    01492 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01493 {
    01494         /*
    01495         * Draw
    01496         */
    01497         return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01498 }
    01499
    01512 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    01513 {
    01514         int result;
    01515         Sint16 tmp;
    01516
    01517         /* Check destination surface */
    01518         if (dst == NULL)
    01519         {
    01520                 return -1;
    01521         }
    01522
    01523         /*
    01524         * Check visibility of clipping rectangle
    01525         */
    01526         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    01527                 return 0;
    01528         }
    01529
    01530         /*
    01531         * Test for special cases of straight lines or single point
    01532         */
    01533         if (x1 == x2) {
    01534                 if (y1 == y2) {
    01535                         return (pixelColor(dst, x1, y1, color));
    01536                 } else {
    01537                         return (vlineColor(dst, x1, y1, y2, color));
    01538                 }
    01539         } else {
    01540                 if (y1 == y2) {
    01541                         return (hlineColor(dst, x1, x2, y1, color));
    01542                 }
    01543         }
    01544
    01545         /*
    01546         * Swap x1, x2 if required
    01547         */
    01548         if (x1 > x2) {
    01549                 tmp = x1;
    01550                 x1 = x2;
    01551                 x2 = tmp;
    01552         }
    01553
    01554         /*
    01555         * Swap y1, y2 if required
    01556         */
    01557         if (y1 > y2) {
    01558                 tmp = y1;
    01559                 y1 = y2;
    01560                 y2 = tmp;
    01561         }
    01562
    01563         /*
    01564         * Draw rectangle
    01565         */
    01566         result = 0;
    01567         result |= hlineColor(dst, x1, x2, y1, color);
    01568         result |= hlineColor(dst, x1, x2, y2, color);
    01569         y1 += 1;
    01570         y2 -= 1;
    01571         if (y1 <= y2) {
    01572                 result |= vlineColor(dst, x1, y1, y2, color);
    01573                 result |= vlineColor(dst, x2, y1, y2, color);
    01574         }
    01575
    01576         return (result);
    01577
    01578 }
    01579
    01595 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01596 {
    01597         /*
    01598         * Draw
    01599         */
    01600         return (rectangleColor
    01601                 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01602 }
    01603
    01617 int roundedRectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
    01618 {
    01619         int result;
    01620         Sint16 w, h, tmp;
    01621         Sint16 xx1, xx2, yy1, yy2;
    01622
    01623         /*
    01624         * Check destination surface
    01625         */
    01626         if (dst == NULL)
    01627         {
    01628                 return -1;
    01629         }
    01630
    01631         /*
    01632         * Check radius vor valid range
    01633         */
    01634         if (rad < 0) {
    01635                 return -1;
    01636         }
    01637
    01638         /*
    01639         * Special case - no rounding
    01640         */
    01641         if (rad == 0) {
    01642                 return rectangleColor(dst, x1, y1, x2, y2, color);
    01643         }
    01644
    01645         /*
    01646         * Check visibility of clipping rectangle
    01647         */
    01648         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    01649                 return 0;
    01650         }
    01651
    01652         /*
    01653         * Test for special cases of straight lines or single point
    01654         */
    01655         if (x1 == x2) {
    01656                 if (y1 == y2) {
    01657                         return (pixelColor(dst, x1, y1, color));
    01658                 } else {
    01659                         return (vlineColor(dst, x1, y1, y2, color));
    01660                 }
    01661         } else {
    01662                 if (y1 == y2) {
    01663                         return (hlineColor(dst, x1, x2, y1, color));
    01664                 }
    01665         }
    01666
    01667         /*
    01668         * Swap x1, x2 if required
    01669         */
    01670         if (x1 > x2) {
    01671                 tmp = x1;
    01672                 x1 = x2;
    01673                 x2 = tmp;
    01674         }
    01675
    01676         /*
    01677         * Swap y1, y2 if required
    01678         */
    01679         if (y1 > y2) {
    01680                 tmp = y1;
    01681                 y1 = y2;
    01682                 y2 = tmp;
    01683         }
    01684
    01685         /*
    01686         * Calculate width&height
    01687         */
    01688         w = x2 - x1;
    01689         h = y2 - y1;
    01690
    01691         /*
    01692         * Maybe adjust radius
    01693         */
    01694         if ((rad * 2) > w)
    01695         {
    01696                 rad = w / 2;
    01697         }
    01698         if ((rad * 2) > h)
    01699         {
    01700                 rad = h / 2;
    01701         }
    01702
    01703         /*
    01704         * Draw corners
    01705         */
    01706         result = 0;
    01707         xx1 = x1 + rad;
    01708         xx2 = x2 - rad;
    01709         yy1 = y1 + rad;
    01710         yy2 = y2 - rad;
    01711         result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
    01712         result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
    01713         result |= arcColor(dst, xx1, yy2, rad,  90, 180, color);
    01714         result |= arcColor(dst, xx2, yy2, rad,   0,  90, color);
    01715
    01716         /*
    01717         * Draw lines
    01718         */
    01719         if (xx1 <= xx2) {
    01720                 result |= hlineColor(dst, xx1, xx2, y1, color);
    01721                 result |= hlineColor(dst, xx1, xx2, y2, color);
    01722         }
    01723         if (yy1 <= yy2) {
    01724                 result |= vlineColor(dst, x1, yy1, yy2, color);
    01725                 result |= vlineColor(dst, x2, yy1, yy2, color);
    01726         }
    01727
    01728         return result;
    01729 }
    01730
    01747 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01748 {
    01749         /*
    01750         * Draw
    01751         */
    01752         return (roundedRectangleColor
    01753                 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01754 }
    01755
    01769 int roundedBoxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
    01770 {
    01771         int result;
    01772         Sint16 w, h, tmp;
    01773         Sint16 xx1, xx2, yy1, yy2;
    01774
    01775         /*
    01776         * Check destination surface
    01777         */
    01778         if (dst == NULL)
    01779         {
    01780                 return -1;
    01781         }
    01782
    01783         /*
    01784         * Check radius vor valid range
    01785         */
    01786         if (rad < 0) {
    01787                 return -1;
    01788         }
    01789
    01790         /*
    01791         * Special case - no rounding
    01792         */
    01793         if (rad == 0) {
    01794                 return rectangleColor(dst, x1, y1, x2, y2, color);
    01795         }
    01796
    01797         /*
    01798         * Check visibility of clipping rectangle
    01799         */
    01800         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    01801                 return 0;
    01802         }
    01803
    01804         /*
    01805         * Test for special cases of straight lines or single point
    01806         */
    01807         if (x1 == x2) {
    01808                 if (y1 == y2) {
    01809                         return (pixelColor(dst, x1, y1, color));
    01810                 } else {
    01811                         return (vlineColor(dst, x1, y1, y2, color));
    01812                 }
    01813         } else {
    01814                 if (y1 == y2) {
    01815                         return (hlineColor(dst, x1, x2, y1, color));
    01816                 }
    01817         }
    01818
    01819         /*
    01820         * Swap x1, x2 if required
    01821         */
    01822         if (x1 > x2) {
    01823                 tmp = x1;
    01824                 x1 = x2;
    01825                 x2 = tmp;
    01826         }
    01827
    01828         /*
    01829         * Swap y1, y2 if required
    01830         */
    01831         if (y1 > y2) {
    01832                 tmp = y1;
    01833                 y1 = y2;
    01834                 y2 = tmp;
    01835         }
    01836
    01837         /*
    01838         * Calculate width&height
    01839         */
    01840         w = x2 - x1;
    01841         h = y2 - y1;
    01842
    01843         /*
    01844         * Maybe adjust radius
    01845         */
    01846         if ((rad * 2) > w)
    01847         {
    01848                 rad = w / 2;
    01849         }
    01850         if ((rad * 2) > h)
    01851         {
    01852                 rad = h / 2;
    01853         }
    01854
    01855         /*
    01856         * Draw corners
    01857         */
    01858         result = 0;
    01859         xx1 = x1 + rad;
    01860         xx2 = x2 - rad;
    01861         yy1 = y1 + rad;
    01862         yy2 = y2 - rad;
    01863         result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
    01864         result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
    01865         result |= filledPieColor(dst, xx1, yy2, rad,  90, 180, color);
    01866         result |= filledPieColor(dst, xx2, yy2, rad,   0,  90, color);
    01867
    01868         /*
    01869         * Draw body
    01870         */
    01871         xx1++;
    01872         xx2--;
    01873         yy1++;
    01874         yy2--;
    01875         if (xx1 <= xx2) {
    01876                 result |= boxColor(dst, xx1, y1, xx2, y2, color);
    01877         }
    01878         if (yy1 <= yy2) {
    01879                 result |= boxColor(dst, x1, yy1, xx1-1, yy2, color);
    01880                 result |= boxColor(dst, xx2+1, yy1, x2, yy2, color);
    01881         }
    01882
    01883         return result;
    01884 }
    01885
    01902 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,
    01903                                    Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01904 {
    01905         /*
    01906         * Draw
    01907         */
    01908         return (roundedBoxColor
    01909                 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    01910 }
    01911
    01912 /* --------- Clipping routines for line */
    01913
    01914 /* Clipping based heavily on code from                       */
    01915 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
    01916
    01917 #define CLIP_LEFT_EDGE   0x1
    01918 #define CLIP_RIGHT_EDGE  0x2
    01919 #define CLIP_BOTTOM_EDGE 0x4
    01920 #define CLIP_TOP_EDGE    0x8
    01921 #define CLIP_INSIDE(a)   (!a)
    01922 #define CLIP_REJECT(a,b) (a&b)
    01923 #define CLIP_ACCEPT(a,b) (!(a|b))
    01924
    01937 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
    01938 {
    01939         int code = 0;
    01940
    01941         if (x < left) {
    01942                 code |= CLIP_LEFT_EDGE;
    01943         } else if (x > right) {
    01944                 code |= CLIP_RIGHT_EDGE;
    01945         }
    01946         if (y < top) {
    01947                 code |= CLIP_TOP_EDGE;
    01948         } else if (y > bottom) {
    01949                 code |= CLIP_BOTTOM_EDGE;
    01950         }
    01951         return code;
    01952 }
    01953
    01963 static int _clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
    01964 {
    01965         Sint16 left, right, top, bottom;
    01966         int code1, code2;
    01967         int draw = 0;
    01968         Sint16 swaptmp;
    01969         float m;
    01970
    01971         /*
    01972         * Get clipping boundary
    01973         */
    01974         left = dst->clip_rect.x;
    01975         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    01976         top = dst->clip_rect.y;
    01977         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    01978
    01979         while (1) {
    01980                 code1 = _clipEncode(*x1, *y1, left, top, right, bottom);
    01981                 code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
    01982                 if (CLIP_ACCEPT(code1, code2)) {
    01983                         draw = 1;
    01984                         break;
    01985                 } else if (CLIP_REJECT(code1, code2))
    01986                         break;
    01987                 else {
    01988                         if (CLIP_INSIDE(code1)) {
    01989                                 swaptmp = *x2;
    01990                                 *x2 = *x1;
    01991                                 *x1 = swaptmp;
    01992                                 swaptmp = *y2;
    01993                                 *y2 = *y1;
    01994                                 *y1 = swaptmp;
    01995                                 swaptmp = code2;
    01996                                 code2 = code1;
    01997                                 code1 = swaptmp;
    01998                         }
    01999                         if (*x2 != *x1) {
    02000                                 m = (*y2 - *y1) / (float) (*x2 - *x1);
    02001                         } else {
    02002                                 m = 1.0f;
    02003                         }
    02004                         if (code1 & CLIP_LEFT_EDGE) {
    02005                                 *y1 += (Sint16) ((left - *x1) * m);
    02006                                 *x1 = left;
    02007                         } else if (code1 & CLIP_RIGHT_EDGE) {
    02008                                 *y1 += (Sint16) ((right - *x1) * m);
    02009                                 *x1 = right;
    02010                         } else if (code1 & CLIP_BOTTOM_EDGE) {
    02011                                 if (*x2 != *x1) {
    02012                                         *x1 += (Sint16) ((bottom - *y1) / m);
    02013                                 }
    02014                                 *y1 = bottom;
    02015                         } else if (code1 & CLIP_TOP_EDGE) {
    02016                                 if (*x2 != *x1) {
    02017                                         *x1 += (Sint16) ((top - *y1) / m);
    02018                                 }
    02019                                 *y1 = top;
    02020                         }
    02021                 }
    02022         }
    02023
    02024         return draw;
    02025 }
    02026
    02039 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    02040 {
    02041         Sint16 left, right, top, bottom;
    02042         Uint8 *pixel, *pixellast;
    02043         int x, dx;
    02044         int dy;
    02045         int pixx, pixy;
    02046         Sint16 w, h, tmp;
    02047         int result;
    02048         Uint8 *colorptr;
    02049
    02050         /*
    02051         * Check visibility of clipping rectangle
    02052         */
    02053         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    02054                 return(0);
    02055         }
    02056
    02057         /*
    02058         * Order coordinates to ensure that
    02059         * x1<=x2 and y1<=y2
    02060         */
    02061         if (x1 > x2) {
    02062                 tmp = x1;
    02063                 x1 = x2;
    02064                 x2 = tmp;
    02065         }
    02066         if (y1 > y2) {
    02067                 tmp = y1;
    02068                 y1 = y2;
    02069                 y2 = tmp;
    02070         }
    02071
    02072         /*
    02073         * Get clipping boundary and
    02074         * check visibility
    02075         */
    02076         left = dst->clip_rect.x;
    02077         if (x2<left) {
    02078                 return(0);
    02079         }
    02080         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    02081         if (x1>right) {
    02082                 return(0);
    02083         }
    02084         top = dst->clip_rect.y;
    02085         if (y2<top) {
    02086                 return(0);
    02087         }
    02088         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    02089         if (y1>bottom) {
    02090                 return(0);
    02091         }
    02092
    02093         /* Clip all points */
    02094         if (x1<left) {
    02095                 x1=left;
    02096         } else if (x1>right) {
    02097                 x1=right;
    02098         }
    02099         if (x2<left) {
    02100                 x2=left;
    02101         } else if (x2>right) {
    02102                 x2=right;
    02103         }
    02104         if (y1<top) {
    02105                 y1=top;
    02106         } else if (y1>bottom) {
    02107                 y1=bottom;
    02108         }
    02109         if (y2<top) {
    02110                 y2=top;
    02111         } else if (y2>bottom) {
    02112                 y2=bottom;
    02113         }
    02114
    02115         /*
    02116         * Test for special cases of straight line or single point
    02117         */
    02118         if (x1 == x2) {
    02119                 if (y1 == y2) {
    02120                         return (pixelColor(dst, x1, y1, color));
    02121                 } else {
    02122                         return (vlineColor(dst, x1, y1, y2, color));
    02123                 }
    02124         }
    02125         if (y1 == y2) {
    02126                 return (hlineColor(dst, x1, x2, y1, color));
    02127         }
    02128
    02129         /*
    02130         * Calculate width&height
    02131         */
    02132         w = x2 - x1;
    02133         h = y2 - y1;
    02134
    02135         /*
    02136         * Alpha check
    02137         */
    02138         if ((color & 255) == 255) {
    02139
    02140                 /*
    02141                 * No alpha-blending required
    02142                 */
    02143
    02144                 /*
    02145                 * Setup color
    02146                 */
    02147                 colorptr = (Uint8 *) & color;
    02148                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    02149                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    02150                 } else {
    02151                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    02152                 }
    02153
    02154                 /*
    02155                 * Lock the surface
    02156                 */
    02157                 if (SDL_MUSTLOCK(dst)) {
    02158                         if (SDL_LockSurface(dst) < 0) {
    02159                                 return (-1);
    02160                         }
    02161                 }
    02162
    02163                 /*
    02164                 * More variable setup
    02165                 */
    02166                 dx = w;
    02167                 dy = h;
    02168                 pixx = dst->format->BytesPerPixel;
    02169                 pixy = dst->pitch;
    02170                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
    02171                 pixellast = pixel + pixx * dx + pixy * dy;
    02172                 dx++;
    02173
    02174                 /*
    02175                 * Draw
    02176                 */
    02177                 switch (dst->format->BytesPerPixel) {
    02178         case 1:
    02179                 for (; pixel <= pixellast; pixel += pixy) {
    02180                         memset(pixel, (Uint8) color, dx);
    02181                 }
    02182                 break;
    02183         case 2:
    02184                 pixy -= (pixx * dx);
    02185                 for (; pixel <= pixellast; pixel += pixy) {
    02186                         for (x = 0; x < dx; x++) {
    02187                                 *(Uint16*) pixel = color;
    02188                                 pixel += pixx;
    02189                         }
    02190                 }
    02191                 break;
    02192         case 3:
    02193                 pixy -= (pixx * dx);
    02194                 for (; pixel <= pixellast; pixel += pixy) {
    02195                         for (x = 0; x < dx; x++) {
    02196                                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    02197                                         pixel[0] = (color >> 16) & 0xff;
    02198                                         pixel[1] = (color >> 8) & 0xff;
    02199                                         pixel[2] = color & 0xff;
    02200                                 } else {
    02201                                         pixel[0] = color & 0xff;
    02202                                         pixel[1] = (color >> 8) & 0xff;
    02203                                         pixel[2] = (color >> 16) & 0xff;
    02204                                 }
    02205                                 pixel += pixx;
    02206                         }
    02207                 }
    02208                 break;
    02209         default:                /* case 4 */
    02210                 pixy -= (pixx * dx);
    02211                 for (; pixel <= pixellast; pixel += pixy) {
    02212                         for (x = 0; x < dx; x++) {
    02213                                 *(Uint32 *) pixel = color;
    02214                                 pixel += pixx;
    02215                         }
    02216                 }
    02217                 break;
    02218                 }
    02219
    02220                 /* Unlock surface */
    02221                 if (SDL_MUSTLOCK(dst)) {
    02222                         SDL_UnlockSurface(dst);
    02223                 }
    02224
    02225                 result = 0;
    02226
    02227         } else {
    02228
    02229                 result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
    02230
    02231         }
    02232
    02233         return (result);
    02234 }
    02235
    02251 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02252 {
    02253         /*
    02254         * Draw
    02255         */
    02256         return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    02257 }
    02258
    02259 /* ----- Line */
    02260
    02261 /* Non-alpha line drawing code adapted from routine          */
    02262 /* by Pete Shinners, pete@shinners.org                       */
    02263 /* Originally from pygame, http://pygame.seul.org            */
    02264
    02265 #define ABS(a) (((a)<0) ? -(a) : (a))
    02266
    02279 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    02280 {
    02281         int pixx, pixy;
    02282         int x, y;
    02283         int dx, dy;
    02284         int ax, ay;
    02285         int sx, sy;
    02286         int swaptmp;
    02287         Uint8 *pixel;
    02288         Uint8 *colorptr;
    02289
    02290         /*
    02291         * Clip line and test if we have to draw
    02292         */
    02293         if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
    02294                 return (0);
    02295         }
    02296
    02297         /*
    02298         * Test for special cases of straight lines or single point
    02299         */
    02300         if (x1 == x2) {
    02301                 if (y1 < y2) {
    02302                         return (vlineColor(dst, x1, y1, y2, color));
    02303                 } else if (y1 > y2) {
    02304                         return (vlineColor(dst, x1, y2, y1, color));
    02305                 } else {
    02306                         return (pixelColor(dst, x1, y1, color));
    02307                 }
    02308         }
    02309         if (y1 == y2) {
    02310                 if (x1 < x2) {
    02311                         return (hlineColor(dst, x1, x2, y1, color));
    02312                 } else if (x1 > x2) {
    02313                         return (hlineColor(dst, x2, x1, y1, color));
    02314                 }
    02315         }
    02316
    02317         /*
    02318         * Variable setup
    02319         */
    02320         dx = x2 - x1;
    02321         dy = y2 - y1;
    02322         sx = (dx >= 0) ? 1 : -1;
    02323         sy = (dy >= 0) ? 1 : -1;
    02324
    02325         /* Lock surface */
    02326         if (SDL_MUSTLOCK(dst)) {
    02327                 if (SDL_LockSurface(dst) < 0) {
    02328                         return (-1);
    02329                 }
    02330         }
    02331
    02332         /*
    02333         * Check for alpha blending
    02334         */
    02335         if ((color & 255) == 255) {
    02336
    02337                 /*
    02338                 * No alpha blending - use fast pixel routines
    02339                 */
    02340
    02341                 /*
    02342                 * Setup color
    02343                 */
    02344                 colorptr = (Uint8 *) & color;
    02345                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    02346                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    02347                 } else {
    02348                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    02349                 }
    02350
    02351                 /*
    02352                 * More variable setup
    02353                 */
    02354                 dx = sx * dx + 1;
    02355                 dy = sy * dy + 1;
    02356                 pixx = dst->format->BytesPerPixel;
    02357                 pixy = dst->pitch;
    02358                 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
    02359                 pixx *= sx;
    02360                 pixy *= sy;
    02361                 if (dx < dy) {
    02362                         swaptmp = dx;
    02363                         dx = dy;
    02364                         dy = swaptmp;
    02365                         swaptmp = pixx;
    02366                         pixx = pixy;
    02367                         pixy = swaptmp;
    02368                 }
    02369
    02370                 /*
    02371                 * Draw
    02372                 */
    02373                 x = 0;
    02374                 y = 0;
    02375                 switch (dst->format->BytesPerPixel) {
    02376         case 1:
    02377                 for (; x < dx; x++, pixel += pixx) {
    02378                         *pixel = color;
    02379                         y += dy;
    02380                         if (y >= dx) {
    02381                                 y -= dx;
    02382                                 pixel += pixy;
    02383                         }
    02384                 }
    02385                 break;
    02386         case 2:
    02387                 for (; x < dx; x++, pixel += pixx) {
    02388                         *(Uint16 *) pixel = color;
    02389                         y += dy;
    02390                         if (y >= dx) {
    02391                                 y -= dx;
    02392                                 pixel += pixy;
    02393                         }
    02394                 }
    02395                 break;
    02396         case 3:
    02397                 for (; x < dx; x++, pixel += pixx) {
    02398                         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    02399                                 pixel[0] = (color >> 16) & 0xff;
    02400                                 pixel[1] = (color >> 8) & 0xff;
    02401                                 pixel[2] = color & 0xff;
    02402                         } else {
    02403                                 pixel[0] = color & 0xff;
    02404                                 pixel[1] = (color >> 8) & 0xff;
    02405                                 pixel[2] = (color >> 16) & 0xff;
    02406                         }
    02407                         y += dy;
    02408                         if (y >= dx) {
    02409                                 y -= dx;
    02410                                 pixel += pixy;
    02411                         }
    02412                 }
    02413                 break;
    02414         default:                /* case 4 */
    02415                 for (; x < dx; x++, pixel += pixx) {
    02416                         *(Uint32 *) pixel = color;
    02417                         y += dy;
    02418                         if (y >= dx) {
    02419                                 y -= dx;
    02420                                 pixel += pixy;
    02421                         }
    02422                 }
    02423                 break;
    02424                 }
    02425
    02426         } else {
    02427
    02428                 /*
    02429                 * Alpha blending required - use single-pixel blits
    02430                 */
    02431
    02432                 ax = ABS(dx) << 1;
    02433                 ay = ABS(dy) << 1;
    02434                 x = x1;
    02435                 y = y1;
    02436                 if (ax > ay) {
    02437                         int d = ay - (ax >> 1);
    02438
    02439                         while (x != x2) {
    02440                                 pixelColorNolock (dst, x, y, color);
    02441                                 if (d > 0 || (d == 0 && sx == 1)) {
    02442                                         y += sy;
    02443                                         d -= ax;
    02444                                 }
    02445                                 x += sx;
    02446                                 d += ay;
    02447                         }
    02448                 } else {
    02449                         int d = ax - (ay >> 1);
    02450
    02451                         while (y != y2) {
    02452                                 pixelColorNolock (dst, x, y, color);
    02453                                 if (d > 0 || ((d == 0) && (sy == 1))) {
    02454                                         x += sx;
    02455                                         d -= ay;
    02456                                 }
    02457                                 y += sy;
    02458                                 d += ax;
    02459                         }
    02460                 }
    02461                 pixelColorNolock (dst, x, y, color);
    02462
    02463         }
    02464
    02465         /* Unlock surface */
    02466         if (SDL_MUSTLOCK(dst)) {
    02467                 SDL_UnlockSurface(dst);
    02468         }
    02469
    02470         return (0);
    02471 }
    02472
    02488 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02489 {
    02490         /*
    02491         * Draw
    02492         */
    02493         return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    02494 }
    02495
    02496 /* AA Line */
    02497
    02498 #define AAlevels 256
    02499 #define AAbits 8
    02500
    02521 int _aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
    02522 {
    02523         Sint32 xx0, yy0, xx1, yy1;
    02524         int result;
    02525         Uint32 intshift, erracc, erradj;
    02526         Uint32 erracctmp, wgt, wgtcompmask;
    02527         int dx, dy, tmp, xdir, y0p1, x0pxdir;
    02528
    02529         /*
    02530         * Check visibility of clipping rectangle
    02531         */
    02532         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    02533                 return(0);
    02534         }
    02535
    02536         /*
    02537         * Clip line and test if we have to draw
    02538         */
    02539         if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
    02540                 return (0);
    02541         }
    02542
    02543         /*
    02544         * Keep on working with 32bit numbers
    02545         */
    02546         xx0 = x1;
    02547         yy0 = y1;
    02548         xx1 = x2;
    02549         yy1 = y2;
    02550
    02551         /*
    02552         * Reorder points if required
    02553         */
    02554         if (yy0 > yy1) {
    02555                 tmp = yy0;
    02556                 yy0 = yy1;
    02557                 yy1 = tmp;
    02558                 tmp = xx0;
    02559                 xx0 = xx1;
    02560                 xx1 = tmp;
    02561         }
    02562
    02563         /*
    02564         * Calculate distance
    02565         */
    02566         dx = xx1 - xx0;
    02567         dy = yy1 - yy0;
    02568
    02569         /*
    02570         * Check for special cases
    02571         */
    02572         if (dx == 0) {
    02573                 /*
    02574                 * Vertical line
    02575                 */
    02576                 if (draw_endpoint)
    02577                 {
    02578                         return (vlineColor(dst, x1, y1, y2, color));
    02579                 } else {
    02580                         if (dy>0) {
    02581                                 return (vlineColor(dst, x1, yy0, yy0+dy, color));
    02582                         } else {
    02583                                 return (pixelColor(dst, x1, y1, color));
    02584                         }
    02585                 }
    02586         } else if (dy == 0) {
    02587                 /*
    02588                 * Horizontal line
    02589                 */
    02590                 if (draw_endpoint)
    02591                 {
    02592                         return (hlineColor(dst, x1, x2, y1, color));
    02593                 } else {
    02594                         if (dx>0) {
    02595                                 return (hlineColor(dst, xx0, xx0+dx, y1, color));
    02596                         } else {
    02597                                 return (pixelColor(dst, x1, y1, color));
    02598                         }
    02599                 }
    02600         } else if ((dx == dy) && (draw_endpoint)) {
    02601                 /*
    02602                 * Diagonal line (with endpoint)
    02603                 */
    02604                 return (lineColor(dst, x1, y1, x2, y2, color));
    02605         }
    02606
    02607         /*
    02608         * Adjust for negative dx and set xdir
    02609         */
    02610         if (dx >= 0) {
    02611                 xdir = 1;
    02612         } else {
    02613                 xdir = -1;
    02614                 dx = (-dx);
    02615         }
    02616
    02617         /*
    02618         * Line is not horizontal, vertical or diagonal (with endpoint)
    02619         */
    02620         result = 0;
    02621
    02622         /*
    02623         * Zero accumulator
    02624         */
    02625         erracc = 0;
    02626
    02627         /*
    02628         * # of bits by which to shift erracc to get intensity level
    02629         */
    02630         intshift = 32 - AAbits;
    02631
    02632         /*
    02633         * Mask used to flip all bits in an intensity weighting
    02634         */
    02635         wgtcompmask = AAlevels - 1;
    02636
    02637         /* Lock surface */
    02638         if (SDL_MUSTLOCK(dst)) {
    02639                 if (SDL_LockSurface(dst) < 0) {
    02640                         return (-1);
    02641                 }
    02642         }
    02643
    02644         /*
    02645         * Draw the initial pixel in the foreground color
    02646         */
    02647         result |= pixelColorNolock(dst, x1, y1, color);
    02648
    02649         /*
    02650         * x-major or y-major?
    02651         */
    02652         if (dy > dx) {
    02653
    02654                 /*
    02655                 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
    02656                 * X advances every time Y advances 1 pixel, truncating the result so that
    02657                 * we won't overrun the endpoint along the X axis
    02658                 */
    02659                 /*
    02660                 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
    02661                 */
    02662                 erradj = ((dx << 16) / dy) << 16;
    02663
    02664                 /*
    02665                 * draw all pixels other than the first and last
    02666                 */
    02667                 x0pxdir = xx0 + xdir;
    02668                 while (--dy) {
    02669                         erracctmp = erracc;
    02670                         erracc += erradj;
    02671                         if (erracc <= erracctmp) {
    02672                                 /*
    02673                                 * rollover in error accumulator, x coord advances
    02674                                 */
    02675                                 xx0 = x0pxdir;
    02676                                 x0pxdir += xdir;
    02677                         }
    02678                         yy0++;          /* y-major so always advance Y */
    02679
    02680                         /*
    02681                         * the AAbits most significant bits of erracc give us the intensity
    02682                         * weighting for this pixel, and the complement of the weighting for
    02683                         * the paired pixel.
    02684                         */
    02685                         wgt = (erracc >> intshift) & 255;
    02686                         result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
    02687                         result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
    02688                 }
    02689
    02690         } else {
    02691
    02692                 /*
    02693                 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
    02694                 * that Y advances each time X advances 1 pixel, truncating the result so
    02695                 * that we won't overrun the endpoint along the X axis.
    02696                 */
    02697                 /*
    02698                 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
    02699                 */
    02700                 erradj = ((dy << 16) / dx) << 16;
    02701
    02702                 /*
    02703                 * draw all pixels other than the first and last
    02704                 */
    02705                 y0p1 = yy0 + 1;
    02706                 while (--dx) {
    02707
    02708                         erracctmp = erracc;
    02709                         erracc += erradj;
    02710                         if (erracc <= erracctmp) {
    02711                                 /*
    02712                                 * Accumulator turned over, advance y
    02713                                 */
    02714                                 yy0 = y0p1;
    02715                                 y0p1++;
    02716                         }
    02717                         xx0 += xdir;    /* x-major so always advance X */
    02718                         /*
    02719                         * the AAbits most significant bits of erracc give us the intensity
    02720                         * weighting for this pixel, and the complement of the weighting for
    02721                         * the paired pixel.
    02722                         */
    02723                         wgt = (erracc >> intshift) & 255;
    02724                         result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
    02725                         result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
    02726                 }
    02727         }
    02728
    02729         /*
    02730         * Do we have to draw the endpoint
    02731         */
    02732         if (draw_endpoint) {
    02733                 /*
    02734                 * Draw final pixel, always exactly intersected by the line and doesn't
    02735                 * need to be weighted.
    02736                 */
    02737                 result |= pixelColorNolock (dst, x2, y2, color);
    02738         }
    02739
    02740         /* Unlock surface */
    02741         if (SDL_MUSTLOCK(dst)) {
    02742                 SDL_UnlockSurface(dst);
    02743         }
    02744
    02745         return (result);
    02746 }
    02747
    02760 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    02761 {
    02762         return (_aalineColor(dst, x1, y1, x2, y2, color, 1));
    02763 }
    02764
    02780 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02781 {
    02782         return (_aalineColor
    02783                 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
    02784 }
    02785
    02786
    02787 /* ----- Circle */
    02788
    02804 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    02805 {
    02806         Sint16 left, right, top, bottom;
    02807         int result;
    02808         Sint16 x1, y1, x2, y2;
    02809         Sint16 cx = 0;
    02810         Sint16 cy = rad;
    02811         Sint16 ocx = (Sint16) 0xffff;
    02812         Sint16 ocy = (Sint16) 0xffff;
    02813         Sint16 df = 1 - rad;
    02814         Sint16 d_e = 3;
    02815         Sint16 d_se = -2 * rad + 5;
    02816         Sint16 xpcx, xmcx, xpcy, xmcy;
    02817         Sint16 ypcy, ymcy, ypcx, ymcx;
    02818         Uint8 *colorptr;
    02819
    02820         /*
    02821         * Check visibility of clipping rectangle
    02822         */
    02823         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    02824                 return(0);
    02825         }
    02826
    02827         /*
    02828         * Sanity check radius
    02829         */
    02830         if (rad < 0) {
    02831                 return (-1);
    02832         }
    02833
    02834         /*
    02835         * Special case for rad=0 - draw a point
    02836         */
    02837         if (rad == 0) {
    02838                 return (pixelColor(dst, x, y, color));
    02839         }
    02840
    02841         /*
    02842         * Get circle and clipping boundary and
    02843         * test if bounding box of circle is visible
    02844         */
    02845         x2 = x + rad;
    02846         left = dst->clip_rect.x;
    02847         if (x2<left) {
    02848                 return(0);
    02849         }
    02850         x1 = x - rad;
    02851         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    02852         if (x1>right) {
    02853                 return(0);
    02854         }
    02855         y2 = y + rad;
    02856         top = dst->clip_rect.y;
    02857         if (y2<top) {
    02858                 return(0);
    02859         }
    02860         y1 = y - rad;
    02861         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    02862         if (y1>bottom) {
    02863                 return(0);
    02864         }
    02865
    02866         /*
    02867         * Draw circle
    02868         */
    02869         result = 0;
    02870
    02871         /* Lock surface */
    02872         if (SDL_MUSTLOCK(dst)) {
    02873                 if (SDL_LockSurface(dst) < 0) {
    02874                         return (-1);
    02875                 }
    02876         }
    02877
    02878         /*
    02879         * Alpha Check
    02880         */
    02881         if ((color & 255) == 255) {
    02882
    02883                 /*
    02884                 * No Alpha - direct memory writes
    02885                 */
    02886
    02887                 /*
    02888                 * Setup color
    02889                 */
    02890                 colorptr = (Uint8 *) & color;
    02891                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    02892                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    02893                 } else {
    02894                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    02895                 }
    02896
    02897                 /*
    02898                 * Draw
    02899                 */
    02900                 do {
    02901                         ypcy = y + cy;
    02902                         ymcy = y - cy;
    02903                         if (cx > 0) {
    02904                                 xpcx = x + cx;
    02905                                 xmcx = x - cx;
    02906                                 result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
    02907                                 result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
    02908                                 result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
    02909                                 result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
    02910                         } else {
    02911                                 result |= fastPixelColorNolock(dst, x, ymcy, color);
    02912                                 result |= fastPixelColorNolock(dst, x, ypcy, color);
    02913                         }
    02914                         xpcy = x + cy;
    02915                         xmcy = x - cy;
    02916                         if ((cx > 0) && (cx != cy)) {
    02917                                 ypcx = y + cx;
    02918                                 ymcx = y - cx;
    02919                                 result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
    02920                                 result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
    02921                                 result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
    02922                                 result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
    02923                         } else if (cx == 0) {
    02924                                 result |= fastPixelColorNolock(dst, xmcy, y, color);
    02925                                 result |= fastPixelColorNolock(dst, xpcy, y, color);
    02926                         }
    02927                         /*
    02928                         * Update
    02929                         */
    02930                         if (df < 0) {
    02931                                 df += d_e;
    02932                                 d_e += 2;
    02933                                 d_se += 2;
    02934                         } else {
    02935                                 df += d_se;
    02936                                 d_e += 2;
    02937                                 d_se += 4;
    02938                                 cy--;
    02939                         }
    02940                         cx++;
    02941                 } while (cx <= cy);
    02942
    02943                 /*
    02944                 * Unlock surface
    02945                 */
    02946                 SDL_UnlockSurface(dst);
    02947
    02948         } else {
    02949
    02950                 /*
    02951                 * Using Alpha - blended pixel blits
    02952                 */
    02953
    02954                 do {
    02955                         /*
    02956                         * Draw
    02957                         */
    02958                         ypcy = y + cy;
    02959                         ymcy = y - cy;
    02960                         if (cx > 0) {
    02961                                 xpcx = x + cx;
    02962                                 xmcx = x - cx;
    02963                                 result |= pixelColorNolock (dst, xmcx, ypcy, color);
    02964                                 result |= pixelColorNolock (dst, xpcx, ypcy, color);
    02965                                 result |= pixelColorNolock (dst, xmcx, ymcy, color);
    02966                                 result |= pixelColorNolock (dst, xpcx, ymcy, color);
    02967                         } else {
    02968                                 result |= pixelColorNolock (dst, x, ymcy, color);
    02969                                 result |= pixelColorNolock (dst, x, ypcy, color);
    02970                         }
    02971                         xpcy = x + cy;
    02972                         xmcy = x - cy;
    02973                         if ((cx > 0) && (cx != cy)) {
    02974                                 ypcx = y + cx;
    02975                                 ymcx = y - cx;
    02976                                 result |= pixelColorNolock (dst, xmcy, ypcx, color);
    02977                                 result |= pixelColorNolock (dst, xpcy, ypcx, color);
    02978                                 result |= pixelColorNolock (dst, xmcy, ymcx, color);
    02979                                 result |= pixelColorNolock (dst, xpcy, ymcx, color);
    02980                         } else if (cx == 0) {
    02981                                 result |= pixelColorNolock (dst, xmcy, y, color);
    02982                                 result |= pixelColorNolock (dst, xpcy, y, color);
    02983                         }
    02984                         /*
    02985                         * Update
    02986                         */
    02987                         if (df < 0) {
    02988                                 df += d_e;
    02989                                 d_e += 2;
    02990                                 d_se += 2;
    02991                         } else {
    02992                                 df += d_se;
    02993                                 d_e += 2;
    02994                                 d_se += 4;
    02995                                 cy--;
    02996                         }
    02997                         cx++;
    02998                 } while (cx <= cy);
    02999
    03000         }                               /* Alpha check */
    03001
    03002         /* Unlock surface */
    03003         if (SDL_MUSTLOCK(dst)) {
    03004                 SDL_UnlockSurface(dst);
    03005         }
    03006
    03007         return (result);
    03008 }
    03009
    03024 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03025 {
    03026         /*
    03027         * Draw
    03028         */
    03029         return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    03030 }
    03031
    03032 /* ----- Arc */
    03033
    03051 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    03052 {
    03053         Sint16 left, right, top, bottom;
    03054         int result;
    03055         Sint16 x1, y1, x2, y2;
    03056         Sint16 cx = 0;
    03057         Sint16 cy = rad;
    03058         Sint16 ocx = (Sint16) 0xffff;
    03059         Sint16 ocy = (Sint16) 0xffff;
    03060         Sint16 df = 1 - rad;
    03061         Sint16 d_e = 3;
    03062         Sint16 d_se = -2 * rad + 5;
    03063         Sint16 xpcx, xmcx, xpcy, xmcy;
    03064         Sint16 ypcy, ymcy, ypcx, ymcx;
    03065         Uint8 *colorptr;
    03066         Uint8 drawoct;
    03067         int startoct, endoct, oct, stopval_start, stopval_end;
    03068         double temp;
    03069
    03070         /*
    03071         * Check visibility of clipping rectangle
    03072         */
    03073         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    03074                 return(0);
    03075         }
    03076
    03077         /*
    03078         * Sanity check radius
    03079         */
    03080         if (rad < 0) {
    03081                 return (-1);
    03082         }
    03083
    03084         /*
    03085         * Special case for rad=0 - draw a point
    03086         */
    03087         if (rad == 0) {
    03088                 return (pixelColor(dst, x, y, color));
    03089         }
    03090
    03091         /*
    03092         * Get arc's circle and clipping boundary and
    03093         * test if bounding box of circle is visible
    03094         */
    03095         x2 = x + rad;
    03096         left = dst->clip_rect.x;
    03097         if (x2<left) {
    03098                 return(0);
    03099         }
    03100         x1 = x - rad;
    03101         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    03102         if (x1>right) {
    03103                 return(0);
    03104         }
    03105         y2 = y + rad;
    03106         top = dst->clip_rect.y;
    03107         if (y2<top) {
    03108                 return(0);
    03109         }
    03110         y1 = y - rad;
    03111         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    03112         if (y1>bottom) {
    03113                 return(0);
    03114         }
    03115
    03116         // Octant labelling
    03117         //
    03118         //  \ 5 | 6 /
    03119         //   \  |  /
    03120         //  4 \ | / 7
    03121         //     \|/
    03122         //------+------ +x
    03123         //     /|\
    03124         //  3 / | \ 0
    03125         //   /  |  \
    03126         //  / 2 | 1 \
    03127         //      +y
    03128
    03129         // Initially reset bitmask to 0x00000000
    03130         // the set whether or not to keep drawing a given octant.
    03131         // For example: 0x00111100 means we're drawing in octants 2-5
    03132         drawoct = 0;
    03133
    03134         /*
    03135         * Fixup angles
    03136         */
    03137         start %= 360;
    03138         end %= 360;
    03139         // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
    03140         while (start < 0) start += 360;
    03141         while (end < 0) end += 360;
    03142         start %= 360;
    03143         end %= 360;
    03144
    03145         // now, we find which octants we're drawing in.
    03146         startoct = start / 45;
    03147         endoct = end / 45;
    03148         oct = startoct - 1; // we increment as first step in loop
    03149
    03150         // stopval_start, stopval_end;
    03151         // what values of cx to stop at.
    03152         do {
    03153                 oct = (oct + 1) % 8;
    03154
    03155                 if (oct == startoct) {
    03156                         // need to compute stopval_start for this octant.  Look at picture above if this is unclear
    03157                         switch (oct)
    03158                         {
    03159                         case 0:
    03160                         case 3:
    03161                                 temp = sin(start * M_PI / 180);
    03162                                 break;
    03163                         case 1:
    03164                         case 6:
    03165                                 temp = cos(start * M_PI / 180);
    03166                                 break;
    03167                         case 2:
    03168                         case 5:
    03169                                 temp = -cos(start * M_PI / 180);
    03170                                 break;
    03171                         case 4:
    03172                         case 7:
    03173                                 temp = -sin(start * M_PI / 180);
    03174                                 break;
    03175                         }
    03176                         temp *= rad;
    03177                         stopval_start = (int)temp; // always round down.
    03178                         // This isn't arbitrary, but requires graph paper to explain well.
    03179                         // The basic idea is that we're always changing drawoct after we draw, so we
    03180                         // stop immediately after we render the last sensible pixel at x = ((int)temp).
    03181
    03182                         // and whether to draw in this octant initially
    03183                         if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
    03184                         else             drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
    03185                 }
    03186                 if (oct == endoct) {
    03187                         // need to compute stopval_end for this octant
    03188                         switch (oct)
    03189                         {
    03190                         case 0:
    03191                         case 3:
    03192                                 temp = sin(end * M_PI / 180);
    03193                                 break;
    03194                         case 1:
    03195                         case 6:
    03196                                 temp = cos(end * M_PI / 180);
    03197                                 break;
    03198                         case 2:
    03199                         case 5:
    03200                                 temp = -cos(end * M_PI / 180);
    03201                                 break;
    03202                         case 4:
    03203                         case 7:
    03204                                 temp = -sin(end * M_PI / 180);
    03205                                 break;
    03206                         }
    03207                         temp *= rad;
    03208                         stopval_end = (int)temp;
    03209
    03210                         // and whether to draw in this octant initially
    03211                         if (startoct == endoct) {
    03212                                 // note:      we start drawing, stop, then start again in this case
    03213                                 // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
    03214                                 if (start > end) {
    03215                                         // unfortunately, if we're in the same octant and need to draw over the whole circle,
    03216                                         // we need to set the rest to true, because the while loop will end at the bottom.
    03217                                         drawoct = 255;
    03218                                 } else {
    03219                                         drawoct &= 255 - (1 << oct);
    03220                                 }
    03221                         }
    03222                         else if (oct % 2) drawoct &= 255 - (1 << oct);
    03223                         else                      drawoct |= (1 << oct);
    03224                 } else if (oct != startoct) { // already verified that it's != endoct
    03225                         drawoct |= (1 << oct); // draw this entire segment
    03226                 }
    03227         } while (oct != endoct);
    03228
    03229         // so now we have what octants to draw and when to draw them.  all that's left is the actual raster code.
    03230
    03231         /* Lock surface */
    03232         if (SDL_MUSTLOCK(dst)) {
    03233                 if (SDL_LockSurface(dst) < 0) {
    03234                         return (-1);
    03235                 }
    03236         }
    03237
    03238         /*
    03239         * Draw arc
    03240         */
    03241         result = 0;
    03242
    03243         /*
    03244         * Alpha Check
    03245         */
    03246         if ((color & 255) == 255) {
    03247
    03248                 /*
    03249                 * No Alpha - direct memory writes
    03250                 */
    03251
    03252                 /*
    03253                 * Setup color
    03254                 */
    03255                 colorptr = (Uint8 *) & color;
    03256                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    03257                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    03258                 } else {
    03259                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    03260                 }
    03261
    03262                 /*
    03263                 * Draw
    03264                 */
    03265                 do {
    03266                         ypcy = y + cy;
    03267                         ymcy = y - cy;
    03268                         if (cx > 0) {
    03269                                 xpcx = x + cx;
    03270                                 xmcx = x - cx;
    03271                                 // always check if we're drawing a certain octant before adding a pixel to that octant.
    03272                                 if (drawoct & 4)  result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2]
    03273                                 if (drawoct & 2)  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
    03274                                 if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
    03275                                 if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
    03276                         } else {
    03277                                 if (drawoct & 6)  result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1]
    03278                                 if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64
    03279                         }
    03280
    03281                         xpcy = x + cy;
    03282                         xmcy = x - cy;
    03283                         if (cx > 0 && cx != cy) {
    03284                                 ypcx = y + cx;
    03285                                 ymcx = y - cx;
    03286                                 if (drawoct & 8)   result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
    03287                                 if (drawoct & 1)   result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
    03288                                 if (drawoct & 16)  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
    03289                                 if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
    03290                         } else if (cx == 0) {
    03291                                 if (drawoct & 24)  result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16
    03292                                 if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128
    03293                         }
    03294
    03295                         /*
    03296                         * Update whether we're drawing an octant
    03297                         */
    03298                         if (stopval_start == cx) {
    03299                                 // works like an on-off switch because start & end may be in the same octant.
    03300                                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
    03301                                 else drawoct |= (1 << startoct);
    03302                         }
    03303                         if (stopval_end == cx) {
    03304                                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
    03305                                 else drawoct |= (1 << endoct);
    03306                         }
    03307
    03308                         /*
    03309                         * Update pixels
    03310                         */
    03311                         if (df < 0) {
    03312                                 df += d_e;
    03313                                 d_e += 2;
    03314                                 d_se += 2;
    03315                         } else {
    03316                                 df += d_se;
    03317                                 d_e += 2;
    03318                                 d_se += 4;
    03319                                 cy--;
    03320                         }
    03321                         cx++;
    03322                 } while (cx <= cy);
    03323
    03324                 /*
    03325                 * Unlock surface
    03326                 */
    03327                 SDL_UnlockSurface(dst);
    03328
    03329         } else {
    03330
    03331                 /*
    03332                 * Using Alpha - blended pixel blits
    03333                 */
    03334
    03335                 do {
    03336                         ypcy = y + cy;
    03337                         ymcy = y - cy;
    03338                         if (cx > 0) {
    03339                                 xpcx = x + cx;
    03340                                 xmcx = x - cx;
    03341
    03342                                 // always check if we're drawing a certain octant before adding a pixel to that octant.
    03343                                 if (drawoct & 4)  result |= pixelColorNolock(dst, xmcx, ypcy, color);
    03344                                 if (drawoct & 2)  result |= pixelColorNolock(dst, xpcx, ypcy, color);
    03345                                 if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
    03346                                 if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
    03347                         } else {
    03348                                 if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
    03349                                 if (drawoct & 6)  result |= pixelColorNolock(dst, x, ypcy, color);
    03350                         }
    03351
    03352                         xpcy = x + cy;
    03353                         xmcy = x - cy;
    03354                         if (cx > 0 && cx != cy) {
    03355                                 ypcx = y + cx;
    03356                                 ymcx = y - cx;
    03357                                 if (drawoct & 8)   result |= pixelColorNolock(dst, xmcy, ypcx, color);
    03358                                 if (drawoct & 1)   result |= pixelColorNolock(dst, xpcy, ypcx, color);
    03359                                 if (drawoct & 16)  result |= pixelColorNolock(dst, xmcy, ymcx, color);
    03360                                 if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
    03361                         } else if (cx == 0) {
    03362                                 if (drawoct & 24)  result |= pixelColorNolock(dst, xmcy, y, color);
    03363                                 if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
    03364                         }
    03365
    03366                         /*
    03367                         * Update whether we're drawing an octant
    03368                         */
    03369                         if (stopval_start == cx) {
    03370                                 // works like an on-off switch.
    03371                                 // This is just in case start & end are in the same octant.
    03372                                 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
    03373                                 else                                               drawoct |= (1 << startoct);
    03374                         }
    03375                         if (stopval_end == cx) {
    03376                                 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
    03377                                 else                                             drawoct |= (1 << endoct);
    03378                         }
    03379
    03380                         /*
    03381                         * Update pixels
    03382                         */
    03383                         if (df < 0) {
    03384                                 df += d_e;
    03385                                 d_e += 2;
    03386                                 d_se += 2;
    03387                         } else {
    03388                                 df += d_se;
    03389                                 d_e += 2;
    03390                                 d_se += 4;
    03391                                 cy--;
    03392                         }
    03393                         cx++;
    03394                 } while (cx <= cy);
    03395
    03396         }                               /* Alpha check */
    03397
    03398         /* Unlock surface */
    03399         if (SDL_MUSTLOCK(dst)) {
    03400                 SDL_UnlockSurface(dst);
    03401         }
    03402
    03403         return (result);
    03404 }
    03405
    03422 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03423 {
    03424         /*
    03425         * Draw
    03426         */
    03427         return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    03428 }
    03429
    03430 /* ----- AA Circle */
    03431
    03432
    03446 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    03447 {
    03448         return (aaellipseColor(dst, x, y, rad, rad, color));
    03449 }
    03450
    03465 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03466 {
    03467         /*
    03468         * Draw
    03469         */
    03470         return (aaellipseColor
    03471                 (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    03472 }
    03473
    03474 /* ----- Filled Circle */
    03475
    03490 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    03491 {
    03492         Sint16 left, right, top, bottom;
    03493         int result;
    03494         Sint16 x1, y1, x2, y2;
    03495         Sint16 cx = 0;
    03496         Sint16 cy = rad;
    03497         Sint16 ocx = (Sint16) 0xffff;
    03498         Sint16 ocy = (Sint16) 0xffff;
    03499         Sint16 df = 1 - rad;
    03500         Sint16 d_e = 3;
    03501         Sint16 d_se = -2 * rad + 5;
    03502         Sint16 xpcx, xmcx, xpcy, xmcy;
    03503         Sint16 ypcy, ymcy, ypcx, ymcx;
    03504
    03505         /*
    03506         * Check visibility of clipping rectangle
    03507         */
    03508         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    03509                 return(0);
    03510         }
    03511
    03512         /*
    03513         * Sanity check radius
    03514         */
    03515         if (rad < 0) {
    03516                 return (-1);
    03517         }
    03518
    03519         /*
    03520         * Special case for rad=0 - draw a point
    03521         */
    03522         if (rad == 0) {
    03523                 return (pixelColor(dst, x, y, color));
    03524         }
    03525
    03526         /*
    03527         * Get circle and clipping boundary and
    03528         * test if bounding box of circle is visible
    03529         */
    03530         x2 = x + rad;
    03531         left = dst->clip_rect.x;
    03532         if (x2<left) {
    03533                 return(0);
    03534         }
    03535         x1 = x - rad;
    03536         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    03537         if (x1>right) {
    03538                 return(0);
    03539         }
    03540         y2 = y + rad;
    03541         top = dst->clip_rect.y;
    03542         if (y2<top) {
    03543                 return(0);
    03544         }
    03545         y1 = y - rad;
    03546         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    03547         if (y1>bottom) {
    03548                 return(0);
    03549         }
    03550
    03551         /*
    03552         * Draw
    03553         */
    03554         result = 0;
    03555         do {
    03556                 xpcx = x + cx;
    03557                 xmcx = x - cx;
    03558                 xpcy = x + cy;
    03559                 xmcy = x - cy;
    03560                 if (ocy != cy) {
    03561                         if (cy > 0) {
    03562                                 ypcy = y + cy;
    03563                                 ymcy = y - cy;
    03564                                 result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
    03565                                 result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
    03566                         } else {
    03567                                 result |= hlineColor(dst, xmcx, xpcx, y, color);
    03568                         }
    03569                         ocy = cy;
    03570                 }
    03571                 if (ocx != cx) {
    03572                         if (cx != cy) {
    03573                                 if (cx > 0) {
    03574                                         ypcx = y + cx;
    03575                                         ymcx = y - cx;
    03576                                         result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
    03577                                         result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
    03578                                 } else {
    03579                                         result |= hlineColor(dst, xmcy, xpcy, y, color);
    03580                                 }
    03581                         }
    03582                         ocx = cx;
    03583                 }
    03584                 /*
    03585                 * Update
    03586                 */
    03587                 if (df < 0) {
    03588                         df += d_e;
    03589                         d_e += 2;
    03590                         d_se += 2;
    03591                 } else {
    03592                         df += d_se;
    03593                         d_e += 2;
    03594                         d_se += 4;
    03595                         cy--;
    03596                 }
    03597                 cx++;
    03598         } while (cx <= cy);
    03599
    03600         return (result);
    03601 }
    03602
    03617 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03618 {
    03619         /*
    03620         * Draw
    03621         */
    03622         return (filledCircleColor
    03623                 (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    03624 }
    03625
    03626 /* ----- Ellipse */
    03627
    03643 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    03644 {
    03645         Sint16 left, right, top, bottom;
    03646         int result;
    03647         Sint16 x1, y1, x2, y2;
    03648         int ix, iy;
    03649         int h, i, j, k;
    03650         int oh, oi, oj, ok;
    03651         int xmh, xph, ypk, ymk;
    03652         int xmi, xpi, ymj, ypj;
    03653         int xmj, xpj, ymi, ypi;
    03654         int xmk, xpk, ymh, yph;
    03655         Uint8 *colorptr;
    03656
    03657         /*
    03658         * Check visibility of clipping rectangle
    03659         */
    03660         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    03661                 return(0);
    03662         }
    03663
    03664         /*
    03665         * Sanity check radii
    03666         */
    03667         if ((rx < 0) || (ry < 0)) {
    03668                 return (-1);
    03669         }
    03670
    03671         /*
    03672         * Special case for rx=0 - draw a vline
    03673         */
    03674         if (rx == 0) {
    03675                 return (vlineColor(dst, x, y - ry, y + ry, color));
    03676         }
    03677         /*
    03678         * Special case for ry=0 - draw a hline
    03679         */
    03680         if (ry == 0) {
    03681                 return (hlineColor(dst, x - rx, x + rx, y, color));
    03682         }
    03683
    03684         /*
    03685         * Get circle and clipping boundary and
    03686         * test if bounding box of circle is visible
    03687         */
    03688         x2 = x + rx;
    03689         left = dst->clip_rect.x;
    03690         if (x2<left) {
    03691                 return(0);
    03692         }
    03693         x1 = x - rx;
    03694         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    03695         if (x1>right) {
    03696                 return(0);
    03697         }
    03698         y2 = y + ry;
    03699         top = dst->clip_rect.y;
    03700         if (y2<top) {
    03701                 return(0);
    03702         }
    03703         y1 = y - ry;
    03704         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    03705         if (y1>bottom) {
    03706                 return(0);
    03707         }
    03708
    03709         /*
    03710         * Init vars
    03711         */
    03712         oh = oi = oj = ok = 0xFFFF;
    03713
    03714         /*
    03715         * Draw
    03716         */
    03717         result = 0;
    03718
    03719         /* Lock surface */
    03720         if (SDL_MUSTLOCK(dst)) {
    03721                 if (SDL_LockSurface(dst) < 0) {
    03722                         return (-1);
    03723                 }
    03724         }
    03725
    03726         /*
    03727         * Check alpha
    03728         */
    03729         if ((color & 255) == 255) {
    03730
    03731                 /*
    03732                 * No Alpha - direct memory writes
    03733                 */
    03734
    03735                 /*
    03736                 * Setup color
    03737                 */
    03738                 colorptr = (Uint8 *) & color;
    03739                 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    03740                         color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
    03741                 } else {
    03742                         color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
    03743                 }
    03744
    03745
    03746                 if (rx > ry) {
    03747                         ix = 0;
    03748                         iy = rx * 64;
    03749
    03750                         do {
    03751                                 h = (ix + 32) >> 6;
    03752                                 i = (iy + 32) >> 6;
    03753                                 j = (h * ry) / rx;
    03754                                 k = (i * ry) / rx;
    03755
    03756                                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
    03757                                         xph = x + h;
    03758                                         xmh = x - h;
    03759                                         if (k > 0) {
    03760                                                 ypk = y + k;
    03761                                                 ymk = y - k;
    03762                                                 result |= fastPixelColorNolock(dst, xmh, ypk, color);
    03763                                                 result |= fastPixelColorNolock(dst, xph, ypk, color);
    03764                                                 result |= fastPixelColorNolock(dst, xmh, ymk, color);
    03765                                                 result |= fastPixelColorNolock(dst, xph, ymk, color);
    03766                                         } else {
    03767                                                 result |= fastPixelColorNolock(dst, xmh, y, color);
    03768                                                 result |= fastPixelColorNolock(dst, xph, y, color);
    03769                                         }
    03770                                         ok = k;
    03771                                         xpi = x + i;
    03772                                         xmi = x - i;
    03773                                         if (j > 0) {
    03774                                                 ypj = y + j;
    03775                                                 ymj = y - j;
    03776                                                 result |= fastPixelColorNolock(dst, xmi, ypj, color);
    03777                                                 result |= fastPixelColorNolock(dst, xpi, ypj, color);
    03778                                                 result |= fastPixelColorNolock(dst, xmi, ymj, color);
    03779                                                 result |= fastPixelColorNolock(dst, xpi, ymj, color);
    03780                                         } else {
    03781                                                 result |= fastPixelColorNolock(dst, xmi, y, color);
    03782                                                 result |= fastPixelColorNolock(dst, xpi, y, color);
    03783                                         }
    03784                                         oj = j;
    03785                                 }
    03786
    03787                                 ix = ix + iy / rx;
    03788                                 iy = iy - ix / rx;
    03789
    03790                         } while (i > h);
    03791                 } else {
    03792                         ix = 0;
    03793                         iy = ry * 64;
    03794
    03795                         do {
    03796                                 h = (ix + 32) >> 6;
    03797                                 i = (iy + 32) >> 6;
    03798                                 j = (h * rx) / ry;
    03799                                 k = (i * rx) / ry;
    03800
    03801                                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
    03802                                         xmj = x - j;
    03803                                         xpj = x + j;
    03804                                         if (i > 0) {
    03805                                                 ypi = y + i;
    03806                                                 ymi = y - i;
    03807                                                 result |= fastPixelColorNolock(dst, xmj, ypi, color);
    03808                                                 result |= fastPixelColorNolock(dst, xpj, ypi, color);
    03809                                                 result |= fastPixelColorNolock(dst, xmj, ymi, color);
    03810                                                 result |= fastPixelColorNolock(dst, xpj, ymi, color);
    03811                                         } else {
    03812                                                 result |= fastPixelColorNolock(dst, xmj, y, color);
    03813                                                 result |= fastPixelColorNolock(dst, xpj, y, color);
    03814                                         }
    03815                                         oi = i;
    03816                                         xmk = x - k;
    03817                                         xpk = x + k;
    03818                                         if (h > 0) {
    03819                                                 yph = y + h;
    03820                                                 ymh = y - h;
    03821                                                 result |= fastPixelColorNolock(dst, xmk, yph, color);
    03822                                                 result |= fastPixelColorNolock(dst, xpk, yph, color);
    03823                                                 result |= fastPixelColorNolock(dst, xmk, ymh, color);
    03824                                                 result |= fastPixelColorNolock(dst, xpk, ymh, color);
    03825                                         } else {
    03826                                                 result |= fastPixelColorNolock(dst, xmk, y, color);
    03827                                                 result |= fastPixelColorNolock(dst, xpk, y, color);
    03828                                         }
    03829                                         oh = h;
    03830                                 }
    03831
    03832                                 ix = ix + iy / ry;
    03833                                 iy = iy - ix / ry;
    03834
    03835                         } while (i > h);
    03836                 }
    03837
    03838         } else {
    03839
    03840                 if (rx > ry) {
    03841                         ix = 0;
    03842                         iy = rx * 64;
    03843
    03844                         do {
    03845                                 h = (ix + 32) >> 6;
    03846                                 i = (iy + 32) >> 6;
    03847                                 j = (h * ry) / rx;
    03848                                 k = (i * ry) / rx;
    03849
    03850                                 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
    03851                                         xph = x + h;
    03852                                         xmh = x - h;
    03853                                         if (k > 0) {
    03854                                                 ypk = y + k;
    03855                                                 ymk = y - k;
    03856                                                 result |= pixelColorNolock (dst, xmh, ypk, color);
    03857                                                 result |= pixelColorNolock (dst, xph, ypk, color);
    03858                                                 result |= pixelColorNolock (dst, xmh, ymk, color);
    03859                                                 result |= pixelColorNolock (dst, xph, ymk, color);
    03860                                         } else {
    03861                                                 result |= pixelColorNolock (dst, xmh, y, color);
    03862                                                 result |= pixelColorNolock (dst, xph, y, color);
    03863                                         }
    03864                                         ok = k;
    03865                                         xpi = x + i;
    03866                                         xmi = x - i;
    03867                                         if (j > 0) {
    03868                                                 ypj = y + j;
    03869                                                 ymj = y - j;
    03870                                                 result |= pixelColorNolock (dst, xmi, ypj, color);
    03871                                                 result |= pixelColorNolock (dst, xpi, ypj, color);
    03872                                                 result |= pixelColorNolock (dst, xmi, ymj, color);
    03873                                                 result |= pixelColor(dst, xpi, ymj, color);
    03874                                         } else {
    03875                                                 result |= pixelColorNolock (dst, xmi, y, color);
    03876                                                 result |= pixelColorNolock (dst, xpi, y, color);
    03877                                         }
    03878                                         oj = j;
    03879                                 }
    03880
    03881                                 ix = ix + iy / rx;
    03882                                 iy = iy - ix / rx;
    03883
    03884                         } while (i > h);
    03885                 } else {
    03886                         ix = 0;
    03887                         iy = ry * 64;
    03888
    03889                         do {
    03890                                 h = (ix + 32) >> 6;
    03891                                 i = (iy + 32) >> 6;
    03892                                 j = (h * rx) / ry;
    03893                                 k = (i * rx) / ry;
    03894
    03895                                 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
    03896                                         xmj = x - j;
    03897                                         xpj = x + j;
    03898                                         if (i > 0) {
    03899                                                 ypi = y + i;
    03900                                                 ymi = y - i;
    03901                                                 result |= pixelColorNolock (dst, xmj, ypi, color);
    03902                                                 result |= pixelColorNolock (dst, xpj, ypi, color);
    03903                                                 result |= pixelColorNolock (dst, xmj, ymi, color);
    03904                                                 result |= pixelColorNolock (dst, xpj, ymi, color);
    03905                                         } else {
    03906                                                 result |= pixelColorNolock (dst, xmj, y, color);
    03907                                                 result |= pixelColorNolock (dst, xpj, y, color);
    03908                                         }
    03909                                         oi = i;
    03910                                         xmk = x - k;
    03911                                         xpk = x + k;
    03912                                         if (h > 0) {
    03913                                                 yph = y + h;
    03914                                                 ymh = y - h;
    03915                                                 result |= pixelColorNolock (dst, xmk, yph, color);
    03916                                                 result |= pixelColorNolock (dst, xpk, yph, color);
    03917                                                 result |= pixelColorNolock (dst, xmk, ymh, color);
    03918                                                 result |= pixelColorNolock (dst, xpk, ymh, color);
    03919                                         } else {
    03920                                                 result |= pixelColorNolock (dst, xmk, y, color);
    03921                                                 result |= pixelColorNolock (dst, xpk, y, color);
    03922                                         }
    03923                                         oh = h;
    03924                                 }
    03925
    03926                                 ix = ix + iy / ry;
    03927                                 iy = iy - ix / ry;
    03928
    03929                         } while (i > h);
    03930                 }
    03931
    03932         }                               /* Alpha check */
    03933
    03934         /* Unlock surface */
    03935         if (SDL_MUSTLOCK(dst)) {
    03936                 SDL_UnlockSurface(dst);
    03937         }
    03938
    03939         return (result);
    03940 }
    03941
    03957 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03958 {
    03959         /*
    03960         * Draw
    03961         */
    03962         return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    03963 }
    03964
    03965 /* ----- AA Ellipse */
    03966
    03967 /* Win32 does not have lrint, so provide a local inline version */
    03968 /*  detect MinGW and Symbian and avoid function */
    03969 /*  detect 64bit and use intrinsic version */
    03970 #if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW_H) && !defined(__SYMBIAN32__)
    03971 #ifdef _M_X64
    03972 #include <emmintrin.h>
    03973 static __inline long
    03974 lrint(float f)
    03975 {
    03976         return _mm_cvtss_si32(_mm_load_ss(&f));
    03977 }
    03978 #else
    03979 __inline long int
    03980 lrint (double flt)
    03981 {
    03982         int intgr;
    03983         _asm
    03984         {
    03985                 fld flt
    03986                         fistp intgr
    03987         };
    03988         return intgr;
    03989 }
    03990 #endif
    03991 #endif
    03992
    04008 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    04009 {
    04010         Sint16 left, right, top, bottom;
    04011         Sint16 x1,y1,x2,y2;
    04012         int i;
    04013         int a2, b2, ds, dt, dxt, t, s, d;
    04014         Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
    04015         float cp;
    04016         double sab;
    04017         Uint8 weight, iweight;
    04018         int result;
    04019
    04020         /*
    04021         * Check visibility of clipping rectangle
    04022         */
    04023         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    04024                 return(0);
    04025         }
    04026
    04027         /*
    04028         * Sanity check radii
    04029         */
    04030         if ((rx < 0) || (ry < 0)) {
    04031                 return (-1);
    04032         }
    04033
    04034         /*
    04035         * Special case for rx=0 - draw a vline
    04036         */
    04037         if (rx == 0) {
    04038                 return (vlineColor(dst, x, y - ry, y + ry, color));
    04039         }
    04040         /*
    04041         * Special case for ry=0 - draw an hline
    04042         */
    04043         if (ry == 0) {
    04044                 return (hlineColor(dst, x - rx, x + rx, y, color));
    04045         }
    04046
    04047         /*
    04048         * Get circle and clipping boundary and
    04049         * test if bounding box of circle is visible
    04050         */
    04051         x2 = x + rx;
    04052         left = dst->clip_rect.x;
    04053         if (x2<left) {
    04054                 return(0);
    04055         }
    04056         x1 = x - rx;
    04057         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    04058         if (x1>right) {
    04059                 return(0);
    04060         }
    04061         y2 = y + ry;
    04062         top = dst->clip_rect.y;
    04063         if (y2<top) {
    04064                 return(0);
    04065         }
    04066         y1 = y - ry;
    04067         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    04068         if (y1>bottom) {
    04069                 return(0);
    04070         }
    04071
    04072         /* Variable setup */
    04073         a2 = rx * rx;
    04074         b2 = ry * ry;
    04075
    04076         ds = 2 * a2;
    04077         dt = 2 * b2;
    04078
    04079         xc2 = 2 * x;
    04080         yc2 = 2 * y;
    04081
    04082         sab = sqrt(a2 + b2);
    04083         od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
    04084         dxt = (Sint16)lrint((double)a2 / sab) + od;
    04085
    04086         t = 0;
    04087         s = -2 * a2 * ry;
    04088         d = 0;
    04089
    04090         xp = x;
    04091         yp = y - ry;
    04092
    04093         /* Lock surface */
    04094         if (SDL_MUSTLOCK(dst)) {
    04095                 if (SDL_LockSurface(dst) < 0) {
    04096                         return (-1);
    04097                 }
    04098         }
    04099
    04100         /* Draw */
    04101         result = 0;
    04102
    04103         /* "End points" */
    04104         result |= pixelColorNolock(dst, xp, yp, color);
    04105         result |= pixelColorNolock(dst, xc2 - xp, yp, color);
    04106         result |= pixelColorNolock(dst, xp, yc2 - yp, color);
    04107         result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
    04108
    04109         for (i = 1; i <= dxt; i++) {
    04110                 xp--;
    04111                 d += t - b2;
    04112
    04113                 if (d >= 0)
    04114                         ys = yp - 1;
    04115                 else if ((d - s - a2) > 0) {
    04116                         if ((2 * d - s - a2) >= 0)
    04117                                 ys = yp + 1;
    04118                         else {
    04119                                 ys = yp;
    04120                                 yp++;
    04121                                 d -= s + a2;
    04122                                 s += ds;
    04123                         }
    04124                 } else {
    04125                         yp++;
    04126                         ys = yp + 1;
    04127                         d -= s + a2;
    04128                         s += ds;
    04129                 }
    04130
    04131                 t -= dt;
    04132
    04133                 /* Calculate alpha */
    04134                 if (s != 0.0) {
    04135                         cp = (float) abs(d) / (float) abs(s);
    04136                         if (cp > 1.0) {
    04137                                 cp = 1.0;
    04138                         }
    04139                 } else {
    04140                         cp = 1.0;
    04141                 }
    04142
    04143                 /* Calculate weights */
    04144                 weight = (Uint8) (cp * 255);
    04145                 iweight = 255 - weight;
    04146
    04147                 /* Upper half */
    04148                 xx = xc2 - xp;
    04149                 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
    04150                 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
    04151
    04152                 result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
    04153                 result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
    04154
    04155                 /* Lower half */
    04156                 yy = yc2 - yp;
    04157                 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
    04158                 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
    04159
    04160                 yy = yc2 - ys;
    04161                 result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
    04162                 result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
    04163         }
    04164
    04165         /* Replaces original approximation code dyt = abs(yp - yc); */
    04166         dyt = (Sint16)lrint((double)b2 / sab ) + od;
    04167
    04168         for (i = 1; i <= dyt; i++) {
    04169                 yp++;
    04170                 d -= s + a2;
    04171
    04172                 if (d <= 0)
    04173                         xs = xp + 1;
    04174                 else if ((d + t - b2) < 0) {
    04175                         if ((2 * d + t - b2) <= 0)
    04176                                 xs = xp - 1;
    04177                         else {
    04178                                 xs = xp;
    04179                                 xp--;
    04180                                 d += t - b2;
    04181                                 t -= dt;
    04182                         }
    04183                 } else {
    04184                         xp--;
    04185                         xs = xp - 1;
    04186                         d += t - b2;
    04187                         t -= dt;
    04188                 }
    04189
    04190                 s += ds;
    04191
    04192                 /* Calculate alpha */
    04193                 if (t != 0.0) {
    04194                         cp = (float) abs(d) / (float) abs(t);
    04195                         if (cp > 1.0) {
    04196                                 cp = 1.0;
    04197                         }
    04198                 } else {
    04199                         cp = 1.0;
    04200                 }
    04201
    04202                 /* Calculate weight */
    04203                 weight = (Uint8) (cp * 255);
    04204                 iweight = 255 - weight;
    04205
    04206                 /* Left half */
    04207                 xx = xc2 - xp;
    04208                 yy = yc2 - yp;
    04209                 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
    04210                 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
    04211
    04212                 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
    04213                 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
    04214
    04215                 /* Right half */
    04216                 xx = xc2 - xs;
    04217                 result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
    04218                 result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
    04219
    04220                 result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
    04221                 result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
    04222
    04223         }
    04224
    04225         /* Unlock surface */
    04226         if (SDL_MUSTLOCK(dst)) {
    04227                 SDL_UnlockSurface(dst);
    04228         }
    04229
    04230         return (result);
    04231 }
    04232
    04248 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04249 {
    04250         /*
    04251         * Draw
    04252         */
    04253         return (aaellipseColor
    04254                 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    04255 }
    04256
    04257 /* ---- Filled Ellipse */
    04258
    04259 /* Note: */
    04260 /* Based on algorithm from sge library with multiple-hline draw removal */
    04261 /* and other speedup changes. */
    04262
    04278 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    04279 {
    04280         Sint16 left, right, top, bottom;
    04281         int result;
    04282         Sint16 x1, y1, x2, y2;
    04283         int ix, iy;
    04284         int h, i, j, k;
    04285         int oh, oi, oj, ok;
    04286         int xmh, xph;
    04287         int xmi, xpi;
    04288         int xmj, xpj;
    04289         int xmk, xpk;
    04290
    04291         /*
    04292         * Check visibility of clipping rectangle
    04293         */
    04294         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    04295                 return(0);
    04296         }
    04297
    04298         /*
    04299         * Sanity check radii
    04300         */
    04301         if ((rx < 0) || (ry < 0)) {
    04302                 return (-1);
    04303         }
    04304
    04305         /*
    04306         * Special case for rx=0 - draw a vline
    04307         */
    04308         if (rx == 0) {
    04309                 return (vlineColor(dst, x, y - ry, y + ry, color));
    04310         }
    04311         /*
    04312         * Special case for ry=0 - draw a hline
    04313         */
    04314         if (ry == 0) {
    04315                 return (hlineColor(dst, x - rx, x + rx, y, color));
    04316         }
    04317
    04318         /*
    04319         * Get circle and clipping boundary and
    04320         * test if bounding box of circle is visible
    04321         */
    04322         x2 = x + rx;
    04323         left = dst->clip_rect.x;
    04324         if (x2<left) {
    04325                 return(0);
    04326         }
    04327         x1 = x - rx;
    04328         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    04329         if (x1>right) {
    04330                 return(0);
    04331         }
    04332         y2 = y + ry;
    04333         top = dst->clip_rect.y;
    04334         if (y2<top) {
    04335                 return(0);
    04336         }
    04337         y1 = y - ry;
    04338         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    04339         if (y1>bottom) {
    04340                 return(0);
    04341         }
    04342
    04343         /*
    04344         * Init vars
    04345         */
    04346         oh = oi = oj = ok = 0xFFFF;
    04347
    04348         /*
    04349         * Draw
    04350         */
    04351         result = 0;
    04352         if (rx > ry) {
    04353                 ix = 0;
    04354                 iy = rx * 64;
    04355
    04356                 do {
    04357                         h = (ix + 32) >> 6;
    04358                         i = (iy + 32) >> 6;
    04359                         j = (h * ry) / rx;
    04360                         k = (i * ry) / rx;
    04361
    04362                         if ((ok != k) && (oj != k)) {
    04363                                 xph = x + h;
    04364                                 xmh = x - h;
    04365                                 if (k > 0) {
    04366                                         result |= hlineColor(dst, xmh, xph, y + k, color);
    04367                                         result |= hlineColor(dst, xmh, xph, y - k, color);
    04368                                 } else {
    04369                                         result |= hlineColor(dst, xmh, xph, y, color);
    04370                                 }
    04371                                 ok = k;
    04372                         }
    04373                         if ((oj != j) && (ok != j) && (k != j)) {
    04374                                 xmi = x - i;
    04375                                 xpi = x + i;
    04376                                 if (j > 0) {
    04377                                         result |= hlineColor(dst, xmi, xpi, y + j, color);
    04378                                         result |= hlineColor(dst, xmi, xpi, y - j, color);
    04379                                 } else {
    04380                                         result |= hlineColor(dst, xmi, xpi, y, color);
    04381                                 }
    04382                                 oj = j;
    04383                         }
    04384
    04385                         ix = ix + iy / rx;
    04386                         iy = iy - ix / rx;
    04387
    04388                 } while (i > h);
    04389         } else {
    04390                 ix = 0;
    04391                 iy = ry * 64;
    04392
    04393                 do {
    04394                         h = (ix + 32) >> 6;
    04395                         i = (iy + 32) >> 6;
    04396                         j = (h * rx) / ry;
    04397                         k = (i * rx) / ry;
    04398
    04399                         if ((oi != i) && (oh != i)) {
    04400                                 xmj = x - j;
    04401                                 xpj = x + j;
    04402                                 if (i > 0) {
    04403                                         result |= hlineColor(dst, xmj, xpj, y + i, color);
    04404                                         result |= hlineColor(dst, xmj, xpj, y - i, color);
    04405                                 } else {
    04406                                         result |= hlineColor(dst, xmj, xpj, y, color);
    04407                                 }
    04408                                 oi = i;
    04409                         }
    04410                         if ((oh != h) && (oi != h) && (i != h)) {
    04411                                 xmk = x - k;
    04412                                 xpk = x + k;
    04413                                 if (h > 0) {
    04414                                         result |= hlineColor(dst, xmk, xpk, y + h, color);
    04415                                         result |= hlineColor(dst, xmk, xpk, y - h, color);
    04416                                 } else {
    04417                                         result |= hlineColor(dst, xmk, xpk, y, color);
    04418                                 }
    04419                                 oh = h;
    04420                         }
    04421
    04422                         ix = ix + iy / ry;
    04423                         iy = iy - ix / ry;
    04424
    04425                 } while (i > h);
    04426         }
    04427
    04428         return (result);
    04429 }
    04430
    04446 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04447 {
    04448         /*
    04449         * Draw
    04450         */
    04451         return (filledEllipseColor
    04452                 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    04453 }
    04454
    04455 /* ----- pie */
    04456
    04473 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
    04474 {
    04475         Sint16 left, right, top, bottom;
    04476         Sint16 x1, y1, x2, y2;
    04477         int result;
    04478         double angle, start_angle, end_angle;
    04479         double deltaAngle;
    04480         double dr;
    04481         int numpoints, i;
    04482         Sint16 *vx, *vy;
    04483
    04484         /*
    04485         * Check visibility of clipping rectangle
    04486         */
    04487         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    04488                 return(0);
    04489         }
    04490
    04491         /*
    04492         * Sanity check radii
    04493         */
    04494         if (rad < 0) {
    04495                 return (-1);
    04496         }
    04497
    04498         /*
    04499         * Fixup angles
    04500         */
    04501         start = start % 360;
    04502         end = end % 360;
    04503
    04504         /*
    04505         * Special case for rad=0 - draw a point
    04506         */
    04507         if (rad == 0) {
    04508                 return (pixelColor(dst, x, y, color));
    04509         }
    04510
    04511         /*
    04512         * Clip against circle, not pie (not 100% optimal).
    04513         * Get pie's circle and clipping boundary and
    04514         * test if bounding box of circle is visible
    04515         */
    04516         x2 = x + rad;
    04517         left = dst->clip_rect.x;
    04518         if (x2<left) {
    04519                 return(0);
    04520         }
    04521         x1 = x - rad;
    04522         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    04523         if (x1>right) {
    04524                 return(0);
    04525         }
    04526         y2 = y + rad;
    04527         top = dst->clip_rect.y;
    04528         if (y2<top) {
    04529                 return(0);
    04530         }
    04531         y1 = y - rad;
    04532         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    04533         if (y1>bottom) {
    04534                 return(0);
    04535         }
    04536
    04537         /*
    04538         * Variable setup
    04539         */
    04540         dr = (double) rad;
    04541         deltaAngle = 3.0 / dr;
    04542         start_angle = (double) start *(2.0 * M_PI / 360.0);
    04543         end_angle = (double) end *(2.0 * M_PI / 360.0);
    04544         if (start > end) {
    04545                 end_angle += (2.0 * M_PI);
    04546         }
    04547
    04548         /* We will always have at least 2 points */
    04549         numpoints = 2;
    04550
    04551         /* Count points (rather than calculating it) */
    04552         angle = start_angle;
    04553         while (angle < end_angle) {
    04554                 angle += deltaAngle;
    04555                 numpoints++;
    04556         }
    04557
    04558         /* Allocate combined vertex array */
    04559         vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
    04560         if (vx == NULL) {
    04561                 return (-1);
    04562         }
    04563
    04564         /* Update point to start of vy */
    04565         vy += numpoints;
    04566
    04567         /* Center */
    04568         vx[0] = x;
    04569         vy[0] = y;
    04570
    04571         /* First vertex */
    04572         angle = start_angle;
    04573         vx[1] = x + (int) (dr * cos(angle));
    04574         vy[1] = y + (int) (dr * sin(angle));
    04575
    04576         if (numpoints<3)
    04577         {
    04578                 result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
    04579         }
    04580         else
    04581         {
    04582                 /* Calculate other vertices */
    04583                 i = 2;
    04584                 angle = start_angle;
    04585                 while (angle < end_angle) {
    04586                         angle += deltaAngle;
    04587                         if (angle>end_angle)
    04588                         {
    04589                                 angle = end_angle;
    04590                         }
    04591                         vx[i] = x + (int) (dr * cos(angle));
    04592                         vy[i] = y + (int) (dr * sin(angle));
    04593                         i++;
    04594                 }
    04595
    04596                 /* Draw */
    04597                 if (filled) {
    04598                         result = filledPolygonColor(dst, vx, vy, numpoints, color);
    04599                 } else {
    04600                         result = polygonColor(dst, vx, vy, numpoints, color);
    04601                 }
    04602         }
    04603
    04604         /* Free combined vertex array */
    04605         free(vx);
    04606
    04607         return (result);
    04608 }
    04609
    04623 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
    04624                          Sint16 start, Sint16 end, Uint32 color)
    04625 {
    04626         return (_pieColor(dst, x, y, rad, start, end, color, 0));
    04627
    04628 }
    04629
    04646 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
    04647                         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04648 {
    04649         return (_pieColor(dst, x, y, rad, start, end,
    04650                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
    04651
    04652 }
    04653
    04667 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    04668 {
    04669         return (_pieColor(dst, x, y, rad, start, end, color, 1));
    04670 }
    04671
    04688 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
    04689                                   Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04690 {
    04691         return (_pieColor(dst, x, y, rad, start, end,
    04692                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
    04693 }
    04694
    04695 /* ------ Trigon */
    04696
    04713 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    04714 {
    04715         Sint16 vx[3];
    04716         Sint16 vy[3];
    04717
    04718         vx[0]=x1;
    04719         vx[1]=x2;
    04720         vx[2]=x3;
    04721         vy[0]=y1;
    04722         vy[1]=y2;
    04723         vy[2]=y3;
    04724
    04725         return(polygonColor(dst,vx,vy,3,color));
    04726 }
    04727
    04745 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    04746                            Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04747 {
    04748         Sint16 vx[3];
    04749         Sint16 vy[3];
    04750
    04751         vx[0]=x1;
    04752         vx[1]=x2;
    04753         vx[2]=x3;
    04754         vy[0]=y1;
    04755         vy[1]=y2;
    04756         vy[2]=y3;
    04757
    04758         return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
    04759 }
    04760
    04761 /* ------ AA-Trigon */
    04762
    04779 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    04780 {
    04781         Sint16 vx[3];
    04782         Sint16 vy[3];
    04783
    04784         vx[0]=x1;
    04785         vx[1]=x2;
    04786         vx[2]=x3;
    04787         vy[0]=y1;
    04788         vy[1]=y2;
    04789         vy[2]=y3;
    04790
    04791         return(aapolygonColor(dst,vx,vy,3,color));
    04792 }
    04793
    04811 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    04812                                  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04813 {
    04814         Sint16 vx[3];
    04815         Sint16 vy[3];
    04816
    04817         vx[0]=x1;
    04818         vx[1]=x2;
    04819         vx[2]=x3;
    04820         vy[0]=y1;
    04821         vy[1]=y2;
    04822         vy[2]=y3;
    04823
    04824         return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
    04825 }
    04826
    04827 /* ------ Filled Trigon */
    04828
    04845 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    04846 {
    04847         Sint16 vx[3];
    04848         Sint16 vy[3];
    04849
    04850         vx[0]=x1;
    04851         vx[1]=x2;
    04852         vx[2]=x3;
    04853         vy[0]=y1;
    04854         vy[1]=y2;
    04855         vy[2]=y3;
    04856
    04857         return(filledPolygonColor(dst,vx,vy,3,color));
    04858 }
    04859
    04879 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    04880                                          Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04881 {
    04882         Sint16 vx[3];
    04883         Sint16 vy[3];
    04884
    04885         vx[0]=x1;
    04886         vx[1]=x2;
    04887         vx[2]=x3;
    04888         vy[0]=y1;
    04889         vy[1]=y2;
    04890         vy[2]=y3;
    04891
    04892         return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
    04893 }
    04894
    04895 /* ---- Polygon */
    04896
    04908 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    04909 {
    04910         int result;
    04911         int i;
    04912         const Sint16 *x1, *y1, *x2, *y2;
    04913
    04914         /*
    04915         * Check visibility of clipping rectangle
    04916         */
    04917         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    04918                 return(0);
    04919         }
    04920
    04921         /*
    04922         * Vertex array NULL check
    04923         */
    04924         if (vx == NULL) {
    04925                 return (-1);
    04926         }
    04927         if (vy == NULL) {
    04928                 return (-1);
    04929         }
    04930
    04931         /*
    04932         * Sanity check
    04933         */
    04934         if (n < 3) {
    04935                 return (-1);
    04936         }
    04937
    04938         /*
    04939         * Pointer setup
    04940         */
    04941         x1 = x2 = vx;
    04942         y1 = y2 = vy;
    04943         x2++;
    04944         y2++;
    04945
    04946         /*
    04947         * Draw
    04948         */
    04949         result = 0;
    04950         for (i = 1; i < n; i++) {
    04951                 result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
    04952                 x1 = x2;
    04953                 y1 = y2;
    04954                 x2++;
    04955                 y2++;
    04956         }
    04957         result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
    04958
    04959         return (result);
    04960 }
    04961
    04976 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04977 {
    04978         /*
    04979         * Draw
    04980         */
    04981         return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    04982 }
    04983
    04984 /* ---- AA-Polygon */
    04985
    04997 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    04998 {
    04999         int result;
    05000         int i;
    05001         const Sint16 *x1, *y1, *x2, *y2;
    05002
    05003         /*
    05004         * Check visibility of clipping rectangle
    05005         */
    05006         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    05007                 return(0);
    05008         }
    05009
    05010         /*
    05011         * Vertex array NULL check
    05012         */
    05013         if (vx == NULL) {
    05014                 return (-1);
    05015         }
    05016         if (vy == NULL) {
    05017                 return (-1);
    05018         }
    05019
    05020         /*
    05021         * Sanity check
    05022         */
    05023         if (n < 3) {
    05024                 return (-1);
    05025         }
    05026
    05027         /*
    05028         * Pointer setup
    05029         */
    05030         x1 = x2 = vx;
    05031         y1 = y2 = vy;
    05032         x2++;
    05033         y2++;
    05034
    05035         /*
    05036         * Draw
    05037         */
    05038         result = 0;
    05039         for (i = 1; i < n; i++) {
    05040                 result |= _aalineColor(dst, *x1, *y1, *x2, *y2, color, 0);
    05041                 x1 = x2;
    05042                 y1 = y2;
    05043                 x2++;
    05044                 y2++;
    05045         }
    05046         result |= _aalineColor(dst, *x1, *y1, *vx, *vy, color, 0);
    05047
    05048         return (result);
    05049 }
    05050
    05065 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    05066 {
    05067         /*
    05068         * Draw
    05069         */
    05070         return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    05071 }
    05072
    05073 /* ---- Filled Polygon */
    05074
    05083 int _gfxPrimitivesCompareInt(const void *a, const void *b)
    05084 {
    05085         return (*(const int *) a) - (*(const int *) b);
    05086 }
    05087
    05093 static int *gfxPrimitivesPolyIntsGlobal = NULL;
    05094
    05100 static int gfxPrimitivesPolyAllocatedGlobal = 0;
    05101
    05117 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
    05118 {
    05119         int result;
    05120         int i;
    05121         int y, xa, xb;
    05122         int miny, maxy;
    05123         int x1, y1;
    05124         int x2, y2;
    05125         int ind1, ind2;
    05126         int ints;
    05127         int *gfxPrimitivesPolyInts = NULL;
    05128         int gfxPrimitivesPolyAllocated = 0;
    05129
    05130         /*
    05131         * Check visibility of clipping rectangle
    05132         */
    05133         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    05134                 return(0);
    05135         }
    05136
    05137         /*
    05138         * Vertex array NULL check
    05139         */
    05140         if (vx == NULL) {
    05141                 return (-1);
    05142         }
    05143         if (vy == NULL) {
    05144                 return (-1);
    05145         }
    05146
    05147         /*
    05148         * Sanity check number of edges
    05149         */
    05150         if (n < 3) {
    05151                 return -1;
    05152         }
    05153
    05154         /*
    05155         * Map polygon cache
    05156         */
    05157         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    05158                 /* Use global cache */
    05159                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    05160                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    05161         } else {
    05162                 /* Use local cache */
    05163                 gfxPrimitivesPolyInts = *polyInts;
    05164                 gfxPrimitivesPolyAllocated = *polyAllocated;
    05165         }
    05166
    05167         /*
    05168         * Allocate temp array, only grow array
    05169         */
    05170         if (!gfxPrimitivesPolyAllocated) {
    05171                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    05172                 gfxPrimitivesPolyAllocated = n;
    05173         } else {
    05174                 if (gfxPrimitivesPolyAllocated < n) {
    05175                         gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    05176                         gfxPrimitivesPolyAllocated = n;
    05177                 }
    05178         }
    05179
    05180         /*
    05181         * Check temp array
    05182         */
    05183         if (gfxPrimitivesPolyInts==NULL) {
    05184                 gfxPrimitivesPolyAllocated = 0;
    05185         }
    05186
    05187         /*
    05188         * Update cache variables
    05189         */
    05190         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    05191                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    05192                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    05193         } else {
    05194                 *polyInts = gfxPrimitivesPolyInts;
    05195                 *polyAllocated = gfxPrimitivesPolyAllocated;
    05196         }
    05197
    05198         /*
    05199         * Check temp array again
    05200         */
    05201         if (gfxPrimitivesPolyInts==NULL) {
    05202                 return(-1);
    05203         }
    05204
    05205         /*
    05206         * Determine Y maxima
    05207         */
    05208         miny = vy[0];
    05209         maxy = vy[0];
    05210         for (i = 1; (i < n); i++) {
    05211                 if (vy[i] < miny) {
    05212                         miny = vy[i];
    05213                 } else if (vy[i] > maxy) {
    05214                         maxy = vy[i];
    05215                 }
    05216         }
    05217
    05218         /*
    05219         * Draw, scanning y
    05220         */
    05221         result = 0;
    05222         for (y = miny; (y <= maxy); y++) {
    05223                 ints = 0;
    05224                 for (i = 0; (i < n); i++) {
    05225                         if (!i) {
    05226                                 ind1 = n - 1;
    05227                                 ind2 = 0;
    05228                         } else {
    05229                                 ind1 = i - 1;
    05230                                 ind2 = i;
    05231                         }
    05232                         y1 = vy[ind1];
    05233                         y2 = vy[ind2];
    05234                         if (y1 < y2) {
    05235                                 x1 = vx[ind1];
    05236                                 x2 = vx[ind2];
    05237                         } else if (y1 > y2) {
    05238                                 y2 = vy[ind1];
    05239                                 y1 = vy[ind2];
    05240                                 x2 = vx[ind1];
    05241                                 x1 = vx[ind2];
    05242                         } else {
    05243                                 continue;
    05244                         }
    05245                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    05246                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    05247                         }
    05248                 }
    05249
    05250                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    05251
    05252                 for (i = 0; (i < ints); i += 2) {
    05253                         xa = gfxPrimitivesPolyInts[i] + 1;
    05254                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    05255                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    05256                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    05257                         result |= hlineColor(dst, xa, xb, y, color);
    05258                 }
    05259         }
    05260
    05261         return (result);
    05262 }
    05263
    05282 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)
    05283 {
    05284         /*
    05285         * Draw
    05286         */
    05287         return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
    05288 }
    05289
    05304 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    05305 {
    05306         /*
    05307         * Draw
    05308         */
    05309         return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
    05310 }
    05311
    05326 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    05327 {
    05328         /*
    05329         * Draw
    05330         */
    05331         return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
    05332 }
    05333
    05347 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy)
    05348 {
    05349         Sint16 left, right, top, bottom;
    05350         Sint16 w;
    05351         Sint16 xtmp;
    05352         int result = 0;
    05353         int texture_x_walker;
    05354         int texture_y_start;
    05355         SDL_Rect source_rect,dst_rect;
    05356         int pixels_written,write_width;
    05357
    05358         /*
    05359         * Check visibility of clipping rectangle
    05360         */
    05361         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    05362                 return(0);
    05363         }
    05364
    05365         /*
    05366         * Swap x1, x2 if required to ensure x1<=x2
    05367         */
    05368         if (x1 > x2) {
    05369                 xtmp = x1;
    05370                 x1 = x2;
    05371                 x2 = xtmp;
    05372         }
    05373
    05374         /*
    05375         * Get clipping boundary and
    05376         * check visibility of hline
    05377         */
    05378         left = dst->clip_rect.x;
    05379         if (x2<left) {
    05380                 return(0);
    05381         }
    05382         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    05383         if (x1>right) {
    05384                 return(0);
    05385         }
    05386         top = dst->clip_rect.y;
    05387         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    05388         if ((y<top) || (y>bottom)) {
    05389                 return (0);
    05390         }
    05391
    05392         /*
    05393         * Clip x
    05394         */
    05395         if (x1 < left) {
    05396                 x1 = left;
    05397         }
    05398         if (x2 > right) {
    05399                 x2 = right;
    05400         }
    05401
    05402         /*
    05403         * Calculate width to draw
    05404         */
    05405         w = x2 - x1 + 1;
    05406
    05407         /*
    05408         * Determine where in the texture we start drawing
    05409         */
    05410         texture_x_walker =   (x1 - texture_dx)  % texture->w;
    05411         if (texture_x_walker < 0){
    05412                 texture_x_walker = texture->w + texture_x_walker ;
    05413         }
    05414
    05415         texture_y_start = (y + texture_dy) % texture->h;
    05416         if (texture_y_start < 0){
    05417                 texture_y_start = texture->h + texture_y_start;
    05418         }
    05419
    05420         // setup the source rectangle; we are only drawing one horizontal line
    05421         source_rect.y = texture_y_start;
    05422         source_rect.x = texture_x_walker;
    05423         source_rect.h = 1;
    05424
    05425         // we will draw to the current y
    05426         dst_rect.y = y;
    05427
    05428         // if there are enough pixels left in the current row of the texture
    05429         // draw it all at once
    05430         if (w <= texture->w -texture_x_walker){
    05431                 source_rect.w = w;
    05432                 source_rect.x = texture_x_walker;
    05433                 dst_rect.x= x1;
    05434                 result = (SDL_BlitSurface  (texture, &source_rect , dst, &dst_rect) == 0);
    05435         } else { // we need to draw multiple times
    05436                 // draw the first segment
    05437                 pixels_written = texture->w  - texture_x_walker;
    05438                 source_rect.w = pixels_written;
    05439                 source_rect.x = texture_x_walker;
    05440                 dst_rect.x= x1;
    05441                 result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
    05442                 write_width = texture->w;
    05443
    05444                 // now draw the rest
    05445                 // set the source x to 0
    05446                 source_rect.x = 0;
    05447                 while (pixels_written < w){
    05448                         if (write_width >= w - pixels_written) {
    05449                                 write_width =  w - pixels_written;
    05450                         }
    05451                         source_rect.w = write_width;
    05452                         dst_rect.x = x1 + pixels_written;
    05453                         result  |= (SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) == 0);
    05454                         pixels_written += write_width;
    05455                 }
    05456         }
    05457
    05458         return result;
    05459 }
    05460
    05484 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n,
    05485                                           SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
    05486 {
    05487         int result;
    05488         int i;
    05489         int y, xa, xb;
    05490         int minx,maxx,miny, maxy;
    05491         int x1, y1;
    05492         int x2, y2;
    05493         int ind1, ind2;
    05494         int ints;
    05495         int *gfxPrimitivesPolyInts = NULL;
    05496         int gfxPrimitivesPolyAllocated = 0;
    05497
    05498         /*
    05499         * Check visibility of clipping rectangle
    05500         */
    05501         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    05502                 return(0);
    05503         }
    05504
    05505         /*
    05506         * Sanity check number of edges
    05507         */
    05508         if (n < 3) {
    05509                 return -1;
    05510         }
    05511
    05512         /*
    05513         * Map polygon cache
    05514         */
    05515         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    05516                 /* Use global cache */
    05517                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    05518                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    05519         } else {
    05520                 /* Use local cache */
    05521                 gfxPrimitivesPolyInts = *polyInts;
    05522                 gfxPrimitivesPolyAllocated = *polyAllocated;
    05523         }
    05524
    05525         /*
    05526         * Allocate temp array, only grow array
    05527         */
    05528         if (!gfxPrimitivesPolyAllocated) {
    05529                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    05530                 gfxPrimitivesPolyAllocated = n;
    05531         } else {
    05532                 if (gfxPrimitivesPolyAllocated < n) {
    05533                         gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    05534                         gfxPrimitivesPolyAllocated = n;
    05535                 }
    05536         }
    05537
    05538         /*
    05539         * Check temp array
    05540         */
    05541         if (gfxPrimitivesPolyInts==NULL) {
    05542                 gfxPrimitivesPolyAllocated = 0;
    05543         }
    05544
    05545         /*
    05546         * Update cache variables
    05547         */
    05548         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    05549                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    05550                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    05551         } else {
    05552                 *polyInts = gfxPrimitivesPolyInts;
    05553                 *polyAllocated = gfxPrimitivesPolyAllocated;
    05554         }
    05555
    05556         /*
    05557         * Check temp array again
    05558         */
    05559         if (gfxPrimitivesPolyInts==NULL) {
    05560                 return(-1);
    05561         }
    05562
    05563         /*
    05564         * Determine X,Y minima,maxima
    05565         */
    05566         miny = vy[0];
    05567         maxy = vy[0];
    05568         minx = vx[0];
    05569         maxx = vx[0];
    05570         for (i = 1; (i < n); i++) {
    05571                 if (vy[i] < miny) {
    05572                         miny = vy[i];
    05573                 } else if (vy[i] > maxy) {
    05574                         maxy = vy[i];
    05575                 }
    05576                 if (vx[i] < minx) {
    05577                         minx = vx[i];
    05578                 } else if (vx[i] > maxx) {
    05579                         maxx = vx[i];
    05580                 }
    05581         }
    05582         if (maxx <0 || minx > dst->w){
    05583                 return -1;
    05584         }
    05585         if (maxy <0 || miny > dst->h){
    05586                 return -1;
    05587         }
    05588
    05589         /*
    05590         * Draw, scanning y
    05591         */
    05592         result = 0;
    05593         for (y = miny; (y <= maxy); y++) {
    05594                 ints = 0;
    05595                 for (i = 0; (i < n); i++) {
    05596                         if (!i) {
    05597                                 ind1 = n - 1;
    05598                                 ind2 = 0;
    05599                         } else {
    05600                                 ind1 = i - 1;
    05601                                 ind2 = i;
    05602                         }
    05603                         y1 = vy[ind1];
    05604                         y2 = vy[ind2];
    05605                         if (y1 < y2) {
    05606                                 x1 = vx[ind1];
    05607                                 x2 = vx[ind2];
    05608                         } else if (y1 > y2) {
    05609                                 y2 = vy[ind1];
    05610                                 y1 = vy[ind2];
    05611                                 x2 = vx[ind1];
    05612                                 x1 = vx[ind2];
    05613                         } else {
    05614                                 continue;
    05615                         }
    05616                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    05617                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    05618                         }
    05619                 }
    05620
    05621                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    05622
    05623                 for (i = 0; (i < ints); i += 2) {
    05624                         xa = gfxPrimitivesPolyInts[i] + 1;
    05625                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    05626                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    05627                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    05628                         result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
    05629                 }
    05630         }
    05631
    05632         return (result);
    05633 }
    05634
    05651 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
    05652 {
    05653         /*
    05654         * Draw
    05655         */
    05656         return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
    05657 }
    05658
    05659
    05660 /* ---- Character */
    05661
    05665 static SDL_Surface *gfxPrimitivesFont[256];
    05666
    05670 static Uint32 gfxPrimitivesFontColor[256];
    05671
    05675 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
    05676
    05680 static Uint32 charWidth = 8;
    05681
    05685 static Uint32 charHeight = 8;
    05686
    05690 static Uint32 charWidthLocal = 8;
    05691
    05695 static Uint32 charHeightLocal = 8;
    05696
    05700 static Uint32 charPitch = 1;
    05701
    05705 static Uint32 charRotation = 0;
    05706
    05710 static Uint32 charSize = 8;
    05711
    05725 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
    05726 {
    05727         int i;
    05728
    05729         if ((fontdata) && (cw) && (ch)) {
    05730                 currentFontdata = fontdata;
    05731                 charWidth = cw;
    05732                 charHeight = ch;
    05733         } else {
    05734                 currentFontdata = gfxPrimitivesFontdata;
    05735                 charWidth = 8;
    05736                 charHeight = 8;
    05737         }
    05738
    05739         charPitch = (charWidth+7)/8;
    05740         charSize = charPitch * charHeight;
    05741
    05742         /* Maybe flip width/height for rendering */
    05743         if ((charRotation==1) || (charRotation==3))
    05744         {
    05745                 charWidthLocal = charHeight;
    05746                 charHeightLocal = charWidth;
    05747         }
    05748         else
    05749         {
    05750                 charWidthLocal = charWidth;
    05751                 charHeightLocal = charHeight;
    05752         }
    05753
    05754         /* Clear character cache */
    05755         for (i = 0; i < 256; i++) {
    05756                 if (gfxPrimitivesFont[i]) {
    05757                         SDL_FreeSurface(gfxPrimitivesFont[i]);
    05758                         gfxPrimitivesFont[i] = NULL;
    05759                 }
    05760         }
    05761 }
    05762
    05771 void gfxPrimitivesSetFontRotation(Uint32 rotation)
    05772 {
    05773         int i;
    05774
    05775         rotation = rotation & 3;
    05776         if (charRotation != rotation)
    05777         {
    05778                 /* Store rotation */
    05779                 charRotation = rotation;
    05780
    05781                 /* Maybe flip width/height for rendering */
    05782                 if ((charRotation==1) || (charRotation==3))
    05783                 {
    05784                         charWidthLocal = charHeight;
    05785                         charHeightLocal = charWidth;
    05786                 }
    05787                 else
    05788                 {
    05789                         charWidthLocal = charWidth;
    05790                         charHeightLocal = charHeight;
    05791                 }
    05792
    05793                 /* Clear character cache */
    05794                 for (i = 0; i < 256; i++) {
    05795                         if (gfxPrimitivesFont[i]) {
    05796                                 SDL_FreeSurface(gfxPrimitivesFont[i]);
    05797                                 gfxPrimitivesFont[i] = NULL;
    05798                         }
    05799                 }
    05800         }
    05801 }
    05802
    05818 int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color)
    05819 {
    05820         Sint16 left, right, top, bottom;
    05821         Sint16 x1, y1, x2, y2;
    05822         SDL_Rect srect;
    05823         SDL_Rect drect;
    05824         int result;
    05825         Uint32 ix, iy;
    05826         const unsigned char *charpos;
    05827         Uint8 *curpos;
    05828         int forced_redraw;
    05829         Uint8 patt, mask;
    05830         Uint8 *linepos;
    05831         Uint32 pitch;
    05832         SDL_Surface *rotatedCharacter;
    05833         Uint32 ci;
    05834
    05835         /*
    05836         * Check visibility of clipping rectangle
    05837         */
    05838         if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
    05839                 return(0);
    05840         }
    05841
    05842         /*
    05843         * Get text and clipping boundary and
    05844         * test if bounding box of character is visible
    05845         */
    05846
    05847         left = dst->clip_rect.x;
    05848         x2 = x + charWidthLocal;
    05849         if (x2<left) {
    05850                 return(0);
    05851         }
    05852         right = dst->clip_rect.x + dst->clip_rect.w - 1;
    05853         x1 = x;
    05854         if (x1>right) {
    05855                 return(0);
    05856         }
    05857         top = dst->clip_rect.y;
    05858         y2 = y + charHeightLocal;
    05859         if (y2<top) {
    05860                 return(0);
    05861         }
    05862         bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
    05863         y1 = y;
    05864         if (y1>bottom) {
    05865                 return(0);
    05866         }
    05867
    05868         /*
    05869         * Setup source rectangle
    05870         */
    05871         srect.x = 0;
    05872         srect.y = 0;
    05873         srect.w = charWidthLocal;
    05874         srect.h = charHeightLocal;
    05875
    05876         /*
    05877         * Setup destination rectangle
    05878         */
    05879         drect.x = x;
    05880         drect.y = y;
    05881         drect.w = charWidthLocal;
    05882         drect.h = charHeightLocal;
    05883
    05884         /* Character index in cache */
    05885         ci = (unsigned char) c;
    05886
    05887         /*
    05888         * Create new charWidth x charHeight bitmap surface if not already present.
    05889         * Might get rotated later.
    05890         */
    05891         if (gfxPrimitivesFont[ci] == NULL) {
    05892                 gfxPrimitivesFont[ci] =
    05893                         SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA,
    05894                         charWidth, charHeight, 32,
    05895                         0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
    05896                 /*
    05897                 * Check pointer
    05898                 */
    05899                 if (gfxPrimitivesFont[ci] == NULL) {
    05900                         return (-1);
    05901                 }
    05902                 /*
    05903                 * Definitely redraw
    05904                 */
    05905                 forced_redraw = 1;
    05906         } else {
    05907                 forced_redraw = 0;
    05908         }
    05909
    05910         /*
    05911         * Check if color has changed
    05912         */
    05913         if ((gfxPrimitivesFontColor[ci] != color) || (forced_redraw)) {
    05914                 /*
    05915                 * Redraw character
    05916                 */
    05917                 SDL_SetAlpha(gfxPrimitivesFont[ci], SDL_SRCALPHA, 255);
    05918                 gfxPrimitivesFontColor[ci] = color;
    05919
    05920                 /* Lock font-surface */
    05921                 if (SDL_LockSurface(gfxPrimitivesFont[ci]) != 0)
    05922                         return (-1);
    05923
    05924                 /*
    05925                 * Variable setup
    05926                 */
    05927                 charpos = currentFontdata + ci * charSize;
    05928                 linepos = (Uint8 *) gfxPrimitivesFont[ci]->pixels;
    05929                 pitch = gfxPrimitivesFont[ci]->pitch;
    05930
    05931                 /*
    05932                 * Drawing loop
    05933                 */
    05934                 patt = 0;
    05935                 for (iy = 0; iy < charHeight; iy++) {
    05936                         mask = 0x00;
    05937                         curpos = linepos;
    05938                         for (ix = 0; ix < charWidth; ix++) {
    05939                                 if (!(mask >>= 1)) {
    05940                                         patt = *charpos++;
    05941                                         mask = 0x80;
    05942                                 }
    05943
    05944                                 if (patt & mask)
    05945                                         *(Uint32 *)curpos = color;
    05946                                 else
    05947                                         *(Uint32 *)curpos = 0;
    05948                                 curpos += 4;
    05949                         }
    05950                         linepos += pitch;
    05951                 }
    05952
    05953                 /* Unlock font-surface */
    05954                 SDL_UnlockSurface(gfxPrimitivesFont[ci]);
    05955
    05956                 /* Maybe rotate and replace cached image */
    05957                 if (charRotation>0)
    05958                 {
    05959                         rotatedCharacter = rotateSurface90Degrees(gfxPrimitivesFont[ci], charRotation);
    05960                         SDL_FreeSurface(gfxPrimitivesFont[ci]);
    05961                         gfxPrimitivesFont[ci] = rotatedCharacter;
    05962                 }
    05963         }
    05964
    05965         /*
    05966         * Draw bitmap onto destination surface
    05967         */
    05968         result = SDL_BlitSurface(gfxPrimitivesFont[ci], &srect, dst, &drect);
    05969
    05970         return (result);
    05971 }
    05972
    05987 int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    05988 {
    05989         /*
    05990         * Draw
    05991         */
    05992         return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    05993 }
    05994
    06009 int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color)
    06010 {
    06011         int result = 0;
    06012         Sint16 curx = x;
    06013         Sint16 cury = y;
    06014         const char *curchar = s;
    06015
    06016         while (*curchar && !result) {
    06017                 result |= characterColor(dst, curx, cury, *curchar, color);
    06018                 switch (charRotation)
    06019                 {
    06020                 case 0:
    06021                         curx += charWidthLocal;
    06022                         break;
    06023                 case 2:
    06024                         curx -= charWidthLocal;
    06025                         break;
    06026                 case 1:
    06027                         cury += charHeightLocal;
    06028                         break;
    06029                 case 3:
    06030                         cury -= charHeightLocal;
    06031                         break;
    06032                 }
    06033                 curchar++;
    06034         }
    06035
    06036         return (result);
    06037 }
    06038
    06053 int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    06054 {
    06055         /*
    06056         * Draw
    06057         */
    06058         return (stringColor(dst, x, y, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    06059 }
    06060
    06061 /* ---- Bezier curve */
    06062
    06072 double _evaluateBezier (double *data, int ndata, double t)
    06073 {
    06074         double mu, result;
    06075         int n,k,kn,nn,nkn;
    06076         double blend,muk,munk;
    06077
    06078         /* Sanity check bounds */
    06079         if (t<0.0) {
    06080                 return(data[0]);
    06081         }
    06082         if (t>=(double)ndata) {
    06083                 return(data[ndata-1]);
    06084         }
    06085
    06086         /* Adjust t to the range 0.0 to 1.0 */
    06087         mu=t/(double)ndata;
    06088
    06089         /* Calculate interpolate */
    06090         n=ndata-1;
    06091         result=0.0;
    06092         muk = 1;
    06093         munk = pow(1-mu,(double)n);
    06094         for (k=0;k<=n;k++) {
    06095                 nn = n;
    06096                 kn = k;
    06097                 nkn = n - k;
    06098                 blend = muk * munk;
    06099                 muk *= mu;
    06100                 munk /= (1-mu);
    06101                 while (nn >= 1) {
    06102                         blend *= nn;
    06103                         nn--;
    06104                         if (kn > 1) {
    06105                                 blend /= (double)kn;
    06106                                 kn--;
    06107                         }
    06108                         if (nkn > 1) {
    06109                                 blend /= (double)nkn;
    06110                                 nkn--;
    06111                         }
    06112                 }
    06113                 result += data[k] * blend;
    06114         }
    06115
    06116         return (result);
    06117 }
    06118
    06131 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
    06132 {
    06133         int result;
    06134         int i;
    06135         double *x, *y, t, stepsize;
    06136         Sint16 x1, y1, x2, y2;
    06137
    06138         /*
    06139         * Sanity check
    06140         */
    06141         if (n < 3) {
    06142                 return (-1);
    06143         }
    06144         if (s < 2) {
    06145                 return (-1);
    06146         }
    06147
    06148         /*
    06149         * Variable setup
    06150         */
    06151         stepsize=(double)1.0/(double)s;
    06152
    06153         /* Transfer vertices into float arrays */
    06154         if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    06155                 return(-1);
    06156         }
    06157         if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    06158                 free(x);
    06159                 return(-1);
    06160         }
    06161         for (i=0; i<n; i++) {
    06162                 x[i]=vx[i];
    06163                 y[i]=vy[i];
    06164         }
    06165         x[n]=vx[0];
    06166         y[n]=vy[0];
    06167
    06168         /*
    06169         * Draw
    06170         */
    06171         result = 0;
    06172         t=0.0;
    06173         x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
    06174         y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
    06175         for (i = 0; i <= (n*s); i++) {
    06176                 t += stepsize;
    06177                 x2=(Sint16)_evaluateBezier(x,n,t);
    06178                 y2=(Sint16)_evaluateBezier(y,n,t);
    06179                 result |= lineColor(dst, x1, y1, x2, y2, color);
    06180                 x1 = x2;
    06181                 y1 = y2;
    06182         }
    06183
    06184         /* Clean up temporary array */
    06185         free(x);
    06186         free(y);
    06187
    06188         return (result);
    06189 }
    06190
    06206 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    06207 {
    06208         /*
    06209         * Draw
    06210         */
    06211         return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    06212 }
    06213
    06214
    06233 int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
    06234 {
    06235         int temp;
    06236
    06237         if (b==NULL) {
    06238                 return(-1);
    06239         }
    06240
    06241         b->x = x1;
    06242         b->y = y1;
    06243
    06244         /* dx = abs(x2-x1), s1 = sign(x2-x1) */
    06245         if ((b->dx = x2 - x1) != 0) {
    06246                 if (b->dx < 0) {
    06247                         b->dx = -b->dx;
    06248                         b->s1 = -1;
    06249                 } else {
    06250                         b->s1 = 1;
    06251                 }
    06252         } else {
    06253                 b->s1 = 0;
    06254         }
    06255
    06256         /* dy = abs(y2-y1), s2 = sign(y2-y1)    */
    06257         if ((b->dy = y2 - y1) != 0) {
    06258                 if (b->dy < 0) {
    06259                         b->dy = -b->dy;
    06260                         b->s2 = -1;
    06261                 } else {
    06262                         b->s2 = 1;
    06263                 }
    06264         } else {
    06265                 b->s2 = 0;
    06266         }
    06267
    06268         if (b->dy > b->dx) {
    06269                 temp = b->dx;
    06270                 b->dx = b->dy;
    06271                 b->dy = temp;
    06272                 b->swapdir = 1;
    06273         } else {
    06274                 b->swapdir = 0;
    06275         }
    06276
    06277         b->count = b->dx;
    06278         b->dy <<= 1;
    06279         b->error = b->dy - b->dx;
    06280         b->dx <<= 1;
    06281
    06282         return(0);
    06283 }
    06284
    06285
    06295 int _bresenhamIterate(SDL_gfxBresenhamIterator *b)
    06296 {
    06297         if (b==NULL) {
    06298                 return (-1);
    06299         }
    06300
    06301         /* last point check */
    06302         if (b->count <= 0) {
    06303                 return (2);
    06304         }
    06305
    06306         while (b->error >= 0) {
    06307                 if (b->swapdir) {
    06308                         b->x += b->s1;
    06309                 } else  {
    06310                         b->y += b->s2;
    06311                 }
    06312
    06313                 b->error -= b->dx;
    06314         }
    06315
    06316         if (b->swapdir) {
    06317                 b->y += b->s2;
    06318         } else {
    06319                 b->x += b->s1;
    06320         }
    06321
    06322         b->error += b->dy;
    06323         b->count--;
    06324
    06325         /* count==0 indicates "end-of-line" */
    06326         return ((b->count) ? 0 : 1);
    06327 }
    06328
    06329
    06338 void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
    06339 {
    06340         int p;
    06341         d1 = -d1;
    06342
    06343         /*
    06344         * Lock the surface
    06345         */
    06346         if (SDL_MUSTLOCK(m->dst)) {
    06347                 SDL_LockSurface(m->dst);
    06348         }
    06349
    06350         for (p = 0; p <= m->u; p++) {
    06351
    06352                 pixelColorNolock(m->dst, x, y, m->color);
    06353
    06354                 if (d1 <= m->kt) {
    06355                         if (m->oct2 == 0) {
    06356                                 x++;
    06357                         } else {
    06358                                 if (m->quad4 == 0) {
    06359                                         y++;
    06360                                 } else {
    06361                                         y--;
    06362                                 }
    06363                         }
    06364                         d1 += m->kv;
    06365                 } else {
    06366                         x++;
    06367                         if (m->quad4 == 0) {
    06368                                 y++;
    06369                         } else {
    06370                                 y--;
    06371                         }
    06372                         d1 += m->kd;
    06373                 }
    06374         }
    06375
    06376         /* Unlock surface */
    06377         if (SDL_MUSTLOCK(m->dst)) {
    06378                 SDL_UnlockSurface(m->dst);
    06379         }
    06380
    06381         m->tempx = x;
    06382         m->tempy = y;
    06383 }
    06384
    06400 void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter,
    06401                                           Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
    06402                                           Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
    06403 {
    06404         int atemp1, atemp2;
    06405         int ftmp1, ftmp2;
    06406         Uint16 m1x, m1y, m2x, m2y;
    06407         Uint16 fix, fiy, lax, lay, curx, cury;
    06408         Uint16 px[4], py[4];
    06409         SDL_gfxBresenhamIterator b;
    06410
    06411         if (miter > 1) {
    06412                 if (m->first1x != -32768) {
    06413                         fix = (m->first1x + m->first2x) / 2;
    06414                         fiy = (m->first1y + m->first2y) / 2;
    06415                         lax = (m->last1x + m->last2x) / 2;
    06416                         lay = (m->last1y + m->last2y) / 2;
    06417                         curx = (ml1x + ml2x) / 2;
    06418                         cury = (ml1y + ml2y) / 2;
    06419
    06420                         atemp1 = (fix - curx);
    06421                         atemp2 = (fiy - cury);
    06422                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    06423                         atemp1 = (lax - curx);
    06424                         atemp2 = (lay - cury);
    06425                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    06426
    06427                         if (ftmp1 <= ftmp2) {
    06428                                 m1x = m->first1x;
    06429                                 m1y = m->first1y;
    06430                                 m2x = m->first2x;
    06431                                 m2y = m->first2y;
    06432                         } else {
    06433                                 m1x = m->last1x;
    06434                                 m1y = m->last1y;
    06435                                 m2x = m->last2x;
    06436                                 m2y = m->last2y;
    06437                         }
    06438
    06439                         atemp1 = (m2x - ml2x);
    06440                         atemp2 = (m2y - ml2y);
    06441                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    06442                         atemp1 = (m2x - ml2bx);
    06443                         atemp2 = (m2y - ml2by);
    06444                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    06445
    06446                         if (ftmp2 >= ftmp1) {
    06447                                 ftmp1 = ml2bx;
    06448                                 ftmp2 = ml2by;
    06449                                 ml2bx = ml2x;
    06450                                 ml2by = ml2y;
    06451                                 ml2x = ftmp1;
    06452                                 ml2y = ftmp2;
    06453                                 ftmp1 = ml1bx;
    06454                                 ftmp2 = ml1by;
    06455                                 ml1bx = ml1x;
    06456                                 ml1by = ml1y;
    06457                                 ml1x = ftmp1;
    06458                                 ml1y = ftmp2;
    06459                         }
    06460
    06461                         /*
    06462                         * Lock the surface
    06463                         */
    06464                         if (SDL_MUSTLOCK(m->dst)) {
    06465                                 SDL_LockSurface(m->dst);
    06466                         }
    06467
    06468                         _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
    06469                         do {
    06470                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
    06471                         } while (_bresenhamIterate(&b)==0);
    06472
    06473                         _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
    06474                         do {
    06475                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
    06476                         } while (_bresenhamIterate(&b)==0);
    06477
    06478                         _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
    06479                         do {
    06480                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
    06481                         } while (_bresenhamIterate(&b)==0);
    06482
    06483                         _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
    06484                         do {
    06485                                 pixelColorNolock(m->dst, b.x, b.y, m->color);
    06486                         } while (_bresenhamIterate(&b)==0);
    06487
    06488                         /* Unlock surface */
    06489                         if (SDL_MUSTLOCK(m->dst)) {
    06490                                 SDL_UnlockSurface(m->dst);
    06491                         }
    06492
    06493                         px[0] = m1x;
    06494                         px[1] = m2x;
    06495                         px[2] = ml1bx;
    06496                         px[3] = ml2bx;
    06497                         py[0] = m1y;
    06498                         py[1] = m2y;
    06499                         py[2] = ml1by;
    06500                         py[3] = ml2by;
    06501                         polygonColor(m->dst, px, py, 4, m->color);
    06502                 }
    06503         }
    06504
    06505         m->last1x = ml1x;
    06506         m->last1y = ml1y;
    06507         m->last2x = ml2x;
    06508         m->last2y = ml2y;
    06509         m->first1x = ml1bx;
    06510         m->first1y = ml1by;
    06511         m->first2x = ml2bx;
    06512         m->first2y = ml2by;
    06513 }
    06514
    06515
    06516 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
    06517
    06532 void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
    06533 {
    06534         float offset = width / 2.f;
    06535
    06536         Sint16 temp;
    06537         Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
    06538
    06539         int d0, d1;             /* difference terms d0=perpendicular to line, d1=along line */
    06540
    06541         int q;                  /* pel counter,q=perpendicular to line */
    06542         int tmp;
    06543
    06544         int dd;                 /* distance along line */
    06545         int tk;                 /* thickness threshold */
    06546         double ang;             /* angle for initial point calculation */
    06547         double sang, cang;
    06548
    06549         /* Initialisation */
    06550         m->u = x2 - x1; /* delta x */
    06551         m->v = y2 - y1; /* delta y */
    06552
    06553         if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
    06554                 temp = x1;
    06555                 x1 = x2;
    06556                 x2 = temp;
    06557                 temp = y1;
    06558                 y1 = y2;
    06559                 y1 = temp;
    06560                 m->u *= -1;
    06561                 m->v *= -1;
    06562         }
    06563
    06564         if (m->v < 0) { /* swap to 1st quadrant and flag */
    06565                 m->v *= -1;
    06566                 m->quad4 = 1;
    06567         } else {
    06568                 m->quad4 = 0;
    06569         }
    06570
    06571         if (m->v > m->u) {      /* swap things if in 2 octant */
    06572                 tmp = m->u;
    06573                 m->u = m->v;
    06574                 m->v = tmp;
    06575                 m->oct2 = 1;
    06576         } else {
    06577                 m->oct2 = 0;
    06578         }
    06579
    06580         m->ku = m->u + m->u;    /* change in l for square shift */
    06581         m->kv = m->v + m->v;    /* change in d for square shift */
    06582         m->kd = m->kv - m->ku;  /* change in d for diagonal shift */
    06583         m->kt = m->u - m->kv;   /* diag/square decision threshold */
    06584
    06585         d0 = 0;
    06586         d1 = 0;
    06587         dd = 0;
    06588
    06589         ang = atan((double) m->v / (double) m->u);      /* calc new initial point - offset both sides of ideal */
    06590         sang = sin(ang);
    06591         cang = cos(ang);
    06592
    06593         if (m->oct2 == 0) {
    06594                 ptx = x1 + (Sint16)lrint(offset * sang);
    06595                 if (m->quad4 == 0) {
    06596                         pty = y1 - (Sint16)lrint(offset * cang);
    06597                 } else {
    06598                         pty = y1 + (Sint16)lrint(offset * cang);
    06599                 }
    06600         } else {
    06601                 ptx = x1 - (Sint16)lrint(offset * cang);
    06602                 if (m->quad4 == 0) {
    06603                         pty = y1 + (Sint16)lrint(offset * sang);
    06604                 } else {
    06605                         pty = y1 - (Sint16)lrint(offset * sang);
    06606                 }
    06607         }
    06608
    06609         /* used here for constant thickness line */
    06610         tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
    06611
    06612         if (miter == 0) {
    06613                 m->first1x = -32768;
    06614                 m->first1y = -32768;
    06615                 m->first2x = -32768;
    06616                 m->first2y = -32768;
    06617                 m->last1x = -32768;
    06618                 m->last1y = -32768;
    06619                 m->last2x = -32768;
    06620                 m->last2y = -32768;
    06621         }
    06622         ptxx = ptx;
    06623         ptxy = pty;
    06624
    06625         for (q = 0; dd <= tk; q++) {    /* outer loop, stepping perpendicular to line */
    06626
    06627                 _murphyParaline(m, ptx, pty, d1);       /* call to inner loop - right edge */
    06628                 if (q == 0) {
    06629                         ml1x = ptx;
    06630                         ml1y = pty;
    06631                         ml1bx = m->tempx;
    06632                         ml1by = m->tempy;
    06633                 } else {
    06634                         ml2x = ptx;
    06635                         ml2y = pty;
    06636                         ml2bx = m->tempx;
    06637                         ml2by = m->tempy;
    06638                 }
    06639                 if (d0 < m->kt) {       /* square move */
    06640                         if (m->oct2 == 0) {
    06641                                 if (m->quad4 == 0) {
    06642                                         pty++;
    06643                                 } else {
    06644                                         pty--;
    06645                                 }
    06646                         } else {
    06647                                 ptx++;
    06648                         }
    06649                 } else {        /* diagonal move */
    06650                         dd += m->kv;
    06651                         d0 -= m->ku;
    06652                         if (d1 < m->kt) {       /* normal diagonal */
    06653                                 if (m->oct2 == 0) {
    06654                                         ptx--;
    06655                                         if (m->quad4 == 0) {
    06656                                                 pty++;
    06657                                         } else {
    06658                                                 pty--;
    06659                                         }
    06660                                 } else {
    06661                                         ptx++;
    06662                                         if (m->quad4 == 0) {
    06663                                                 pty--;
    06664                                         } else {
    06665                                                 pty++;
    06666                                         }
    06667                                 }
    06668                                 d1 += m->kv;
    06669                         } else {        /* double square move, extra parallel line */
    06670                                 if (m->oct2 == 0) {
    06671                                         ptx--;
    06672                                 } else {
    06673                                         if (m->quad4 == 0) {
    06674                                                 pty--;
    06675                                         } else {
    06676                                                 pty++;
    06677                                         }
    06678                                 }
    06679                                 d1 += m->kd;
    06680                                 if (dd > tk) {
    06681                                         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    06682                                         return; /* breakout on the extra line */
    06683                                 }
    06684                                 _murphyParaline(m, ptx, pty, d1);
    06685                                 if (m->oct2 == 0) {
    06686                                         if (m->quad4 == 0) {
    06687                                                 pty++;
    06688                                         } else {
    06689
    06690                                                 pty--;
    06691                                         }
    06692                                 } else {
    06693                                         ptx++;
    06694                                 }
    06695                         }
    06696                 }
    06697                 dd += m->ku;
    06698                 d0 += m->kv;
    06699         }
    06700
    06701         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    06702 }
    06703
    06704
    06718 int thickLineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
    06719 {
    06720         SDL_gfxMurphyIterator m;
    06721
    06722         if (dst == NULL) return -1;
    06723         if (width < 1) return -1;
    06724
    06725         m.dst = dst;
    06726         m.color = color;
    06727
    06728         _murphyWideline(&m, x1, y1, x2, y2, width, 0);
    06729         _murphyWideline(&m, x1, y1, x2, y2, width, 1);
    06730
    06731         return(0);
    06732 }
    06733
    06750 int thickLineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    06751 {
    06752         return (thickLineColor(dst, x1, y1, x2, y2, width,
    06753                 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
    06754 }