SDL2_gfx 1.0.1 GraphicsprimitivesandsurfacefunctionsforSDL2

- Main Page
- Data Structures
- Files

- File List
- Globals

I:/Sources/sdl2gfx/SDL2_gfxPrimitives.c
Go to the documentation of this file.

    00001 /*
    00002
    00003 SDL2_gfxPrimitives.c: graphics primitives for SDL2 renderers
    00004
    00005 Copyright (C) 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 "SDL2_gfxPrimitives.h"
    00036 #include "SDL2_rotozoom.h"
    00037 #include "SDL2_gfxPrimitives_font.h"
    00038
    00039 /* ---- Structures */
    00040
    00044 typedef struct {
    00045         Sint16 x, y;
    00046         int dx, dy, s1, s2, swapdir, error;
    00047         Uint32 count;
    00048 } SDL2_gfxBresenhamIterator;
    00049
    00053 typedef struct {
    00054         SDL_Renderer *renderer;
    00055         int u, v;               /* delta x , delta y */
    00056         int ku, kt, kv, kd;     /* loop constants */
    00057         int oct2;
    00058         int quad4;
    00059         Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
    00060 } SDL2_gfxMurphyIterator;
    00061
    00062 /* ---- Pixel */
    00063
    00073 int pixel(SDL_Renderer *renderer, Sint16 x, Sint16 y)
    00074 {
    00075         return SDL_RenderDrawPoint(renderer, x, y);
    00076 }
    00077
    00088 int pixelColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint32 color)
    00089 {
    00090         Uint8 *c = (Uint8 *)&color;
    00091         return pixelRGBA(renderer, x, y, c[0], c[1], c[2], c[3]);
    00092 }
    00093
    00107 int pixelRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00108 {
    00109         int result = 0;
    00110         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00111         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00112         result |= SDL_RenderDrawPoint(renderer, x, y);
    00113         return result;
    00114 }
    00115
    00130 int pixelRGBAWeight(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint32 weight)
    00131 {
    00132         /*
    00133         * Modify Alpha by weight
    00134         */
    00135         Uint32 ax = a;
    00136         ax = ((ax * weight) >> 8);
    00137         if (ax > 255) {
    00138                 a = 255;
    00139         } else {
    00140                 a = (Uint8)(ax & 0x000000ff);
    00141         }
    00142
    00143         return pixelRGBA(renderer, x, y, r, g, b, a);
    00144 }
    00145
    00146 /* ---- Hline */
    00147
    00158 int hline(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y)
    00159 {
    00160         return SDL_RenderDrawLine(renderer, x1, y, x2, y);;
    00161 }
    00162
    00163
    00175 int hlineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
    00176 {
    00177         Uint8 *c = (Uint8 *)&color;
    00178         return hlineRGBA(renderer, x1, x2, y, c[0], c[1], c[2], c[3]);
    00179 }
    00180
    00195 int hlineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00196 {
    00197         int result = 0;
    00198         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00199         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00200         result |= SDL_RenderDrawLine(renderer, x1, y, x2, y);
    00201         return result;
    00202 }
    00203
    00204 /* ---- Vline */
    00205
    00217 int vlineColor(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
    00218 {
    00219         Uint8 *c = (Uint8 *)&color;
    00220         return vlineRGBA(renderer, x, y1, y2, c[0], c[1], c[2], c[3]);
    00221 }
    00222
    00237 int vlineRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00238 {
    00239         int result = 0;
    00240         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00241         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00242         result |= SDL_RenderDrawLine(renderer, x, y1, x, y2);
    00243         return result;
    00244 }
    00245
    00246 /* ---- Rectangle */
    00247
    00260 int rectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00261 {
    00262         Uint8 *c = (Uint8 *)&color;
    00263         return rectangleRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
    00264 }
    00265
    00281 int rectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00282 {
    00283         int result;
    00284         Sint16 tmp;
    00285         SDL_Rect rect;
    00286
    00287         /*
    00288         * Test for special cases of straight lines or single point
    00289         */
    00290         if (x1 == x2) {
    00291                 if (y1 == y2) {
    00292                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00293                 } else {
    00294                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00295                 }
    00296         } else {
    00297                 if (y1 == y2) {
    00298                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00299                 }
    00300         }
    00301
    00302         /*
    00303         * Swap x1, x2 if required
    00304         */
    00305         if (x1 > x2) {
    00306                 tmp = x1;
    00307                 x1 = x2;
    00308                 x2 = tmp;
    00309         }
    00310
    00311         /*
    00312         * Swap y1, y2 if required
    00313         */
    00314         if (y1 > y2) {
    00315                 tmp = y1;
    00316                 y1 = y2;
    00317                 y2 = tmp;
    00318         }
    00319
    00320         /*
    00321         * Create destination rect
    00322         */
    00323         rect.x = x1;
    00324         rect.y = y1;
    00325         rect.w = x2 - x1;
    00326         rect.h = y2 - y1;
    00327
    00328         /*
    00329         * Draw
    00330         */
    00331         result = 0;
    00332         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00333         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00334         result |= SDL_RenderDrawRect(renderer, &rect);
    00335         return result;
    00336 }
    00337
    00338 /* ---- Rounded Rectangle */
    00339
    00353 int roundedRectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
    00354 {
    00355         Uint8 *c = (Uint8 *)&color;
    00356         return roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
    00357 }
    00358
    00375 int roundedRectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00376 {
    00377         int result = 0;
    00378         Sint16 tmp;
    00379         Sint16 w, h;
    00380         Sint16 xx1, xx2;
    00381         Sint16 yy1, yy2;
    00382
    00383         /*
    00384         * Check renderer
    00385         */
    00386         if (renderer == NULL)
    00387         {
    00388                 return -1;
    00389         }
    00390
    00391         /*
    00392         * Check radius vor valid range
    00393         */
    00394         if (rad < 0) {
    00395                 return -1;
    00396         }
    00397
    00398         /*
    00399         * Special case - no rounding
    00400         */
    00401         if (rad <= 1) {
    00402                 return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
    00403         }
    00404
    00405         /*
    00406         * Test for special cases of straight lines or single point
    00407         */
    00408         if (x1 == x2) {
    00409                 if (y1 == y2) {
    00410                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00411                 } else {
    00412                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00413                 }
    00414         } else {
    00415                 if (y1 == y2) {
    00416                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00417                 }
    00418         }
    00419
    00420         /*
    00421         * Swap x1, x2 if required
    00422         */
    00423         if (x1 > x2) {
    00424                 tmp = x1;
    00425                 x1 = x2;
    00426                 x2 = tmp;
    00427         }
    00428
    00429         /*
    00430         * Swap y1, y2 if required
    00431         */
    00432         if (y1 > y2) {
    00433                 tmp = y1;
    00434                 y1 = y2;
    00435                 y2 = tmp;
    00436         }
    00437
    00438         /*
    00439         * Calculate width&height
    00440         */
    00441         w = x2 - x1;
    00442         h = y2 - y1;
    00443
    00444         /*
    00445         * Maybe adjust radius
    00446         */
    00447         if ((rad * 2) > w)
    00448         {
    00449                 rad = w / 2;
    00450         }
    00451         if ((rad * 2) > h)
    00452         {
    00453                 rad = h / 2;
    00454         }
    00455
    00456         /*
    00457         * Draw corners
    00458         */
    00459         xx1 = x1 + rad;
    00460         xx2 = x2 - rad;
    00461         yy1 = y1 + rad;
    00462         yy2 = y2 - rad;
    00463         result |= arcRGBA(renderer, xx1, yy1, rad, 180, 270, r, g, b, a);
    00464         result |= arcRGBA(renderer, xx2, yy1, rad, 270, 360, r, g, b, a);
    00465         result |= arcRGBA(renderer, xx1, yy2, rad,  90, 180, r, g, b, a);
    00466         result |= arcRGBA(renderer, xx2, yy2, rad,   0,  90, r, g, b, a);
    00467
    00468         /*
    00469         * Draw lines
    00470         */
    00471         if (xx1 <= xx2) {
    00472                 result |= hlineRGBA(renderer, xx1, xx2, y1, r, g, b, a);
    00473                 result |= hlineRGBA(renderer, xx1, xx2, y2, r, g, b, a);
    00474         }
    00475         if (yy1 <= yy2) {
    00476                 result |= vlineRGBA(renderer, x1, yy1, yy2, r, g, b, a);
    00477                 result |= vlineRGBA(renderer, x2, yy1, yy2, r, g, b, a);
    00478         }
    00479
    00480         return result;
    00481 }
    00482
    00483 /* ---- Rounded Box */
    00484
    00498 int roundedBoxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
    00499 {
    00500         Uint8 *c = (Uint8 *)&color;
    00501         return roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
    00502 }
    00503
    00520 int roundedBoxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2,
    00521         Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00522 {
    00523         int result;
    00524         Sint16 w, h, r2, tmp;
    00525         Sint16 cx = 0;
    00526         Sint16 cy = rad;
    00527         Sint16 ocx = (Sint16) 0xffff;
    00528         Sint16 ocy = (Sint16) 0xffff;
    00529         Sint16 df = 1 - rad;
    00530         Sint16 d_e = 3;
    00531         Sint16 d_se = -2 * rad + 5;
    00532         Sint16 xpcx, xmcx, xpcy, xmcy;
    00533         Sint16 ypcy, ymcy, ypcx, ymcx;
    00534         Sint16 x, y, dx, dy;
    00535
    00536         /*
    00537         * Check destination renderer
    00538         */
    00539         if (renderer == NULL)
    00540         {
    00541                 return -1;
    00542         }
    00543
    00544         /*
    00545         * Check radius vor valid range
    00546         */
    00547         if (rad < 0) {
    00548                 return -1;
    00549         }
    00550
    00551         /*
    00552         * Special case - no rounding
    00553         */
    00554         if (rad <= 1) {
    00555                 return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
    00556         }
    00557
    00558         /*
    00559         * Test for special cases of straight lines or single point
    00560         */
    00561         if (x1 == x2) {
    00562                 if (y1 == y2) {
    00563                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00564                 } else {
    00565                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00566                 }
    00567         } else {
    00568                 if (y1 == y2) {
    00569                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00570                 }
    00571         }
    00572
    00573         /*
    00574         * Swap x1, x2 if required
    00575         */
    00576         if (x1 > x2) {
    00577                 tmp = x1;
    00578                 x1 = x2;
    00579                 x2 = tmp;
    00580         }
    00581
    00582         /*
    00583         * Swap y1, y2 if required
    00584         */
    00585         if (y1 > y2) {
    00586                 tmp = y1;
    00587                 y1 = y2;
    00588                 y2 = tmp;
    00589         }
    00590
    00591         /*
    00592         * Calculate width&height
    00593         */
    00594         w = x2 - x1 + 1;
    00595         h = y2 - y1 + 1;
    00596
    00597         /*
    00598         * Maybe adjust radius
    00599         */
    00600         r2 = rad + rad;
    00601         if (r2 > w)
    00602         {
    00603                 rad = w / 2;
    00604                 r2 = rad + rad;
    00605         }
    00606         if (r2 > h)
    00607         {
    00608                 rad = h / 2;
    00609         }
    00610
    00611         /* Setup filled circle drawing for corners */
    00612         x = x1 + rad;
    00613         y = y1 + rad;
    00614         dx = x2 - x1 - rad - rad;
    00615         dy = y2 - y1 - rad - rad;
    00616
    00617         /*
    00618         * Set color
    00619         */
    00620         result = 0;
    00621         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00622         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00623
    00624         /*
    00625         * Draw corners
    00626         */
    00627         do {
    00628                 xpcx = x + cx;
    00629                 xmcx = x - cx;
    00630                 xpcy = x + cy;
    00631                 xmcy = x - cy;
    00632                 if (ocy != cy) {
    00633                         if (cy > 0) {
    00634                                 ypcy = y + cy;
    00635                                 ymcy = y - cy;
    00636                                 result |= hline(renderer, xmcx, xpcx + dx, ypcy + dy);
    00637                                 result |= hline(renderer, xmcx, xpcx + dx, ymcy);
    00638                         } else {
    00639                                 result |= hline(renderer, xmcx, xpcx + dx, y);
    00640                         }
    00641                         ocy = cy;
    00642                 }
    00643                 if (ocx != cx) {
    00644                         if (cx != cy) {
    00645                                 if (cx > 0) {
    00646                                         ypcx = y + cx;
    00647                                         ymcx = y - cx;
    00648                                         result |= hline(renderer, xmcy, xpcy + dx, ymcx);
    00649                                         result |= hline(renderer, xmcy, xpcy + dx, ypcx + dy);
    00650                                 } else {
    00651                                         result |= hline(renderer, xmcy, xpcy + dx, y);
    00652                                 }
    00653                         }
    00654                         ocx = cx;
    00655                 }
    00656
    00657                 /*
    00658                 * Update
    00659                 */
    00660                 if (df < 0) {
    00661                         df += d_e;
    00662                         d_e += 2;
    00663                         d_se += 2;
    00664                 } else {
    00665                         df += d_se;
    00666                         d_e += 2;
    00667                         d_se += 4;
    00668                         cy--;
    00669                 }
    00670                 cx++;
    00671         } while (cx <= cy);
    00672
    00673         /* Inside */
    00674         if (dx > 0 && dy > 0) {
    00675                 result |= boxRGBA(renderer, x1, y1 + rad + 1, x2, y2 - rad, r, g, b, a);
    00676         }
    00677
    00678         return (result);
    00679 }
    00680
    00681 /* ---- Box */
    00682
    00695 int boxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00696 {
    00697         Uint8 *c = (Uint8 *)&color;
    00698         return boxRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
    00699 }
    00700
    00716 int boxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00717 {
    00718         int result;
    00719         Sint16 tmp;
    00720         SDL_Rect rect;
    00721
    00722         /*
    00723         * Test for special cases of straight lines or single point
    00724         */
    00725         if (x1 == x2) {
    00726                 if (y1 == y2) {
    00727                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00728                 } else {
    00729                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00730                 }
    00731         } else {
    00732                 if (y1 == y2) {
    00733                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00734                 }
    00735         }
    00736
    00737         /*
    00738         * Swap x1, x2 if required
    00739         */
    00740         if (x1 > x2) {
    00741                 tmp = x1;
    00742                 x1 = x2;
    00743                 x2 = tmp;
    00744         }
    00745
    00746         /*
    00747         * Swap y1, y2 if required
    00748         */
    00749         if (y1 > y2) {
    00750                 tmp = y1;
    00751                 y1 = y2;
    00752                 y2 = tmp;
    00753         }
    00754
    00755         /*
    00756         * Create destination rect
    00757         */
    00758         rect.x = x1;
    00759         rect.y = y1;
    00760         rect.w = x2 - x1 + 1;
    00761         rect.h = y2 - y1 + 1;
    00762
    00763         /*
    00764         * Draw
    00765         */
    00766         result = 0;
    00767         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00768         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00769         result |= SDL_RenderFillRect(renderer, &rect);
    00770         return result;
    00771 }
    00772
    00773 /* ----- Line */
    00774
    00786 int line(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
    00787 {
    00788         /*
    00789         * Draw
    00790         */
    00791         return SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
    00792 }
    00793
    00806 int lineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00807 {
    00808         Uint8 *c = (Uint8 *)&color;
    00809         return lineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
    00810 }
    00811
    00827 int lineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00828 {
    00829         /*
    00830         * Draw
    00831         */
    00832         int result = 0;
    00833         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00834         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00835         result |= SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
    00836         return result;
    00837 }
    00838
    00839 /* ---- AA Line */
    00840
    00841 #define AAlevels 256
    00842 #define AAbits 8
    00843
    00867 int _aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
    00868 {
    00869         Sint32 xx0, yy0, xx1, yy1;
    00870         int result;
    00871         Uint32 intshift, erracc, erradj;
    00872         Uint32 erracctmp, wgt, wgtcompmask;
    00873         int dx, dy, tmp, xdir, y0p1, x0pxdir;
    00874
    00875         /*
    00876         * Keep on working with 32bit numbers
    00877         */
    00878         xx0 = x1;
    00879         yy0 = y1;
    00880         xx1 = x2;
    00881         yy1 = y2;
    00882
    00883         /*
    00884         * Reorder points to make dy positive
    00885         */
    00886         if (yy0 > yy1) {
    00887                 tmp = yy0;
    00888                 yy0 = yy1;
    00889                 yy1 = tmp;
    00890                 tmp = xx0;
    00891                 xx0 = xx1;
    00892                 xx1 = tmp;
    00893         }
    00894
    00895         /*
    00896         * Calculate distance
    00897         */
    00898         dx = xx1 - xx0;
    00899         dy = yy1 - yy0;
    00900
    00901         /*
    00902         * Adjust for negative dx and set xdir
    00903         */
    00904         if (dx >= 0) {
    00905                 xdir = 1;
    00906         } else {
    00907                 xdir = -1;
    00908                 dx = (-dx);
    00909         }
    00910
    00911         /*
    00912         * Check for special cases
    00913         */
    00914         if (dx == 0) {
    00915                 /*
    00916                 * Vertical line
    00917                 */
    00918                 if (draw_endpoint)
    00919                 {
    00920                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00921                 } else {
    00922                         if (dy > 0) {
    00923                                 return (vlineRGBA(renderer, x1, yy0, yy0+dy, r, g, b, a));
    00924                         } else {
    00925                                 return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00926                         }
    00927                 }
    00928         } else if (dy == 0) {
    00929                 /*
    00930                 * Horizontal line
    00931                 */
    00932                 if (draw_endpoint)
    00933                 {
    00934                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00935                 } else {
    00936                         if (dx > 0) {
    00937                                 return (hlineRGBA(renderer, xx0, xx0+dx, y1, r, g, b, a));
    00938                         } else {
    00939                                 return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00940                         }
    00941                 }
    00942         } else if ((dx == dy) && (draw_endpoint)) {
    00943                 /*
    00944                 * Diagonal line (with endpoint)
    00945                 */
    00946                 return (lineRGBA(renderer, x1, y1, x2, y2,  r, g, b, a));
    00947         }
    00948
    00949
    00950         /*
    00951         * Line is not horizontal, vertical or diagonal (with endpoint)
    00952         */
    00953         result = 0;
    00954
    00955         /*
    00956         * Zero accumulator
    00957         */
    00958         erracc = 0;
    00959
    00960         /*
    00961         * # of bits by which to shift erracc to get intensity level
    00962         */
    00963         intshift = 32 - AAbits;
    00964
    00965         /*
    00966         * Mask used to flip all bits in an intensity weighting
    00967         */
    00968         wgtcompmask = AAlevels - 1;
    00969
    00970         /*
    00971         * Draw the initial pixel in the foreground color
    00972         */
    00973         result |= pixelRGBA(renderer, x1, y1, r, g, b, a);
    00974
    00975         /*
    00976         * x-major or y-major?
    00977         */
    00978         if (dy > dx) {
    00979
    00980                 /*
    00981                 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
    00982                 * X advances every time Y advances 1 pixel, truncating the result so that
    00983                 * we won't overrun the endpoint along the X axis
    00984                 */
    00985                 /*
    00986                 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
    00987                 */
    00988                 erradj = ((dx << 16) / dy) << 16;
    00989
    00990                 /*
    00991                 * draw all pixels other than the first and last
    00992                 */
    00993                 x0pxdir = xx0 + xdir;
    00994                 while (--dy) {
    00995                         erracctmp = erracc;
    00996                         erracc += erradj;
    00997                         if (erracc <= erracctmp) {
    00998                                 /*
    00999                                 * rollover in error accumulator, x coord advances
    01000                                 */
    01001                                 xx0 = x0pxdir;
    01002                                 x0pxdir += xdir;
    01003                         }
    01004                         yy0++;          /* y-major so always advance Y */
    01005
    01006                         /*
    01007                         * the AAbits most significant bits of erracc give us the intensity
    01008                         * weighting for this pixel, and the complement of the weighting for
    01009                         * the paired pixel.
    01010                         */
    01011                         wgt = (erracc >> intshift) & 255;
    01012                         result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
    01013                         result |= pixelRGBAWeight (renderer, x0pxdir, yy0, r, g, b, a, wgt);
    01014                 }
    01015
    01016         } else {
    01017
    01018                 /*
    01019                 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
    01020                 * that Y advances each time X advances 1 pixel, truncating the result so
    01021                 * that we won't overrun the endpoint along the X axis.
    01022                 */
    01023                 /*
    01024                 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
    01025                 */
    01026                 erradj = ((dy << 16) / dx) << 16;
    01027
    01028                 /*
    01029                 * draw all pixels other than the first and last
    01030                 */
    01031                 y0p1 = yy0 + 1;
    01032                 while (--dx) {
    01033
    01034                         erracctmp = erracc;
    01035                         erracc += erradj;
    01036                         if (erracc <= erracctmp) {
    01037                                 /*
    01038                                 * Accumulator turned over, advance y
    01039                                 */
    01040                                 yy0 = y0p1;
    01041                                 y0p1++;
    01042                         }
    01043                         xx0 += xdir;    /* x-major so always advance X */
    01044                         /*
    01045                         * the AAbits most significant bits of erracc give us the intensity
    01046                         * weighting for this pixel, and the complement of the weighting for
    01047                         * the paired pixel.
    01048                         */
    01049                         wgt = (erracc >> intshift) & 255;
    01050                         result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
    01051                         result |= pixelRGBAWeight (renderer, xx0, y0p1, r, g, b, a, wgt);
    01052                 }
    01053         }
    01054
    01055         /*
    01056         * Do we have to draw the endpoint
    01057         */
    01058         if (draw_endpoint) {
    01059                 /*
    01060                 * Draw final pixel, always exactly intersected by the line and doesn't
    01061                 * need to be weighted.
    01062                 */
    01063                 result |= pixelRGBA (renderer, x2, y2, r, g, b, a);
    01064         }
    01065
    01066         return (result);
    01067 }
    01068
    01081 int aalineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    01082 {
    01083         Uint8 *c = (Uint8 *)&color;
    01084         return _aalineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3], 1);
    01085 }
    01086
    01102 int aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01103 {
    01104         return _aalineRGBA(renderer, x1, y1, x2, y2, r, g, b, a, 1);
    01105 }
    01106
    01107 /* ----- Circle */
    01108
    01120 int circleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01121 {
    01122         Uint8 *c = (Uint8 *)&color;
    01123         return ellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01124 }
    01125
    01140 int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01141 {
    01142         return ellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
    01143 }
    01144
    01145 /* ----- Arc */
    01146
    01160 int arcColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    01161 {
    01162         Uint8 *c = (Uint8 *)&color;
    01163         return arcRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3]);
    01164 }
    01165
    01182 /* TODO: rewrite algorithm; arc endpoints are not always drawn */
    01183 int arcRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01184 {
    01185         int result;
    01186         Sint16 cx = 0;
    01187         Sint16 cy = rad;
    01188         Sint16 df = 1 - rad;
    01189         Sint16 d_e = 3;
    01190         Sint16 d_se = -2 * rad + 5;
    01191         Sint16 xpcx, xmcx, xpcy, xmcy;
    01192         Sint16 ypcy, ymcy, ypcx, ymcx;
    01193         Uint8 drawoct;
    01194         int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
    01195         double dstart, dend, temp = 0.;
    01196
    01197         /*
    01198         * Sanity check radius
    01199         */
    01200         if (rad < 0) {
    01201                 return (-1);
    01202         }
    01203
    01204         /*
    01205         * Special case for rad=0 - draw a point
    01206         */
    01207         if (rad == 0) {
    01208                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    01209         }
    01210
    01211         // Octant labelling
    01212         //
    01213         //  \ 5 | 6 /
    01214         //   \  |  /
    01215         //  4 \ | / 7
    01216         //     \|/
    01217         //------+------ +x
    01218         //     /|\
    01219         //  3 / | \ 0
    01220         //   /  |  \
    01221         //  / 2 | 1 \
    01222         //      +y
    01223
    01224         // Initially reset bitmask to 0x00000000
    01225         // the set whether or not to keep drawing a given octant.
    01226         // For example: 0x00111100 means we're drawing in octants 2-5
    01227         drawoct = 0;
    01228
    01229         /*
    01230         * Fixup angles
    01231         */
    01232         start %= 360;
    01233         end %= 360;
    01234         // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
    01235         while (start < 0) start += 360;
    01236         while (end < 0) end += 360;
    01237         start %= 360;
    01238         end %= 360;
    01239
    01240         // now, we find which octants we're drawing in.
    01241         startoct = start / 45;
    01242         endoct = end / 45;
    01243         oct = startoct - 1; // we increment as first step in loop
    01244
    01245         // stopval_start, stopval_end;
    01246         // what values of cx to stop at.
    01247         do {
    01248                 oct = (oct + 1) % 8;
    01249
    01250                 if (oct == startoct) {
    01251                         // need to compute stopval_start for this octant.  Look at picture above if this is unclear
    01252                         dstart = (double)start;
    01253                         switch (oct)
    01254                         {
    01255                         case 0:
    01256                         case 3:
    01257                                 temp = sin(dstart * M_PI / 180.);
    01258                                 break;
    01259                         case 1:
    01260                         case 6:
    01261                                 temp = cos(dstart * M_PI / 180.);
    01262                                 break;
    01263                         case 2:
    01264                         case 5:
    01265                                 temp = -cos(dstart * M_PI / 180.);
    01266                                 break;
    01267                         case 4:
    01268                         case 7:
    01269                                 temp = -sin(dstart * M_PI / 180.);
    01270                                 break;
    01271                         }
    01272                         temp *= rad;
    01273                         stopval_start = (int)temp; // always round down
    01274
    01275                         // This isn't arbitrary, but requires graph paper to explain well.
    01276                         // The basic idea is that we're always changing drawoct after we draw, so we
    01277                         // stop immediately after we render the last sensible pixel at x = ((int)temp).
    01278
    01279                         // and whether to draw in this octant initially
    01280                         if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
    01281                         else             drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
    01282                 }
    01283                 if (oct == endoct) {
    01284                         // need to compute stopval_end for this octant
    01285                         dend = (double)end;
    01286                         switch (oct)
    01287                         {
    01288                         case 0:
    01289                         case 3:
    01290                                 temp = sin(dend * M_PI / 180);
    01291                                 break;
    01292                         case 1:
    01293                         case 6:
    01294                                 temp = cos(dend * M_PI / 180);
    01295                                 break;
    01296                         case 2:
    01297                         case 5:
    01298                                 temp = -cos(dend * M_PI / 180);
    01299                                 break;
    01300                         case 4:
    01301                         case 7:
    01302                                 temp = -sin(dend * M_PI / 180);
    01303                                 break;
    01304                         }
    01305                         temp *= rad;
    01306                         stopval_end = (int)temp;
    01307
    01308                         // and whether to draw in this octant initially
    01309                         if (startoct == endoct) {
    01310                                 // note:      we start drawing, stop, then start again in this case
    01311                                 // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
    01312                                 if (start > end) {
    01313                                         // unfortunately, if we're in the same octant and need to draw over the whole circle,
    01314                                         // we need to set the rest to true, because the while loop will end at the bottom.
    01315                                         drawoct = 255;
    01316                                 } else {
    01317                                         drawoct &= 255 - (1 << oct);
    01318                                 }
    01319                         }
    01320                         else if (oct % 2) drawoct &= 255 - (1 << oct);
    01321                         else                      drawoct |= (1 << oct);
    01322                 } else if (oct != startoct) { // already verified that it's != endoct
    01323                         drawoct |= (1 << oct); // draw this entire segment
    01324                 }
    01325         } while (oct != endoct);
    01326
    01327         // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
    01328
    01329         /*
    01330         * Set color
    01331         */
    01332         result = 0;
    01333         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01334         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01335
    01336         /*
    01337         * Draw arc
    01338         */
    01339         do {
    01340                 ypcy = y + cy;
    01341                 ymcy = y - cy;
    01342                 if (cx > 0) {
    01343                         xpcx = x + cx;
    01344                         xmcx = x - cx;
    01345
    01346                         // always check if we're drawing a certain octant before adding a pixel to that octant.
    01347                         if (drawoct & 4)  result |= pixel(renderer, xmcx, ypcy);
    01348                         if (drawoct & 2)  result |= pixel(renderer, xpcx, ypcy);
    01349                         if (drawoct & 32) result |= pixel(renderer, xmcx, ymcy);
    01350                         if (drawoct & 64) result |= pixel(renderer, xpcx, ymcy);
    01351                 } else {
    01352                         if (drawoct & 96) result |= pixel(renderer, x, ymcy);
    01353                         if (drawoct & 6)  result |= pixel(renderer, x, ypcy);
    01354                 }
    01355
    01356                 xpcy = x + cy;
    01357                 xmcy = x - cy;
    01358                 if (cx > 0 && cx != cy) {
    01359                         ypcx = y + cx;
    01360                         ymcx = y - cx;
    01361                         if (drawoct & 8)   result |= pixel(renderer, xmcy, ypcx);
    01362                         if (drawoct & 1)   result |= pixel(renderer, xpcy, ypcx);
    01363                         if (drawoct & 16)  result |= pixel(renderer, xmcy, ymcx);
    01364                         if (drawoct & 128) result |= pixel(renderer, xpcy, ymcx);
    01365                 } else if (cx == 0) {
    01366                         if (drawoct & 24)  result |= pixel(renderer, xmcy, y);
    01367                         if (drawoct & 129) result |= pixel(renderer, xpcy, y);
    01368                 }
    01369
    01370                 /*
    01371                 * Update whether we're drawing an octant
    01372                 */
    01373                 if (stopval_start == cx) {
    01374                         // works like an on-off switch.
    01375                         // This is just in case start & end are in the same octant.
    01376                         if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
    01377                         else                                               drawoct |= (1 << startoct);
    01378                 }
    01379                 if (stopval_end == cx) {
    01380                         if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
    01381                         else                                             drawoct |= (1 << endoct);
    01382                 }
    01383
    01384                 /*
    01385                 * Update pixels
    01386                 */
    01387                 if (df < 0) {
    01388                         df += d_e;
    01389                         d_e += 2;
    01390                         d_se += 2;
    01391                 } else {
    01392                         df += d_se;
    01393                         d_e += 2;
    01394                         d_se += 4;
    01395                         cy--;
    01396                 }
    01397                 cx++;
    01398         } while (cx <= cy);
    01399
    01400         return (result);
    01401 }
    01402
    01403 /* ----- AA Circle */
    01404
    01416 int aacircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01417 {
    01418         Uint8 *c = (Uint8 *)&color;
    01419         return aaellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01420 }
    01421
    01436 int aacircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01437 {
    01438         /*
    01439         * Draw
    01440         */
    01441         return aaellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
    01442 }
    01443
    01444 /* ----- Filled Circle */
    01445
    01457 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01458 {
    01459         Uint8 *c = (Uint8 *)&color;
    01460         return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01461 }
    01462
    01477 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01478 {
    01479         int result;
    01480         Sint16 cx = 0;
    01481         Sint16 cy = rad;
    01482         Sint16 ocx = (Sint16) 0xffff;
    01483         Sint16 ocy = (Sint16) 0xffff;
    01484         Sint16 df = 1 - rad;
    01485         Sint16 d_e = 3;
    01486         Sint16 d_se = -2 * rad + 5;
    01487         Sint16 xpcx, xmcx, xpcy, xmcy;
    01488         Sint16 ypcy, ymcy, ypcx, ymcx;
    01489
    01490         /*
    01491         * Sanity check radius
    01492         */
    01493         if (rad < 0) {
    01494                 return (-1);
    01495         }
    01496
    01497         /*
    01498         * Special case for rad=0 - draw a point
    01499         */
    01500         if (rad == 0) {
    01501                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    01502         }
    01503
    01504         /*
    01505         * Set color
    01506         */
    01507         result = 0;
    01508         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01509         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01510
    01511         /*
    01512         * Draw
    01513         */
    01514         do {
    01515                 xpcx = x + cx;
    01516                 xmcx = x - cx;
    01517                 xpcy = x + cy;
    01518                 xmcy = x - cy;
    01519                 if (ocy != cy) {
    01520                         if (cy > 0) {
    01521                                 ypcy = y + cy;
    01522                                 ymcy = y - cy;
    01523                                 result |= hline(renderer, xmcx, xpcx, ypcy);
    01524                                 result |= hline(renderer, xmcx, xpcx, ymcy);
    01525                         } else {
    01526                                 result |= hline(renderer, xmcx, xpcx, y);
    01527                         }
    01528                         ocy = cy;
    01529                 }
    01530                 if (ocx != cx) {
    01531                         if (cx != cy) {
    01532                                 if (cx > 0) {
    01533                                         ypcx = y + cx;
    01534                                         ymcx = y - cx;
    01535                                         result |= hline(renderer, xmcy, xpcy, ymcx);
    01536                                         result |= hline(renderer, xmcy, xpcy, ypcx);
    01537                                 } else {
    01538                                         result |= hline(renderer, xmcy, xpcy, y);
    01539                                 }
    01540                         }
    01541                         ocx = cx;
    01542                 }
    01543
    01544                 /*
    01545                 * Update
    01546                 */
    01547                 if (df < 0) {
    01548                         df += d_e;
    01549                         d_e += 2;
    01550                         d_se += 2;
    01551                 } else {
    01552                         df += d_se;
    01553                         d_e += 2;
    01554                         d_se += 4;
    01555                         cy--;
    01556                 }
    01557                 cx++;
    01558         } while (cx <= cy);
    01559
    01560         return (result);
    01561 }
    01562
    01563 /* ----- Ellipse */
    01564
    01577 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    01578 {
    01579         Uint8 *c = (Uint8 *)&color;
    01580         return ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    01581 }
    01582
    01598 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01599 {
    01600         int result;
    01601         int ix, iy;
    01602         int h, i, j, k;
    01603         int oh, oi, oj, ok;
    01604         int xmh, xph, ypk, ymk;
    01605         int xmi, xpi, ymj, ypj;
    01606         int xmj, xpj, ymi, ypi;
    01607         int xmk, xpk, ymh, yph;
    01608
    01609         /*
    01610         * Sanity check radii
    01611         */
    01612         if ((rx < 0) || (ry < 0)) {
    01613                 return (-1);
    01614         }
    01615
    01616         /*
    01617         * Special case for rx=0 - draw a vline
    01618         */
    01619         if (rx == 0) {
    01620                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    01621         }
    01622         /*
    01623         * Special case for ry=0 - draw a hline
    01624         */
    01625         if (ry == 0) {
    01626                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    01627         }
    01628
    01629         /*
    01630         * Set color
    01631         */
    01632         result = 0;
    01633         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01634         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01635
    01636         /*
    01637         * Init vars
    01638         */
    01639         oh = oi = oj = ok = 0xFFFF;
    01640
    01641         /*
    01642         * Draw
    01643         */
    01644         if (rx > ry) {
    01645                 ix = 0;
    01646                 iy = rx * 64;
    01647
    01648                 do {
    01649                         h = (ix + 32) >> 6;
    01650                         i = (iy + 32) >> 6;
    01651                         j = (h * ry) / rx;
    01652                         k = (i * ry) / rx;
    01653
    01654                         if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
    01655                                 xph = x + h;
    01656                                 xmh = x - h;
    01657                                 if (k > 0) {
    01658                                         ypk = y + k;
    01659                                         ymk = y - k;
    01660                                         result |= pixel(renderer, xmh, ypk);
    01661                                         result |= pixel(renderer, xph, ypk);
    01662                                         result |= pixel(renderer, xmh, ymk);
    01663                                         result |= pixel(renderer, xph, ymk);
    01664                                 } else {
    01665                                         result |= pixel(renderer, xmh, y);
    01666                                         result |= pixel(renderer, xph, y);
    01667                                 }
    01668                                 ok = k;
    01669                                 xpi = x + i;
    01670                                 xmi = x - i;
    01671                                 if (j > 0) {
    01672                                         ypj = y + j;
    01673                                         ymj = y - j;
    01674                                         result |= pixel(renderer, xmi, ypj);
    01675                                         result |= pixel(renderer, xpi, ypj);
    01676                                         result |= pixel(renderer, xmi, ymj);
    01677                                         result |= pixel(renderer, xpi, ymj);
    01678                                 } else {
    01679                                         result |= pixel(renderer, xmi, y);
    01680                                         result |= pixel(renderer, xpi, y);
    01681                                 }
    01682                                 oj = j;
    01683                         }
    01684
    01685                         ix = ix + iy / rx;
    01686                         iy = iy - ix / rx;
    01687
    01688                 } while (i > h);
    01689         } else {
    01690                 ix = 0;
    01691                 iy = ry * 64;
    01692
    01693                 do {
    01694                         h = (ix + 32) >> 6;
    01695                         i = (iy + 32) >> 6;
    01696                         j = (h * rx) / ry;
    01697                         k = (i * rx) / ry;
    01698
    01699                         if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
    01700                                 xmj = x - j;
    01701                                 xpj = x + j;
    01702                                 if (i > 0) {
    01703                                         ypi = y + i;
    01704                                         ymi = y - i;
    01705                                         result |= pixel(renderer, xmj, ypi);
    01706                                         result |= pixel(renderer, xpj, ypi);
    01707                                         result |= pixel(renderer, xmj, ymi);
    01708                                         result |= pixel(renderer, xpj, ymi);
    01709                                 } else {
    01710                                         result |= pixel(renderer, xmj, y);
    01711                                         result |= pixel(renderer, xpj, y);
    01712                                 }
    01713                                 oi = i;
    01714                                 xmk = x - k;
    01715                                 xpk = x + k;
    01716                                 if (h > 0) {
    01717                                         yph = y + h;
    01718                                         ymh = y - h;
    01719                                         result |= pixel(renderer, xmk, yph);
    01720                                         result |= pixel(renderer, xpk, yph);
    01721                                         result |= pixel(renderer, xmk, ymh);
    01722                                         result |= pixel(renderer, xpk, ymh);
    01723                                 } else {
    01724                                         result |= pixel(renderer, xmk, y);
    01725                                         result |= pixel(renderer, xpk, y);
    01726                                 }
    01727                                 oh = h;
    01728                         }
    01729
    01730                         ix = ix + iy / ry;
    01731                         iy = iy - ix / ry;
    01732
    01733                 } while (i > h);
    01734         }
    01735
    01736         return (result);
    01737 }
    01738
    01739 /* ----- AA Ellipse */
    01740
    01741 /* Windows targets do not have lrint, so provide a local inline version */
    01742 #if defined(_MSC_VER)
    01743 /* Detect 64bit and use intrinsic version */
    01744 #ifdef _M_X64
    01745 #include <emmintrin.h>
    01746 static __inline long
    01747         lrint(float f)
    01748 {
    01749         return _mm_cvtss_si32(_mm_load_ss(&f));
    01750 }
    01751 #elif defined(_M_IX86)
    01752 __inline long int
    01753         lrint (double flt)
    01754 {
    01755         int intgr;
    01756         _asm
    01757         {
    01758                 fld flt
    01759                         fistp intgr
    01760         };
    01761         return intgr;
    01762 }
    01763 #elif defined(_M_ARM)
    01764 #include <armintr.h>
    01765 #pragma warning(push)
    01766 #pragma warning(disable: 4716)
    01767 __declspec(naked) long int
    01768         lrint (double flt)
    01769 {
    01770         __emit(0xEC410B10); // fmdrr  d0, r0, r1
    01771         __emit(0xEEBD0B40); // ftosid s0, d0
    01772         __emit(0xEE100A10); // fmrs   r0, s0
    01773         __emit(0xE12FFF1E); // bx     lr
    01774 }
    01775 #pragma warning(pop)
    01776 #else
    01777 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
    01778 #endif
    01779 #endif
    01780
    01793 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    01794 {
    01795         Uint8 *c = (Uint8 *)&color;
    01796         return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    01797 }
    01798
    01814 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01815 {
    01816         int result;
    01817         int i;
    01818         int a2, b2, ds, dt, dxt, t, s, d;
    01819         Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
    01820         float cp;
    01821         double sab;
    01822         Uint8 weight, iweight;
    01823
    01824         /*
    01825         * Sanity check radii
    01826         */
    01827         if ((rx < 0) || (ry < 0)) {
    01828                 return (-1);
    01829         }
    01830
    01831         /*
    01832         * Special case for rx=0 - draw a vline
    01833         */
    01834         if (rx == 0) {
    01835                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    01836         }
    01837         /*
    01838         * Special case for ry=0 - draw an hline
    01839         */
    01840         if (ry == 0) {
    01841                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    01842         }
    01843
    01844         /* Variable setup */
    01845         a2 = rx * rx;
    01846         b2 = ry * ry;
    01847
    01848         ds = 2 * a2;
    01849         dt = 2 * b2;
    01850
    01851         xc2 = 2 * x;
    01852         yc2 = 2 * y;
    01853
    01854         sab = sqrt((double)(a2 + b2));
    01855         od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
    01856         dxt = (Sint16)lrint((double)a2 / sab) + od;
    01857
    01858         t = 0;
    01859         s = -2 * a2 * ry;
    01860         d = 0;
    01861
    01862         xp = x;
    01863         yp = y - ry;
    01864
    01865         /* Draw */
    01866         result = 0;
    01867         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01868
    01869         /* "End points" */
    01870         result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
    01871         result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
    01872         result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
    01873         result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
    01874
    01875         for (i = 1; i <= dxt; i++) {
    01876                 xp--;
    01877                 d += t - b2;
    01878
    01879                 if (d >= 0)
    01880                         ys = yp - 1;
    01881                 else if ((d - s - a2) > 0) {
    01882                         if ((2 * d - s - a2) >= 0)
    01883                                 ys = yp + 1;
    01884                         else {
    01885                                 ys = yp;
    01886                                 yp++;
    01887                                 d -= s + a2;
    01888                                 s += ds;
    01889                         }
    01890                 } else {
    01891                         yp++;
    01892                         ys = yp + 1;
    01893                         d -= s + a2;
    01894                         s += ds;
    01895                 }
    01896
    01897                 t -= dt;
    01898
    01899                 /* Calculate alpha */
    01900                 if (s != 0) {
    01901                         cp = (float) abs(d) / (float) abs(s);
    01902                         if (cp > 1.0) {
    01903                                 cp = 1.0;
    01904                         }
    01905                 } else {
    01906                         cp = 1.0;
    01907                 }
    01908
    01909                 /* Calculate weights */
    01910                 weight = (Uint8) (cp * 255);
    01911                 iweight = 255 - weight;
    01912
    01913                 /* Upper half */
    01914                 xx = xc2 - xp;
    01915                 result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
    01916                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
    01917
    01918                 result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
    01919                 result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
    01920
    01921                 /* Lower half */
    01922                 yy = yc2 - yp;
    01923                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
    01924                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
    01925
    01926                 yy = yc2 - ys;
    01927                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
    01928                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
    01929         }
    01930
    01931         /* Replaces original approximation code dyt = abs(yp - yc); */
    01932         dyt = (Sint16)lrint((double)b2 / sab ) + od;
    01933
    01934         for (i = 1; i <= dyt; i++) {
    01935                 yp++;
    01936                 d -= s + a2;
    01937
    01938                 if (d <= 0)
    01939                         xs = xp + 1;
    01940                 else if ((d + t - b2) < 0) {
    01941                         if ((2 * d + t - b2) <= 0)
    01942                                 xs = xp - 1;
    01943                         else {
    01944                                 xs = xp;
    01945                                 xp--;
    01946                                 d += t - b2;
    01947                                 t -= dt;
    01948                         }
    01949                 } else {
    01950                         xp--;
    01951                         xs = xp - 1;
    01952                         d += t - b2;
    01953                         t -= dt;
    01954                 }
    01955
    01956                 s += ds;
    01957
    01958                 /* Calculate alpha */
    01959                 if (t != 0) {
    01960                         cp = (float) abs(d) / (float) abs(t);
    01961                         if (cp > 1.0) {
    01962                                 cp = 1.0;
    01963                         }
    01964                 } else {
    01965                         cp = 1.0;
    01966                 }
    01967
    01968                 /* Calculate weight */
    01969                 weight = (Uint8) (cp * 255);
    01970                 iweight = 255 - weight;
    01971
    01972                 /* Left half */
    01973                 xx = xc2 - xp;
    01974                 yy = yc2 - yp;
    01975                 result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
    01976                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
    01977
    01978                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
    01979                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
    01980
    01981                 /* Right half */
    01982                 xx = xc2 - xs;
    01983                 result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
    01984                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
    01985
    01986                 result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
    01987                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
    01988         }
    01989
    01990         return (result);
    01991 }
    01992
    01993 /* ---- Filled Ellipse */
    01994
    02007 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    02008 {
    02009         Uint8 *c = (Uint8 *)&color;
    02010         return filledEllipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    02011 }
    02012
    02028 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02029 {
    02030         int result;
    02031         int ix, iy;
    02032         int h, i, j, k;
    02033         int oh, oi, oj, ok;
    02034         int xmh, xph;
    02035         int xmi, xpi;
    02036         int xmj, xpj;
    02037         int xmk, xpk;
    02038
    02039         /*
    02040         * Sanity check radii
    02041         */
    02042         if ((rx < 0) || (ry < 0)) {
    02043                 return (-1);
    02044         }
    02045
    02046         /*
    02047         * Special case for rx=0 - draw a vline
    02048         */
    02049         if (rx == 0) {
    02050                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    02051         }
    02052         /*
    02053         * Special case for ry=0 - draw a hline
    02054         */
    02055         if (ry == 0) {
    02056                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    02057         }
    02058
    02059         /*
    02060         * Set color
    02061         */
    02062         result = 0;
    02063         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02064         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02065
    02066         /*
    02067         * Init vars
    02068         */
    02069         oh = oi = oj = ok = 0xFFFF;
    02070
    02071         /*
    02072         * Draw
    02073         */
    02074         if (rx > ry) {
    02075                 ix = 0;
    02076                 iy = rx * 64;
    02077
    02078                 do {
    02079                         h = (ix + 32) >> 6;
    02080                         i = (iy + 32) >> 6;
    02081                         j = (h * ry) / rx;
    02082                         k = (i * ry) / rx;
    02083
    02084                         if ((ok != k) && (oj != k)) {
    02085                                 xph = x + h;
    02086                                 xmh = x - h;
    02087                                 if (k > 0) {
    02088                                         result |= hline(renderer, xmh, xph, y + k);
    02089                                         result |= hline(renderer, xmh, xph, y - k);
    02090                                 } else {
    02091                                         result |= hline(renderer, xmh, xph, y);
    02092                                 }
    02093                                 ok = k;
    02094                         }
    02095                         if ((oj != j) && (ok != j) && (k != j)) {
    02096                                 xmi = x - i;
    02097                                 xpi = x + i;
    02098                                 if (j > 0) {
    02099                                         result |= hline(renderer, xmi, xpi, y + j);
    02100                                         result |= hline(renderer, xmi, xpi, y - j);
    02101                                 } else {
    02102                                         result |= hline(renderer, xmi, xpi, y);
    02103                                 }
    02104                                 oj = j;
    02105                         }
    02106
    02107                         ix = ix + iy / rx;
    02108                         iy = iy - ix / rx;
    02109
    02110                 } while (i > h);
    02111         } else {
    02112                 ix = 0;
    02113                 iy = ry * 64;
    02114
    02115                 do {
    02116                         h = (ix + 32) >> 6;
    02117                         i = (iy + 32) >> 6;
    02118                         j = (h * rx) / ry;
    02119                         k = (i * rx) / ry;
    02120
    02121                         if ((oi != i) && (oh != i)) {
    02122                                 xmj = x - j;
    02123                                 xpj = x + j;
    02124                                 if (i > 0) {
    02125                                         result |= hline(renderer, xmj, xpj, y + i);
    02126                                         result |= hline(renderer, xmj, xpj, y - i);
    02127                                 } else {
    02128                                         result |= hline(renderer, xmj, xpj, y);
    02129                                 }
    02130                                 oi = i;
    02131                         }
    02132                         if ((oh != h) && (oi != h) && (i != h)) {
    02133                                 xmk = x - k;
    02134                                 xpk = x + k;
    02135                                 if (h > 0) {
    02136                                         result |= hline(renderer, xmk, xpk, y + h);
    02137                                         result |= hline(renderer, xmk, xpk, y - h);
    02138                                 } else {
    02139                                         result |= hline(renderer, xmk, xpk, y);
    02140                                 }
    02141                                 oh = h;
    02142                         }
    02143
    02144                         ix = ix + iy / ry;
    02145                         iy = iy - ix / ry;
    02146
    02147                 } while (i > h);
    02148         }
    02149
    02150         return (result);
    02151 }
    02152
    02153 /* ----- Pie */
    02154
    02174 /* TODO: rewrite algorithm; pie is not always accurate */
    02175 int _pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end,  Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint8 filled)
    02176 {
    02177         int result;
    02178         double angle, start_angle, end_angle;
    02179         double deltaAngle;
    02180         double dr;
    02181         int numpoints, i;
    02182         Sint16 *vx, *vy;
    02183
    02184         /*
    02185         * Sanity check radii
    02186         */
    02187         if (rad < 0) {
    02188                 return (-1);
    02189         }
    02190
    02191         /*
    02192         * Fixup angles
    02193         */
    02194         start = start % 360;
    02195         end = end % 360;
    02196
    02197         /*
    02198         * Special case for rad=0 - draw a point
    02199         */
    02200         if (rad == 0) {
    02201                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    02202         }
    02203
    02204         /*
    02205         * Variable setup
    02206         */
    02207         dr = (double) rad;
    02208         deltaAngle = 3.0 / dr;
    02209         start_angle = (double) start *(2.0 * M_PI / 360.0);
    02210         end_angle = (double) end *(2.0 * M_PI / 360.0);
    02211         if (start > end) {
    02212                 end_angle += (2.0 * M_PI);
    02213         }
    02214
    02215         /* We will always have at least 2 points */
    02216         numpoints = 2;
    02217
    02218         /* Count points (rather than calculating it) */
    02219         angle = start_angle;
    02220         while (angle < end_angle) {
    02221                 angle += deltaAngle;
    02222                 numpoints++;
    02223         }
    02224
    02225         /* Allocate combined vertex array */
    02226         vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
    02227         if (vx == NULL) {
    02228                 return (-1);
    02229         }
    02230
    02231         /* Update point to start of vy */
    02232         vy += numpoints;
    02233
    02234         /* Center */
    02235         vx[0] = x;
    02236         vy[0] = y;
    02237
    02238         /* First vertex */
    02239         angle = start_angle;
    02240         vx[1] = x + (int) (dr * cos(angle));
    02241         vy[1] = y + (int) (dr * sin(angle));
    02242
    02243         if (numpoints<3)
    02244         {
    02245                 result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
    02246         }
    02247         else
    02248         {
    02249                 /* Calculate other vertices */
    02250                 i = 2;
    02251                 angle = start_angle;
    02252                 while (angle < end_angle) {
    02253                         angle += deltaAngle;
    02254                         if (angle>end_angle)
    02255                         {
    02256                                 angle = end_angle;
    02257                         }
    02258                         vx[i] = x + (int) (dr * cos(angle));
    02259                         vy[i] = y + (int) (dr * sin(angle));
    02260                         i++;
    02261                 }
    02262
    02263                 /* Draw */
    02264                 if (filled) {
    02265                         result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
    02266                 } else {
    02267                         result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
    02268                 }
    02269         }
    02270
    02271         /* Free combined vertex array */
    02272         free(vx);
    02273
    02274         return (result);
    02275 }
    02276
    02290 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02291         Sint16 start, Sint16 end, Uint32 color)
    02292 {
    02293         Uint8 *c = (Uint8 *)&color;
    02294         return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
    02295 }
    02296
    02313 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02314         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02315 {
    02316         return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
    02317 }
    02318
    02332 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    02333 {
    02334         Uint8 *c = (Uint8 *)&color;
    02335         return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
    02336 }
    02337
    02354 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02355         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02356 {
    02357         return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
    02358 }
    02359
    02360 /* ------ Trigon */
    02361
    02378 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02379 {
    02380         Sint16 vx[3];
    02381         Sint16 vy[3];
    02382
    02383         vx[0]=x1;
    02384         vx[1]=x2;
    02385         vx[2]=x3;
    02386         vy[0]=y1;
    02387         vy[1]=y2;
    02388         vy[2]=y3;
    02389
    02390         return(polygonColor(renderer,vx,vy,3,color));
    02391 }
    02392
    02410 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02411         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02412 {
    02413         Sint16 vx[3];
    02414         Sint16 vy[3];
    02415
    02416         vx[0]=x1;
    02417         vx[1]=x2;
    02418         vx[2]=x3;
    02419         vy[0]=y1;
    02420         vy[1]=y2;
    02421         vy[2]=y3;
    02422
    02423         return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02424 }
    02425
    02426 /* ------ AA-Trigon */
    02427
    02444 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02445 {
    02446         Sint16 vx[3];
    02447         Sint16 vy[3];
    02448
    02449         vx[0]=x1;
    02450         vx[1]=x2;
    02451         vx[2]=x3;
    02452         vy[0]=y1;
    02453         vy[1]=y2;
    02454         vy[2]=y3;
    02455
    02456         return(aapolygonColor(renderer,vx,vy,3,color));
    02457 }
    02458
    02476 int aatrigonRGBA(SDL_Renderer * renderer,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02477         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02478 {
    02479         Sint16 vx[3];
    02480         Sint16 vy[3];
    02481
    02482         vx[0]=x1;
    02483         vx[1]=x2;
    02484         vx[2]=x3;
    02485         vy[0]=y1;
    02486         vy[1]=y2;
    02487         vy[2]=y3;
    02488
    02489         return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02490 }
    02491
    02492 /* ------ Filled Trigon */
    02493
    02510 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02511 {
    02512         Sint16 vx[3];
    02513         Sint16 vy[3];
    02514
    02515         vx[0]=x1;
    02516         vx[1]=x2;
    02517         vx[2]=x3;
    02518         vy[0]=y1;
    02519         vy[1]=y2;
    02520         vy[2]=y3;
    02521
    02522         return(filledPolygonColor(renderer,vx,vy,3,color));
    02523 }
    02524
    02544 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02545         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02546 {
    02547         Sint16 vx[3];
    02548         Sint16 vy[3];
    02549
    02550         vx[0]=x1;
    02551         vx[1]=x2;
    02552         vx[2]=x3;
    02553         vy[0]=y1;
    02554         vy[1]=y2;
    02555         vy[2]=y3;
    02556
    02557         return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02558 }
    02559
    02560 /* ---- Polygon */
    02561
    02573 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    02574 {
    02575         Uint8 *c = (Uint8 *)&color;
    02576         return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
    02577 }
    02578
    02589 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
    02590 {
    02591         /*
    02592         * Draw
    02593         */
    02594         int result;
    02595         int i, nn;
    02596         SDL_Point* points;
    02597
    02598         /*
    02599         * Vertex array NULL check
    02600         */
    02601         if (vx == NULL) {
    02602                 return (-1);
    02603         }
    02604         if (vy == NULL) {
    02605                 return (-1);
    02606         }
    02607
    02608         /*
    02609         * Sanity check
    02610         */
    02611         if (n < 3) {
    02612                 return (-1);
    02613         }
    02614
    02615         /*
    02616         * Create array of points
    02617         */
    02618         nn = n + 1;
    02619         points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
    02620         if (points == NULL)
    02621         {
    02622                 return -1;
    02623         }
    02624         for (i=0; i<n; i++)
    02625         {
    02626                 points[i].x = vx[i];
    02627                 points[i].y = vy[i];
    02628         }
    02629         points[n].x = vx[0];
    02630         points[n].y = vy[0];
    02631
    02632         /*
    02633         * Draw
    02634         */
    02635         result |= SDL_RenderDrawLines(renderer, points, nn);
    02636         free(points);
    02637
    02638         return (result);
    02639 }
    02640
    02655 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02656 {
    02657         /*
    02658         * Draw
    02659         */
    02660         int result;
    02661         const Sint16 *x1, *y1, *x2, *y2;
    02662
    02663         /*
    02664         * Vertex array NULL check
    02665         */
    02666         if (vx == NULL) {
    02667                 return (-1);
    02668         }
    02669         if (vy == NULL) {
    02670                 return (-1);
    02671         }
    02672
    02673         /*
    02674         * Sanity check
    02675         */
    02676         if (n < 3) {
    02677                 return (-1);
    02678         }
    02679
    02680         /*
    02681         * Pointer setup
    02682         */
    02683         x1 = x2 = vx;
    02684         y1 = y2 = vy;
    02685         x2++;
    02686         y2++;
    02687
    02688         /*
    02689         * Set color
    02690         */
    02691         result = 0;
    02692         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02693         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02694
    02695         /*
    02696         * Draw
    02697         */
    02698         result |= polygon(renderer, vx, vy, n);
    02699
    02700         return (result);
    02701 }
    02702
    02703 /* ---- AA-Polygon */
    02704
    02716 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    02717 {
    02718         Uint8 *c = (Uint8 *)&color;
    02719         return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
    02720 }
    02721
    02736 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02737 {
    02738         int result;
    02739         int i;
    02740         const Sint16 *x1, *y1, *x2, *y2;
    02741
    02742         /*
    02743         * Vertex array NULL check
    02744         */
    02745         if (vx == NULL) {
    02746                 return (-1);
    02747         }
    02748         if (vy == NULL) {
    02749                 return (-1);
    02750         }
    02751
    02752         /*
    02753         * Sanity check
    02754         */
    02755         if (n < 3) {
    02756                 return (-1);
    02757         }
    02758
    02759         /*
    02760         * Pointer setup
    02761         */
    02762         x1 = x2 = vx;
    02763         y1 = y2 = vy;
    02764         x2++;
    02765         y2++;
    02766
    02767         /*
    02768         * Draw
    02769         */
    02770         result = 0;
    02771         for (i = 1; i < n; i++) {
    02772                 result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
    02773                 x1 = x2;
    02774                 y1 = y2;
    02775                 x2++;
    02776                 y2++;
    02777         }
    02778
    02779         result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
    02780
    02781         return (result);
    02782 }
    02783
    02784 /* ---- Filled Polygon */
    02785
    02794 int _gfxPrimitivesCompareInt(const void *a, const void *b)
    02795 {
    02796         return (*(const int *) a) - (*(const int *) b);
    02797 }
    02798
    02804 static int *gfxPrimitivesPolyIntsGlobal = NULL;
    02805
    02811 static int gfxPrimitivesPolyAllocatedGlobal = 0;
    02812
    02831 int filledPolygonRGBAMT(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
    02832 {
    02833         int result;
    02834         int i;
    02835         int y, xa, xb;
    02836         int miny, maxy;
    02837         int x1, y1;
    02838         int x2, y2;
    02839         int ind1, ind2;
    02840         int ints;
    02841         int *gfxPrimitivesPolyInts = NULL;
    02842         int *gfxPrimitivesPolyIntsNew = NULL;
    02843         int gfxPrimitivesPolyAllocated = 0;
    02844
    02845         /*
    02846         * Vertex array NULL check
    02847         */
    02848         if (vx == NULL) {
    02849                 return (-1);
    02850         }
    02851         if (vy == NULL) {
    02852                 return (-1);
    02853         }
    02854
    02855         /*
    02856         * Sanity check number of edges
    02857         */
    02858         if (n < 3) {
    02859                 return -1;
    02860         }
    02861
    02862         /*
    02863         * Map polygon cache
    02864         */
    02865         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    02866                 /* Use global cache */
    02867                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    02868                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    02869         } else {
    02870                 /* Use local cache */
    02871                 gfxPrimitivesPolyInts = *polyInts;
    02872                 gfxPrimitivesPolyAllocated = *polyAllocated;
    02873         }
    02874
    02875         /*
    02876         * Allocate temp array, only grow array
    02877         */
    02878         if (!gfxPrimitivesPolyAllocated) {
    02879                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    02880                 gfxPrimitivesPolyAllocated = n;
    02881         } else {
    02882                 if (gfxPrimitivesPolyAllocated < n) {
    02883                         gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    02884                         if (!gfxPrimitivesPolyIntsNew) {
    02885                                 if (!gfxPrimitivesPolyInts) {
    02886                                         free(gfxPrimitivesPolyInts);
    02887                                         gfxPrimitivesPolyInts = NULL;
    02888                                 }
    02889                                 gfxPrimitivesPolyAllocated = 0;
    02890                         } else {
    02891                                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
    02892                                 gfxPrimitivesPolyAllocated = n;
    02893                         }
    02894                 }
    02895         }
    02896
    02897         /*
    02898         * Check temp array
    02899         */
    02900         if (gfxPrimitivesPolyInts==NULL) {
    02901                 gfxPrimitivesPolyAllocated = 0;
    02902         }
    02903
    02904         /*
    02905         * Update cache variables
    02906         */
    02907         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    02908                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    02909                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    02910         } else {
    02911                 *polyInts = gfxPrimitivesPolyInts;
    02912                 *polyAllocated = gfxPrimitivesPolyAllocated;
    02913         }
    02914
    02915         /*
    02916         * Check temp array again
    02917         */
    02918         if (gfxPrimitivesPolyInts==NULL) {
    02919                 return(-1);
    02920         }
    02921
    02922         /*
    02923         * Determine Y maxima
    02924         */
    02925         miny = vy[0];
    02926         maxy = vy[0];
    02927         for (i = 1; (i < n); i++) {
    02928                 if (vy[i] < miny) {
    02929                         miny = vy[i];
    02930                 } else if (vy[i] > maxy) {
    02931                         maxy = vy[i];
    02932                 }
    02933         }
    02934
    02935         /*
    02936         * Draw, scanning y
    02937         */
    02938         result = 0;
    02939         for (y = miny; (y <= maxy); y++) {
    02940                 ints = 0;
    02941                 for (i = 0; (i < n); i++) {
    02942                         if (!i) {
    02943                                 ind1 = n - 1;
    02944                                 ind2 = 0;
    02945                         } else {
    02946                                 ind1 = i - 1;
    02947                                 ind2 = i;
    02948                         }
    02949                         y1 = vy[ind1];
    02950                         y2 = vy[ind2];
    02951                         if (y1 < y2) {
    02952                                 x1 = vx[ind1];
    02953                                 x2 = vx[ind2];
    02954                         } else if (y1 > y2) {
    02955                                 y2 = vy[ind1];
    02956                                 y1 = vy[ind2];
    02957                                 x2 = vx[ind1];
    02958                                 x1 = vx[ind2];
    02959                         } else {
    02960                                 continue;
    02961                         }
    02962                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    02963                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    02964                         }
    02965                 }
    02966
    02967                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    02968
    02969                 /*
    02970                 * Set color
    02971                 */
    02972                 result = 0;
    02973             result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02974                 result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02975
    02976                 for (i = 0; (i < ints); i += 2) {
    02977                         xa = gfxPrimitivesPolyInts[i] + 1;
    02978                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    02979                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    02980                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    02981                         result |= hline(renderer, xa, xb, y);
    02982                 }
    02983         }
    02984
    02985         return (result);
    02986 }
    02987
    02999 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    03000 {
    03001         Uint8 *c = (Uint8 *)&color;
    03002         return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
    03003 }
    03004
    03019 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03020 {
    03021         return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
    03022 }
    03023
    03024 /* ---- Textured Polygon */
    03025
    03041 int _HLineTextured(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, SDL_Texture *texture, int texture_w, int texture_h, int texture_dx, int texture_dy)
    03042 {
    03043         Sint16 w;
    03044         Sint16 xtmp;
    03045         int result = 0;
    03046         int texture_x_walker;
    03047         int texture_y_start;
    03048         SDL_Rect source_rect,dst_rect;
    03049         int pixels_written,write_width;
    03050
    03051         /*
    03052         * Swap x1, x2 if required to ensure x1<=x2
    03053         */
    03054         if (x1 > x2) {
    03055                 xtmp = x1;
    03056                 x1 = x2;
    03057                 x2 = xtmp;
    03058         }
    03059
    03060         /*
    03061         * Calculate width to draw
    03062         */
    03063         w = x2 - x1 + 1;
    03064
    03065         /*
    03066         * Determine where in the texture we start drawing
    03067         */
    03068         texture_x_walker =   (x1 - texture_dx)  % texture_w;
    03069         if (texture_x_walker < 0){
    03070                 texture_x_walker = texture_w + texture_x_walker ;
    03071         }
    03072
    03073         texture_y_start = (y + texture_dy) % texture_h;
    03074         if (texture_y_start < 0){
    03075                 texture_y_start = texture_h + texture_y_start;
    03076         }
    03077
    03078         // setup the source rectangle; we are only drawing one horizontal line
    03079         source_rect.y = texture_y_start;
    03080         source_rect.x = texture_x_walker;
    03081         source_rect.h = 1;
    03082
    03083         // we will draw to the current y
    03084         dst_rect.y = y;
    03085         dst_rect.h = 1;
    03086
    03087         // if there are enough pixels left in the current row of the texture
    03088         // draw it all at once
    03089         if (w <= texture_w -texture_x_walker){
    03090                 source_rect.w = w;
    03091                 source_rect.x = texture_x_walker;
    03092                 dst_rect.x= x1;
    03093                 dst_rect.w = source_rect.w;
    03094                 result = (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
    03095         } else {
    03096                 // we need to draw multiple times
    03097                 // draw the first segment
    03098                 pixels_written = texture_w  - texture_x_walker;
    03099                 source_rect.w = pixels_written;
    03100                 source_rect.x = texture_x_walker;
    03101                 dst_rect.x= x1;
    03102                 dst_rect.w = source_rect.w;
    03103                 result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
    03104                 write_width = texture_w;
    03105
    03106                 // now draw the rest
    03107                 // set the source x to 0
    03108                 source_rect.x = 0;
    03109                 while (pixels_written < w){
    03110                         if (write_width >= w - pixels_written) {
    03111                                 write_width =  w - pixels_written;
    03112                         }
    03113                         source_rect.w = write_width;
    03114                         dst_rect.x = x1 + pixels_written;
    03115                         dst_rect.w = source_rect.w;
    03116                         result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
    03117                         pixels_written += write_width;
    03118                 }
    03119         }
    03120
    03121         return result;
    03122 }
    03123
    03140 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
    03141         SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
    03142 {
    03143         int result;
    03144         int i;
    03145         int y, xa, xb;
    03146         int minx,maxx,miny, maxy;
    03147         int x1, y1;
    03148         int x2, y2;
    03149         int ind1, ind2;
    03150         int ints;
    03151         int *gfxPrimitivesPolyInts = NULL;
    03152         int gfxPrimitivesPolyAllocated = 0;
    03153         SDL_Texture *textureAsTexture = NULL;
    03154
    03155         /*
    03156         * Sanity check number of edges
    03157         */
    03158         if (n < 3) {
    03159                 return -1;
    03160         }
    03161
    03162         /*
    03163         * Map polygon cache
    03164         */
    03165         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    03166                 /* Use global cache */
    03167                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    03168                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    03169         } else {
    03170                 /* Use local cache */
    03171                 gfxPrimitivesPolyInts = *polyInts;
    03172                 gfxPrimitivesPolyAllocated = *polyAllocated;
    03173         }
    03174
    03175         /*
    03176         * Allocate temp array, only grow array
    03177         */
    03178         if (!gfxPrimitivesPolyAllocated) {
    03179                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    03180                 gfxPrimitivesPolyAllocated = n;
    03181         } else {
    03182                 if (gfxPrimitivesPolyAllocated < n) {
    03183                         gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    03184                         gfxPrimitivesPolyAllocated = n;
    03185                 }
    03186         }
    03187
    03188         /*
    03189         * Check temp array
    03190         */
    03191         if (gfxPrimitivesPolyInts==NULL) {
    03192                 gfxPrimitivesPolyAllocated = 0;
    03193         }
    03194
    03195         /*
    03196         * Update cache variables
    03197         */
    03198         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    03199                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    03200                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    03201         } else {
    03202                 *polyInts = gfxPrimitivesPolyInts;
    03203                 *polyAllocated = gfxPrimitivesPolyAllocated;
    03204         }
    03205
    03206         /*
    03207         * Check temp array again
    03208         */
    03209         if (gfxPrimitivesPolyInts==NULL) {
    03210                 return(-1);
    03211         }
    03212
    03213         /*
    03214         * Determine X,Y minima,maxima
    03215         */
    03216         miny = vy[0];
    03217         maxy = vy[0];
    03218         minx = vx[0];
    03219         maxx = vx[0];
    03220         for (i = 1; (i < n); i++) {
    03221                 if (vy[i] < miny) {
    03222                         miny = vy[i];
    03223                 } else if (vy[i] > maxy) {
    03224                         maxy = vy[i];
    03225                 }
    03226                 if (vx[i] < minx) {
    03227                         minx = vx[i];
    03228                 } else if (vx[i] > maxx) {
    03229                         maxx = vx[i];
    03230                 }
    03231         }
    03232
    03233     /* Create texture for drawing */
    03234         textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
    03235         if (textureAsTexture == NULL)
    03236         {
    03237                 return -1;
    03238         }
    03239         SDL_SetTextureBlendMode(textureAsTexture, SDL_BLENDMODE_BLEND);
    03240
    03241         /*
    03242         * Draw, scanning y
    03243         */
    03244         result = 0;
    03245         for (y = miny; (y <= maxy); y++) {
    03246                 ints = 0;
    03247                 for (i = 0; (i < n); i++) {
    03248                         if (!i) {
    03249                                 ind1 = n - 1;
    03250                                 ind2 = 0;
    03251                         } else {
    03252                                 ind1 = i - 1;
    03253                                 ind2 = i;
    03254                         }
    03255                         y1 = vy[ind1];
    03256                         y2 = vy[ind2];
    03257                         if (y1 < y2) {
    03258                                 x1 = vx[ind1];
    03259                                 x2 = vx[ind2];
    03260                         } else if (y1 > y2) {
    03261                                 y2 = vy[ind1];
    03262                                 y1 = vy[ind2];
    03263                                 x2 = vx[ind1];
    03264                                 x1 = vx[ind2];
    03265                         } else {
    03266                                 continue;
    03267                         }
    03268                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    03269                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    03270                         }
    03271                 }
    03272
    03273                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    03274
    03275                 for (i = 0; (i < ints); i += 2) {
    03276                         xa = gfxPrimitivesPolyInts[i] + 1;
    03277                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    03278                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    03279                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    03280                         result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
    03281                 }
    03282         }
    03283
    03284         SDL_RenderPresent(renderer);
    03285         SDL_DestroyTexture(textureAsTexture);
    03286
    03287         return (result);
    03288 }
    03289
    03306 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
    03307 {
    03308         /*
    03309         * Draw
    03310         */
    03311         return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
    03312 }
    03313
    03314 /* ---- Character */
    03315
    03319 static SDL_Texture *gfxPrimitivesFont[256];
    03320
    03324 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
    03325
    03329 static Uint32 charWidth = 8;
    03330
    03334 static Uint32 charHeight = 8;
    03335
    03339 static Uint32 charWidthLocal = 8;
    03340
    03344 static Uint32 charHeightLocal = 8;
    03345
    03349 static Uint32 charPitch = 1;
    03350
    03354 static Uint32 charRotation = 0;
    03355
    03359 static Uint32 charSize = 8;
    03360
    03374 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
    03375 {
    03376         int i;
    03377
    03378         if ((fontdata) && (cw) && (ch)) {
    03379                 currentFontdata = (unsigned char *)fontdata;
    03380                 charWidth = cw;
    03381                 charHeight = ch;
    03382         } else {
    03383                 currentFontdata = gfxPrimitivesFontdata;
    03384                 charWidth = 8;
    03385                 charHeight = 8;
    03386         }
    03387
    03388         charPitch = (charWidth+7)/8;
    03389         charSize = charPitch * charHeight;
    03390
    03391         /* Maybe flip width/height for rendering */
    03392         if ((charRotation==1) || (charRotation==3))
    03393         {
    03394                 charWidthLocal = charHeight;
    03395                 charHeightLocal = charWidth;
    03396         }
    03397         else
    03398         {
    03399                 charWidthLocal = charWidth;
    03400                 charHeightLocal = charHeight;
    03401         }
    03402
    03403         /* Clear character cache */
    03404         for (i = 0; i < 256; i++) {
    03405                 if (gfxPrimitivesFont[i]) {
    03406                         SDL_DestroyTexture(gfxPrimitivesFont[i]);
    03407                         gfxPrimitivesFont[i] = NULL;
    03408                 }
    03409         }
    03410 }
    03411
    03420 void gfxPrimitivesSetFontRotation(Uint32 rotation)
    03421 {
    03422         int i;
    03423
    03424         rotation = rotation & 3;
    03425         if (charRotation != rotation)
    03426         {
    03427                 /* Store rotation */
    03428                 charRotation = rotation;
    03429
    03430                 /* Maybe flip width/height for rendering */
    03431                 if ((charRotation==1) || (charRotation==3))
    03432                 {
    03433                         charWidthLocal = charHeight;
    03434                         charHeightLocal = charWidth;
    03435                 }
    03436                 else
    03437                 {
    03438                         charWidthLocal = charWidth;
    03439                         charHeightLocal = charHeight;
    03440                 }
    03441
    03442                 /* Clear character cache */
    03443                 for (i = 0; i < 256; i++) {
    03444                         if (gfxPrimitivesFont[i]) {
    03445                                 SDL_DestroyTexture(gfxPrimitivesFont[i]);
    03446                                 gfxPrimitivesFont[i] = NULL;
    03447                         }
    03448                 }
    03449         }
    03450 }
    03451
    03466 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03467 {
    03468         SDL_Rect srect;
    03469         SDL_Rect drect;
    03470         int result;
    03471         Uint32 ix, iy;
    03472         const unsigned char *charpos;
    03473         Uint8 *curpos;
    03474         Uint8 patt, mask;
    03475         Uint8 *linepos;
    03476         Uint32 pitch;
    03477         SDL_Surface *character;
    03478         SDL_Surface *rotatedCharacter;
    03479         Uint32 ci;
    03480
    03481         /*
    03482         * Setup source rectangle
    03483         */
    03484         srect.x = 0;
    03485         srect.y = 0;
    03486         srect.w = charWidthLocal;
    03487         srect.h = charHeightLocal;
    03488
    03489         /*
    03490         * Setup destination rectangle
    03491         */
    03492         drect.x = x;
    03493         drect.y = y;
    03494         drect.w = charWidthLocal;
    03495         drect.h = charHeightLocal;
    03496
    03497         /* Character index in cache */
    03498         ci = (unsigned char) c;
    03499
    03500         /*
    03501         * Create new charWidth x charHeight bitmap surface if not already present.
    03502         * Might get rotated later.
    03503         */
    03504         if (gfxPrimitivesFont[ci] == NULL) {
    03505                 /*
    03506                 * Redraw character into surface
    03507                 */
    03508                 character =     SDL_CreateRGBSurface(SDL_SWSURFACE,
    03509                         charWidth, charHeight, 32,
    03510                         0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
    03511                 if (character == NULL) {
    03512                         return (-1);
    03513                 }
    03514
    03515                 charpos = currentFontdata + ci * charSize;
    03516                                 linepos = (Uint8 *)character->pixels;
    03517                 pitch = character->pitch;
    03518
    03519                 /*
    03520                 * Drawing loop
    03521                 */
    03522                 patt = 0;
    03523                 for (iy = 0; iy < charHeight; iy++) {
    03524                         mask = 0x00;
    03525                         curpos = linepos;
    03526                         for (ix = 0; ix < charWidth; ix++) {
    03527                                 if (!(mask >>= 1)) {
    03528                                         patt = *charpos++;
    03529                                         mask = 0x80;
    03530                                 }
    03531                                 if (patt & mask) {
    03532                                         *(Uint32 *)curpos = 0xffffffff;
    03533                                 } else {
    03534                                         *(Uint32 *)curpos = 0;
    03535                                 }
    03536                                 curpos += 4;
    03537                         }
    03538                         linepos += pitch;
    03539                 }
    03540
    03541                 /* Maybe rotate and replace cached image */
    03542                 if (charRotation>0)
    03543                 {
    03544                         rotatedCharacter = rotateSurface90Degrees(character, charRotation);
    03545                         SDL_FreeSurface(character);
    03546                         character = rotatedCharacter;
    03547                 }
    03548
    03549                 /* Convert temp surface into texture */
    03550                 gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
    03551                 SDL_FreeSurface(character);
    03552
    03553                 /*
    03554                 * Check pointer
    03555                 */
    03556                 if (gfxPrimitivesFont[ci] == NULL) {
    03557                         return (-1);
    03558                 }
    03559         }
    03560
    03561         /*
    03562         * Set color
    03563         */
    03564         result = 0;
    03565         result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
    03566         result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
    03567
    03568         /*
    03569         * Draw texture onto destination
    03570         */
    03571         result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
    03572
    03573         return (result);
    03574 }
    03575
    03576
    03588 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
    03589 {
    03590         Uint8 *co = (Uint8 *)&color;
    03591         return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
    03592 }
    03593
    03594
    03609 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
    03610 {
    03611         Uint8 *c = (Uint8 *)&color;
    03612         return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
    03613 }
    03614
    03629 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03630 {
    03631         int result = 0;
    03632         Sint16 curx = x;
    03633         Sint16 cury = y;
    03634         const char *curchar = s;
    03635
    03636         while (*curchar && !result) {
    03637                 result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
    03638                 switch (charRotation)
    03639                 {
    03640                 case 0:
    03641                         curx += charWidthLocal;
    03642                         break;
    03643                 case 2:
    03644                         curx -= charWidthLocal;
    03645                         break;
    03646                 case 1:
    03647                         cury += charHeightLocal;
    03648                         break;
    03649                 case 3:
    03650                         cury -= charHeightLocal;
    03651                         break;
    03652                 }
    03653                 curchar++;
    03654         }
    03655
    03656         return (result);
    03657 }
    03658
    03659 /* ---- Bezier curve */
    03660
    03670 double _evaluateBezier (double *data, int ndata, double t)
    03671 {
    03672         double mu, result;
    03673         int n,k,kn,nn,nkn;
    03674         double blend,muk,munk;
    03675
    03676         /* Sanity check bounds */
    03677         if (t<0.0) {
    03678                 return(data[0]);
    03679         }
    03680         if (t>=(double)ndata) {
    03681                 return(data[ndata-1]);
    03682         }
    03683
    03684         /* Adjust t to the range 0.0 to 1.0 */
    03685         mu=t/(double)ndata;
    03686
    03687         /* Calculate interpolate */
    03688         n=ndata-1;
    03689         result=0.0;
    03690         muk = 1;
    03691         munk = pow(1-mu,(double)n);
    03692         for (k=0;k<=n;k++) {
    03693                 nn = n;
    03694                 kn = k;
    03695                 nkn = n - k;
    03696                 blend = muk * munk;
    03697                 muk *= mu;
    03698                 munk /= (1-mu);
    03699                 while (nn >= 1) {
    03700                         blend *= nn;
    03701                         nn--;
    03702                         if (kn > 1) {
    03703                                 blend /= (double)kn;
    03704                                 kn--;
    03705                         }
    03706                         if (nkn > 1) {
    03707                                 blend /= (double)nkn;
    03708                                 nkn--;
    03709                         }
    03710                 }
    03711                 result += data[k] * blend;
    03712         }
    03713
    03714         return (result);
    03715 }
    03716
    03729 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
    03730 {
    03731         Uint8 *c = (Uint8 *)&color;
    03732         return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
    03733 }
    03734
    03750 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03751 {
    03752         int result;
    03753         int i;
    03754         double *x, *y, t, stepsize;
    03755         Sint16 x1, y1, x2, y2;
    03756
    03757         /*
    03758         * Sanity check
    03759         */
    03760         if (n < 3) {
    03761                 return (-1);
    03762         }
    03763         if (s < 2) {
    03764                 return (-1);
    03765         }
    03766
    03767         /*
    03768         * Variable setup
    03769         */
    03770         stepsize=(double)1.0/(double)s;
    03771
    03772         /* Transfer vertices into float arrays */
    03773         if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    03774                 return(-1);
    03775         }
    03776         if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    03777                 free(x);
    03778                 return(-1);
    03779         }
    03780         for (i=0; i<n; i++) {
    03781                 x[i]=(double)vx[i];
    03782                 y[i]=(double)vy[i];
    03783         }
    03784         x[n]=(double)vx[0];
    03785         y[n]=(double)vy[0];
    03786
    03787         /*
    03788         * Set color
    03789         */
    03790         result = 0;
    03791         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    03792         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    03793
    03794         /*
    03795         * Draw
    03796         */
    03797         t=0.0;
    03798         x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
    03799         y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
    03800         for (i = 0; i <= (n*s); i++) {
    03801                 t += stepsize;
    03802                 x2=(Sint16)_evaluateBezier(x,n,t);
    03803                 y2=(Sint16)_evaluateBezier(y,n,t);
    03804                 result |= line(renderer, x1, y1, x2, y2);
    03805                 x1 = x2;
    03806                 y1 = y2;
    03807         }
    03808
    03809         /* Clean up temporary array */
    03810         free(x);
    03811         free(y);
    03812
    03813         return (result);
    03814 }
    03815
    03816
    03817 /* ---- Thick Line */
    03818
    03837 int _bresenhamInitialize(SDL2_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
    03838 {
    03839         int temp;
    03840
    03841         if (b==NULL) {
    03842                 return(-1);
    03843         }
    03844
    03845         b->x = x1;
    03846         b->y = y1;
    03847
    03848         /* dx = abs(x2-x1), s1 = sign(x2-x1) */
    03849         if ((b->dx = x2 - x1) != 0) {
    03850                 if (b->dx < 0) {
    03851                         b->dx = -b->dx;
    03852                         b->s1 = -1;
    03853                 } else {
    03854                         b->s1 = 1;
    03855                 }
    03856         } else {
    03857                 b->s1 = 0;
    03858         }
    03859
    03860         /* dy = abs(y2-y1), s2 = sign(y2-y1)    */
    03861         if ((b->dy = y2 - y1) != 0) {
    03862                 if (b->dy < 0) {
    03863                         b->dy = -b->dy;
    03864                         b->s2 = -1;
    03865                 } else {
    03866                         b->s2 = 1;
    03867                 }
    03868         } else {
    03869                 b->s2 = 0;
    03870         }
    03871
    03872         if (b->dy > b->dx) {
    03873                 temp = b->dx;
    03874                 b->dx = b->dy;
    03875                 b->dy = temp;
    03876                 b->swapdir = 1;
    03877         } else {
    03878                 b->swapdir = 0;
    03879         }
    03880
    03881         b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
    03882         b->dy <<= 1;
    03883         b->error = b->dy - b->dx;
    03884         b->dx <<= 1;
    03885
    03886         return(0);
    03887 }
    03888
    03889
    03899 int _bresenhamIterate(SDL2_gfxBresenhamIterator *b)
    03900 {
    03901         if (b==NULL) {
    03902                 return (-1);
    03903         }
    03904
    03905         /* last point check */
    03906         if (b->count==0) {
    03907                 return (2);
    03908         }
    03909
    03910         while (b->error >= 0) {
    03911                 if (b->swapdir) {
    03912                         b->x += b->s1;
    03913                 } else  {
    03914                         b->y += b->s2;
    03915                 }
    03916
    03917                 b->error -= b->dx;
    03918         }
    03919
    03920         if (b->swapdir) {
    03921                 b->y += b->s2;
    03922         } else {
    03923                 b->x += b->s1;
    03924         }
    03925
    03926         b->error += b->dy;
    03927         b->count--;
    03928
    03929         /* count==0 indicates "end-of-line" */
    03930         return ((b->count) ? 0 : 1);
    03931 }
    03932
    03933
    03942 void _murphyParaline(SDL2_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
    03943 {
    03944         int p;
    03945         d1 = -d1;
    03946
    03947         for (p = 0; p <= m->u; p++) {
    03948
    03949                 pixel(m->renderer, x, y);
    03950
    03951                 if (d1 <= m->kt) {
    03952                         if (m->oct2 == 0) {
    03953                                 x++;
    03954                         } else {
    03955                                 if (m->quad4 == 0) {
    03956                                         y++;
    03957                                 } else {
    03958                                         y--;
    03959                                 }
    03960                         }
    03961                         d1 += m->kv;
    03962                 } else {
    03963                         x++;
    03964                         if (m->quad4 == 0) {
    03965                                 y++;
    03966                         } else {
    03967                                 y--;
    03968                         }
    03969                         d1 += m->kd;
    03970                 }
    03971         }
    03972
    03973         m->tempx = x;
    03974         m->tempy = y;
    03975 }
    03976
    03992 void _murphyIteration(SDL2_gfxMurphyIterator *m, Uint8 miter,
    03993         Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
    03994         Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
    03995 {
    03996         int atemp1, atemp2;
    03997         int ftmp1, ftmp2;
    03998         Uint16 m1x, m1y, m2x, m2y;
    03999         Uint16 fix, fiy, lax, lay, curx, cury;
    04000         Sint16 px[4], py[4];
    04001         SDL2_gfxBresenhamIterator b;
    04002
    04003         if (miter > 1) {
    04004                 if (m->first1x != -32768) {
    04005                         fix = (m->first1x + m->first2x) / 2;
    04006                         fiy = (m->first1y + m->first2y) / 2;
    04007                         lax = (m->last1x + m->last2x) / 2;
    04008                         lay = (m->last1y + m->last2y) / 2;
    04009                         curx = (ml1x + ml2x) / 2;
    04010                         cury = (ml1y + ml2y) / 2;
    04011
    04012                         atemp1 = (fix - curx);
    04013                         atemp2 = (fiy - cury);
    04014                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    04015                         atemp1 = (lax - curx);
    04016                         atemp2 = (lay - cury);
    04017                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    04018
    04019                         if (ftmp1 <= ftmp2) {
    04020                                 m1x = m->first1x;
    04021                                 m1y = m->first1y;
    04022                                 m2x = m->first2x;
    04023                                 m2y = m->first2y;
    04024                         } else {
    04025                                 m1x = m->last1x;
    04026                                 m1y = m->last1y;
    04027                                 m2x = m->last2x;
    04028                                 m2y = m->last2y;
    04029                         }
    04030
    04031                         atemp1 = (m2x - ml2x);
    04032                         atemp2 = (m2y - ml2y);
    04033                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    04034                         atemp1 = (m2x - ml2bx);
    04035                         atemp2 = (m2y - ml2by);
    04036                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    04037
    04038                         if (ftmp2 >= ftmp1) {
    04039                                 ftmp1 = ml2bx;
    04040                                 ftmp2 = ml2by;
    04041                                 ml2bx = ml2x;
    04042                                 ml2by = ml2y;
    04043                                 ml2x = ftmp1;
    04044                                 ml2y = ftmp2;
    04045                                 ftmp1 = ml1bx;
    04046                                 ftmp2 = ml1by;
    04047                                 ml1bx = ml1x;
    04048                                 ml1by = ml1y;
    04049                                 ml1x = ftmp1;
    04050                                 ml1y = ftmp2;
    04051                         }
    04052
    04053                         /*
    04054                         * Lock the surface
    04055                         */
    04056                         _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
    04057                         do {
    04058                                 pixel(m->renderer, b.x, b.y);
    04059                         } while (_bresenhamIterate(&b)==0);
    04060
    04061                         _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
    04062                         do {
    04063                                 pixel(m->renderer, b.x, b.y);
    04064                         } while (_bresenhamIterate(&b)==0);
    04065
    04066                         _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
    04067                         do {
    04068                                 pixel(m->renderer, b.x, b.y);
    04069                         } while (_bresenhamIterate(&b)==0);
    04070
    04071                         _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
    04072                         do {
    04073                                 pixel(m->renderer, b.x, b.y);
    04074                         } while (_bresenhamIterate(&b)==0);
    04075
    04076                         px[0] = m1x;
    04077                         px[1] = m2x;
    04078                         px[2] = ml1bx;
    04079                         px[3] = ml2bx;
    04080                         py[0] = m1y;
    04081                         py[1] = m2y;
    04082                         py[2] = ml1by;
    04083                         py[3] = ml2by;
    04084                         polygon(m->renderer, px, py, 4);
    04085                 }
    04086         }
    04087
    04088         m->last1x = ml1x;
    04089         m->last1y = ml1y;
    04090         m->last2x = ml2x;
    04091         m->last2y = ml2y;
    04092         m->first1x = ml1bx;
    04093         m->first1y = ml1by;
    04094         m->first2x = ml2bx;
    04095         m->first2y = ml2by;
    04096 }
    04097
    04098
    04099 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
    04100
    04115 void _murphyWideline(SDL2_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
    04116 {
    04117         float offset = (float)width / 2.f;
    04118
    04119         Sint16 temp;
    04120         Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
    04121
    04122         int d0, d1;             /* difference terms d0=perpendicular to line, d1=along line */
    04123
    04124         int q;                  /* pel counter,q=perpendicular to line */
    04125         int tmp;
    04126
    04127         int dd;                 /* distance along line */
    04128         int tk;                 /* thickness threshold */
    04129         double ang;             /* angle for initial point calculation */
    04130         double sang, cang;
    04131
    04132         /* Initialisation */
    04133         m->u = x2 - x1; /* delta x */
    04134         m->v = y2 - y1; /* delta y */
    04135
    04136         if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
    04137                 temp = x1;
    04138                 x1 = x2;
    04139                 x2 = temp;
    04140                 temp = y1;
    04141                 y1 = y2;
    04142                 y2 = temp;
    04143                 m->u *= -1;
    04144                 m->v *= -1;
    04145         }
    04146
    04147         if (m->v < 0) { /* swap to 1st quadrant and flag */
    04148                 m->v *= -1;
    04149                 m->quad4 = 1;
    04150         } else {
    04151                 m->quad4 = 0;
    04152         }
    04153
    04154         if (m->v > m->u) {      /* swap things if in 2 octant */
    04155                 tmp = m->u;
    04156                 m->u = m->v;
    04157                 m->v = tmp;
    04158                 m->oct2 = 1;
    04159         } else {
    04160                 m->oct2 = 0;
    04161         }
    04162
    04163         m->ku = m->u + m->u;    /* change in l for square shift */
    04164         m->kv = m->v + m->v;    /* change in d for square shift */
    04165         m->kd = m->kv - m->ku;  /* change in d for diagonal shift */
    04166         m->kt = m->u - m->kv;   /* diag/square decision threshold */
    04167
    04168         d0 = 0;
    04169         d1 = 0;
    04170         dd = 0;
    04171
    04172         ang = atan((double) m->v / (double) m->u);      /* calc new initial point - offset both sides of ideal */
    04173         sang = sin(ang);
    04174         cang = cos(ang);
    04175
    04176         if (m->oct2 == 0) {
    04177                 ptx = x1 + (Sint16)lrint(offset * sang);
    04178                 if (m->quad4 == 0) {
    04179                         pty = y1 - (Sint16)lrint(offset * cang);
    04180                 } else {
    04181                         pty = y1 + (Sint16)lrint(offset * cang);
    04182                 }
    04183         } else {
    04184                 ptx = x1 - (Sint16)lrint(offset * cang);
    04185                 if (m->quad4 == 0) {
    04186                         pty = y1 + (Sint16)lrint(offset * sang);
    04187                 } else {
    04188                         pty = y1 - (Sint16)lrint(offset * sang);
    04189                 }
    04190         }
    04191
    04192         /* used here for constant thickness line */
    04193         tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
    04194
    04195         if (miter == 0) {
    04196                 m->first1x = -32768;
    04197                 m->first1y = -32768;
    04198                 m->first2x = -32768;
    04199                 m->first2y = -32768;
    04200                 m->last1x = -32768;
    04201                 m->last1y = -32768;
    04202                 m->last2x = -32768;
    04203                 m->last2y = -32768;
    04204         }
    04205         ptxx = ptx;
    04206         ptxy = pty;
    04207
    04208         for (q = 0; dd <= tk; q++) {    /* outer loop, stepping perpendicular to line */
    04209
    04210                 _murphyParaline(m, ptx, pty, d1);       /* call to inner loop - right edge */
    04211                 if (q == 0) {
    04212                         ml1x = ptx;
    04213                         ml1y = pty;
    04214                         ml1bx = m->tempx;
    04215                         ml1by = m->tempy;
    04216                 } else {
    04217                         ml2x = ptx;
    04218                         ml2y = pty;
    04219                         ml2bx = m->tempx;
    04220                         ml2by = m->tempy;
    04221                 }
    04222                 if (d0 < m->kt) {       /* square move */
    04223                         if (m->oct2 == 0) {
    04224                                 if (m->quad4 == 0) {
    04225                                         pty++;
    04226                                 } else {
    04227                                         pty--;
    04228                                 }
    04229                         } else {
    04230                                 ptx++;
    04231                         }
    04232                 } else {        /* diagonal move */
    04233                         dd += m->kv;
    04234                         d0 -= m->ku;
    04235                         if (d1 < m->kt) {       /* normal diagonal */
    04236                                 if (m->oct2 == 0) {
    04237                                         ptx--;
    04238                                         if (m->quad4 == 0) {
    04239                                                 pty++;
    04240                                         } else {
    04241                                                 pty--;
    04242                                         }
    04243                                 } else {
    04244                                         ptx++;
    04245                                         if (m->quad4 == 0) {
    04246                                                 pty--;
    04247                                         } else {
    04248                                                 pty++;
    04249                                         }
    04250                                 }
    04251                                 d1 += m->kv;
    04252                         } else {        /* double square move, extra parallel line */
    04253                                 if (m->oct2 == 0) {
    04254                                         ptx--;
    04255                                 } else {
    04256                                         if (m->quad4 == 0) {
    04257                                                 pty--;
    04258                                         } else {
    04259                                                 pty++;
    04260                                         }
    04261                                 }
    04262                                 d1 += m->kd;
    04263                                 if (dd > tk) {
    04264                                         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    04265                                         return; /* breakout on the extra line */
    04266                                 }
    04267                                 _murphyParaline(m, ptx, pty, d1);
    04268                                 if (m->oct2 == 0) {
    04269                                         if (m->quad4 == 0) {
    04270                                                 pty++;
    04271                                         } else {
    04272
    04273                                                 pty--;
    04274                                         }
    04275                                 } else {
    04276                                         ptx++;
    04277                                 }
    04278                         }
    04279                 }
    04280                 dd += m->ku;
    04281                 d0 += m->kv;
    04282         }
    04283
    04284         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    04285 }
    04286
    04287
    04301 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
    04302 {
    04303         Uint8 *c = (Uint8 *)&color;
    04304         return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
    04305 }
    04306
    04323 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04324 {
    04325         int result;
    04326         int wh;
    04327         SDL2_gfxMurphyIterator m;
    04328
    04329         if (renderer == NULL) {
    04330                 return -1;
    04331         }
    04332         if (width < 1) {
    04333                 return -1;
    04334         }
    04335
    04336         /* Special case: thick "point" */
    04337         if ((x1 == x2) && (y1 == y2)) {
    04338                 wh = width / 2;
    04339                 return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
    04340         }
    04341
    04342         /*
    04343         * Set color
    04344         */
    04345         result = 0;
    04346         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    04347         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    04348
    04349         /*
    04350         * Draw
    04351         */
    04352         m.renderer = renderer;
    04353         _murphyWideline(&m, x1, y1, x2, y2, width, 0);
    04354         _murphyWideline(&m, x1, y1, x2, y2, width, 1);
    04355
    04356         return(0);
    04357 }