SDL_gfx: I:/Sources/sdlgfx/SDL_gfxPrimitives.c Source File

SDL_gfx 2.0.25

- Main Page
- Data Structures
- Files

- File List
- Globals

I:/Sources/sdlgfx/SDL_gfxPrimitives.c
Go to the documentation of this file.

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