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