SDL2_gfx: I:/Sources/sdl2gfx/SDL2_gfxPrimitives.c Source File

SDL2_gfx 1.0.0 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 == 0) {
    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 = 0;
    00524         Sint16 w, h, tmp;
    00525         Sint16 xx1, xx2, yy1, yy2;
    00526
    00527         /*
    00528         * Check destination renderer
    00529         */
    00530         if (renderer == NULL)
    00531         {
    00532                 return -1;
    00533         }
    00534
    00535         /*
    00536         * Check radius vor valid range
    00537         */
    00538         if (rad < 0) {
    00539                 return -1;
    00540         }
    00541
    00542         /*
    00543         * Special case - no rounding
    00544         */
    00545         if (rad == 0) {
    00546                 return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
    00547         }
    00548
    00549         /*
    00550         * Test for special cases of straight lines or single point
    00551         */
    00552         if (x1 == x2) {
    00553                 if (y1 == y2) {
    00554                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00555                 } else {
    00556                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00557                 }
    00558         } else {
    00559                 if (y1 == y2) {
    00560                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00561                 }
    00562         }
    00563
    00564         /*
    00565         * Swap x1, x2 if required
    00566         */
    00567         if (x1 > x2) {
    00568                 tmp = x1;
    00569                 x1 = x2;
    00570                 x2 = tmp;
    00571         }
    00572
    00573         /*
    00574         * Swap y1, y2 if required
    00575         */
    00576         if (y1 > y2) {
    00577                 tmp = y1;
    00578                 y1 = y2;
    00579                 y2 = tmp;
    00580         }
    00581
    00582         /*
    00583         * Calculate width&height
    00584         */
    00585         w = x2 - x1;
    00586         h = y2 - y1;
    00587
    00588         /*
    00589         * Maybe adjust radius
    00590         */
    00591         if ((rad * 2) > w)
    00592         {
    00593                 rad = w / 2;
    00594         }
    00595         if ((rad * 2) > h)
    00596         {
    00597                 rad = h / 2;
    00598         }
    00599
    00600         /*
    00601         * Draw corners
    00602         */
    00603         xx1 = x1 + rad;
    00604         xx2 = x2 - rad;
    00605         yy1 = y1 + rad;
    00606         yy2 = y2 - rad;
    00607         result |= filledPieRGBA(renderer, xx1, yy1, rad, 180, 270, r, g, b, a);
    00608         result |= filledPieRGBA(renderer, xx2, yy1, rad, 270, 360, r, g, b, a);
    00609         result |= filledPieRGBA(renderer, xx1, yy2, rad,  90, 180, r, g, b, a);
    00610         result |= filledPieRGBA(renderer, xx2, yy2, rad,   0,  90, r, g, b, a);
    00611
    00612         /*
    00613         * Draw body
    00614         */
    00615         xx1++;
    00616         xx2--;
    00617         yy1++;
    00618         yy2--;
    00619         if (xx1 <= xx2) {
    00620                 result |= boxRGBA(renderer, xx1, y1, xx2, y2, r, g, b, a);
    00621         }
    00622         if (yy1 <= yy2) {
    00623                 result |= boxRGBA(renderer, x1, yy1, xx1-1, yy2, r, g, b, a);
    00624                 result |= boxRGBA(renderer, xx2+1, yy1, x2, yy2, r, g, b, a);
    00625         }
    00626
    00627         return result;
    00628 }
    00629
    00630 /* ---- Box */
    00631
    00644 int boxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00645 {
    00646         Uint8 *c = (Uint8 *)&color;
    00647         return boxRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
    00648 }
    00649
    00665 int boxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00666 {
    00667         int result;
    00668         Sint16 tmp;
    00669         SDL_Rect rect;
    00670
    00671         /*
    00672         * Test for special cases of straight lines or single point
    00673         */
    00674         if (x1 == x2) {
    00675                 if (y1 == y2) {
    00676                         return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00677                 } else {
    00678                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00679                 }
    00680         } else {
    00681                 if (y1 == y2) {
    00682                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00683                 }
    00684         }
    00685
    00686         /*
    00687         * Swap x1, x2 if required
    00688         */
    00689         if (x1 > x2) {
    00690                 tmp = x1;
    00691                 x1 = x2;
    00692                 x2 = tmp;
    00693         }
    00694
    00695         /*
    00696         * Swap y1, y2 if required
    00697         */
    00698         if (y1 > y2) {
    00699                 tmp = y1;
    00700                 y1 = y2;
    00701                 y2 = tmp;
    00702         }
    00703
    00704         /*
    00705         * Create destination rect
    00706         */
    00707         rect.x = x1;
    00708         rect.y = y1;
    00709         rect.w = x2 - x1;
    00710         rect.h = y2 - y1;
    00711
    00712         /*
    00713         * Draw
    00714         */
    00715         result = 0;
    00716         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00717         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00718         result |= SDL_RenderFillRect(renderer, &rect);
    00719         return result;
    00720 }
    00721
    00722 /* ----- Line */
    00723
    00735 int line(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
    00736 {
    00737         /*
    00738         * Draw
    00739         */
    00740         return SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
    00741 }
    00742
    00755 int lineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    00756 {
    00757         Uint8 *c = (Uint8 *)&color;
    00758         return lineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
    00759 }
    00760
    00776 int lineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    00777 {
    00778         /*
    00779         * Draw
    00780         */
    00781         int result = 0;
    00782         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    00783         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    00784         result |= SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
    00785         return result;
    00786 }
    00787
    00788 /* ---- AA Line */
    00789
    00790 #define AAlevels 256
    00791 #define AAbits 8
    00792
    00816 int _aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
    00817 {
    00818         Sint32 xx0, yy0, xx1, yy1;
    00819         int result;
    00820         Uint32 intshift, erracc, erradj;
    00821         Uint32 erracctmp, wgt, wgtcompmask;
    00822         int dx, dy, tmp, xdir, y0p1, x0pxdir;
    00823
    00824         /*
    00825         * Keep on working with 32bit numbers
    00826         */
    00827         xx0 = x1;
    00828         yy0 = y1;
    00829         xx1 = x2;
    00830         yy1 = y2;
    00831
    00832         /*
    00833         * Reorder points to make dy positive
    00834         */
    00835         if (yy0 > yy1) {
    00836                 tmp = yy0;
    00837                 yy0 = yy1;
    00838                 yy1 = tmp;
    00839                 tmp = xx0;
    00840                 xx0 = xx1;
    00841                 xx1 = tmp;
    00842         }
    00843
    00844         /*
    00845         * Calculate distance
    00846         */
    00847         dx = xx1 - xx0;
    00848         dy = yy1 - yy0;
    00849
    00850         /*
    00851         * Adjust for negative dx and set xdir
    00852         */
    00853         if (dx >= 0) {
    00854                 xdir = 1;
    00855         } else {
    00856                 xdir = -1;
    00857                 dx = (-dx);
    00858         }
    00859
    00860         /*
    00861         * Check for special cases
    00862         */
    00863         if (dx == 0) {
    00864                 /*
    00865                 * Vertical line
    00866                 */
    00867                 if (draw_endpoint)
    00868                 {
    00869                         return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
    00870                 } else {
    00871                         if (dy > 0) {
    00872                                 return (vlineRGBA(renderer, x1, yy0, yy0+dy, r, g, b, a));
    00873                         } else {
    00874                                 return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00875                         }
    00876                 }
    00877         } else if (dy == 0) {
    00878                 /*
    00879                 * Horizontal line
    00880                 */
    00881                 if (draw_endpoint)
    00882                 {
    00883                         return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
    00884                 } else {
    00885                         if (dx > 0) {
    00886                                 return (hlineRGBA(renderer, xx0, xx0+dx, y1, r, g, b, a));
    00887                         } else {
    00888                                 return (pixelRGBA(renderer, x1, y1, r, g, b, a));
    00889                         }
    00890                 }
    00891         } else if ((dx == dy) && (draw_endpoint)) {
    00892                 /*
    00893                 * Diagonal line (with endpoint)
    00894                 */
    00895                 return (lineRGBA(renderer, x1, y1, x2, y2,  r, g, b, a));
    00896         }
    00897
    00898
    00899         /*
    00900         * Line is not horizontal, vertical or diagonal (with endpoint)
    00901         */
    00902         result = 0;
    00903
    00904         /*
    00905         * Zero accumulator
    00906         */
    00907         erracc = 0;
    00908
    00909         /*
    00910         * # of bits by which to shift erracc to get intensity level
    00911         */
    00912         intshift = 32 - AAbits;
    00913
    00914         /*
    00915         * Mask used to flip all bits in an intensity weighting
    00916         */
    00917         wgtcompmask = AAlevels - 1;
    00918
    00919         /*
    00920         * Draw the initial pixel in the foreground color
    00921         */
    00922         result |= pixelRGBA(renderer, x1, y1, r, g, b, a);
    00923
    00924         /*
    00925         * x-major or y-major?
    00926         */
    00927         if (dy > dx) {
    00928
    00929                 /*
    00930                 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
    00931                 * X advances every time Y advances 1 pixel, truncating the result so that
    00932                 * we won't overrun the endpoint along the X axis
    00933                 */
    00934                 /*
    00935                 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
    00936                 */
    00937                 erradj = ((dx << 16) / dy) << 16;
    00938
    00939                 /*
    00940                 * draw all pixels other than the first and last
    00941                 */
    00942                 x0pxdir = xx0 + xdir;
    00943                 while (--dy) {
    00944                         erracctmp = erracc;
    00945                         erracc += erradj;
    00946                         if (erracc <= erracctmp) {
    00947                                 /*
    00948                                 * rollover in error accumulator, x coord advances
    00949                                 */
    00950                                 xx0 = x0pxdir;
    00951                                 x0pxdir += xdir;
    00952                         }
    00953                         yy0++;          /* y-major so always advance Y */
    00954
    00955                         /*
    00956                         * the AAbits most significant bits of erracc give us the intensity
    00957                         * weighting for this pixel, and the complement of the weighting for
    00958                         * the paired pixel.
    00959                         */
    00960                         wgt = (erracc >> intshift) & 255;
    00961                         result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
    00962                         result |= pixelRGBAWeight (renderer, x0pxdir, yy0, r, g, b, a, wgt);
    00963                 }
    00964
    00965         } else {
    00966
    00967                 /*
    00968                 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
    00969                 * that Y advances each time X advances 1 pixel, truncating the result so
    00970                 * that we won't overrun the endpoint along the X axis.
    00971                 */
    00972                 /*
    00973                 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
    00974                 */
    00975                 erradj = ((dy << 16) / dx) << 16;
    00976
    00977                 /*
    00978                 * draw all pixels other than the first and last
    00979                 */
    00980                 y0p1 = yy0 + 1;
    00981                 while (--dx) {
    00982
    00983                         erracctmp = erracc;
    00984                         erracc += erradj;
    00985                         if (erracc <= erracctmp) {
    00986                                 /*
    00987                                 * Accumulator turned over, advance y
    00988                                 */
    00989                                 yy0 = y0p1;
    00990                                 y0p1++;
    00991                         }
    00992                         xx0 += xdir;    /* x-major so always advance X */
    00993                         /*
    00994                         * the AAbits most significant bits of erracc give us the intensity
    00995                         * weighting for this pixel, and the complement of the weighting for
    00996                         * the paired pixel.
    00997                         */
    00998                         wgt = (erracc >> intshift) & 255;
    00999                         result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
    01000                         result |= pixelRGBAWeight (renderer, xx0, y0p1, r, g, b, a, wgt);
    01001                 }
    01002         }
    01003
    01004         /*
    01005         * Do we have to draw the endpoint
    01006         */
    01007         if (draw_endpoint) {
    01008                 /*
    01009                 * Draw final pixel, always exactly intersected by the line and doesn't
    01010                 * need to be weighted.
    01011                 */
    01012                 result |= pixelRGBA (renderer, x2, y2, r, g, b, a);
    01013         }
    01014
    01015         return (result);
    01016 }
    01017
    01030 int aalineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
    01031 {
    01032         Uint8 *c = (Uint8 *)&color;
    01033         return _aalineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3], 1);
    01034 }
    01035
    01051 int aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01052 {
    01053         return _aalineRGBA(renderer, x1, y1, x2, y2, r, g, b, a, 1);
    01054 }
    01055
    01056 /* ----- Circle */
    01057
    01069 int circleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01070 {
    01071         Uint8 *c = (Uint8 *)&color;
    01072         return ellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01073 }
    01074
    01089 int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01090 {
    01091         return ellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
    01092 }
    01093
    01094 /* ----- Arc */
    01095
    01109 int arcColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    01110 {
    01111         Uint8 *c = (Uint8 *)&color;
    01112         return arcRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3]);
    01113 }
    01114
    01131 int arcRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01132 {
    01133         int result;
    01134         Sint16 cx = 0;
    01135         Sint16 cy = rad;
    01136         Sint16 df = 1 - rad;
    01137         Sint16 d_e = 3;
    01138         Sint16 d_se = -2 * rad + 5;
    01139         Sint16 xpcx, xmcx, xpcy, xmcy;
    01140         Sint16 ypcy, ymcy, ypcx, ymcx;
    01141         Uint8 drawoct;
    01142         int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
    01143         double dstart, dend, temp = 0.;
    01144
    01145         /*
    01146         * Sanity check radius
    01147         */
    01148         if (rad < 0) {
    01149                 return (-1);
    01150         }
    01151
    01152         /*
    01153         * Special case for rad=0 - draw a point
    01154         */
    01155         if (rad == 0) {
    01156                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    01157         }
    01158
    01159         // Octant labelling
    01160         //
    01161         //  \ 5 | 6 /
    01162         //   \  |  /
    01163         //  4 \ | / 7
    01164         //     \|/
    01165         //------+------ +x
    01166         //     /|\
    01167         //  3 / | \ 0
    01168         //   /  |  \
    01169         //  / 2 | 1 \
    01170         //      +y
    01171
    01172         // Initially reset bitmask to 0x00000000
    01173         // the set whether or not to keep drawing a given octant.
    01174         // For example: 0x00111100 means we're drawing in octants 2-5
    01175         drawoct = 0;
    01176
    01177         /*
    01178         * Fixup angles
    01179         */
    01180         start %= 360;
    01181         end %= 360;
    01182         // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
    01183         while (start < 0) start += 360;
    01184         while (end < 0) end += 360;
    01185         start %= 360;
    01186         end %= 360;
    01187
    01188         // now, we find which octants we're drawing in.
    01189         startoct = start / 45;
    01190         endoct = end / 45;
    01191         oct = startoct - 1; // we increment as first step in loop
    01192
    01193         // stopval_start, stopval_end;
    01194         // what values of cx to stop at.
    01195         do {
    01196                 oct = (oct + 1) % 8;
    01197
    01198                 if (oct == startoct) {
    01199                         // need to compute stopval_start for this octant.  Look at picture above if this is unclear
    01200                         dstart = (double)start;
    01201                         switch (oct)
    01202                         {
    01203                         case 0:
    01204                         case 3:
    01205                                 temp = sin(dstart * M_PI / 180.);
    01206                                 break;
    01207                         case 1:
    01208                         case 6:
    01209                                 temp = cos(dstart * M_PI / 180.);
    01210                                 break;
    01211                         case 2:
    01212                         case 5:
    01213                                 temp = -cos(dstart * M_PI / 180.);
    01214                                 break;
    01215                         case 4:
    01216                         case 7:
    01217                                 temp = -sin(dstart * M_PI / 180.);
    01218                                 break;
    01219                         }
    01220                         temp *= rad;
    01221                         stopval_start = (int)temp; // always round down.
    01222
    01223                         // This isn't arbitrary, but requires graph paper to explain well.
    01224                         // The basic idea is that we're always changing drawoct after we draw, so we
    01225                         // stop immediately after we render the last sensible pixel at x = ((int)temp).
    01226
    01227                         // and whether to draw in this octant initially
    01228                         if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
    01229                         else             drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
    01230                 }
    01231                 if (oct == endoct) {
    01232                         // need to compute stopval_end for this octant
    01233                         dend = (double)end;
    01234                         switch (oct)
    01235                         {
    01236                         case 0:
    01237                         case 3:
    01238                                 temp = sin(dend * M_PI / 180);
    01239                                 break;
    01240                         case 1:
    01241                         case 6:
    01242                                 temp = cos(dend * M_PI / 180);
    01243                                 break;
    01244                         case 2:
    01245                         case 5:
    01246                                 temp = -cos(dend * M_PI / 180);
    01247                                 break;
    01248                         case 4:
    01249                         case 7:
    01250                                 temp = -sin(dend * M_PI / 180);
    01251                                 break;
    01252                         }
    01253                         temp *= rad;
    01254                         stopval_end = (int)temp;
    01255
    01256                         // and whether to draw in this octant initially
    01257                         if (startoct == endoct) {
    01258                                 // note:      we start drawing, stop, then start again in this case
    01259                                 // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
    01260                                 if (start > end) {
    01261                                         // unfortunately, if we're in the same octant and need to draw over the whole circle,
    01262                                         // we need to set the rest to true, because the while loop will end at the bottom.
    01263                                         drawoct = 255;
    01264                                 } else {
    01265                                         drawoct &= 255 - (1 << oct);
    01266                                 }
    01267                         }
    01268                         else if (oct % 2) drawoct &= 255 - (1 << oct);
    01269                         else                      drawoct |= (1 << oct);
    01270                 } else if (oct != startoct) { // already verified that it's != endoct
    01271                         drawoct |= (1 << oct); // draw this entire segment
    01272                 }
    01273         } while (oct != endoct);
    01274
    01275         // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
    01276
    01277         /*
    01278         * Set color
    01279         */
    01280         result = 0;
    01281         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01282         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01283
    01284         /*
    01285         * Draw arc
    01286         */
    01287         do {
    01288                 ypcy = y + cy;
    01289                 ymcy = y - cy;
    01290                 if (cx > 0) {
    01291                         xpcx = x + cx;
    01292                         xmcx = x - cx;
    01293
    01294                         // always check if we're drawing a certain octant before adding a pixel to that octant.
    01295                         if (drawoct & 4)  result |= pixel(renderer, xmcx, ypcy);
    01296                         if (drawoct & 2)  result |= pixel(renderer, xpcx, ypcy);
    01297                         if (drawoct & 32) result |= pixel(renderer, xmcx, ymcy);
    01298                         if (drawoct & 64) result |= pixel(renderer, xpcx, ymcy);
    01299                 } else {
    01300                         if (drawoct & 96) result |= pixel(renderer, x, ymcy);
    01301                         if (drawoct & 6)  result |= pixel(renderer, x, ypcy);
    01302                 }
    01303
    01304                 xpcy = x + cy;
    01305                 xmcy = x - cy;
    01306                 if (cx > 0 && cx != cy) {
    01307                         ypcx = y + cx;
    01308                         ymcx = y - cx;
    01309                         if (drawoct & 8)   result |= pixel(renderer, xmcy, ypcx);
    01310                         if (drawoct & 1)   result |= pixel(renderer, xpcy, ypcx);
    01311                         if (drawoct & 16)  result |= pixel(renderer, xmcy, ymcx);
    01312                         if (drawoct & 128) result |= pixel(renderer, xpcy, ymcx);
    01313                 } else if (cx == 0) {
    01314                         if (drawoct & 24)  result |= pixel(renderer, xmcy, y);
    01315                         if (drawoct & 129) result |= pixel(renderer, xpcy, y);
    01316                 }
    01317
    01318                 /*
    01319                 * Update whether we're drawing an octant
    01320                 */
    01321                 if (stopval_start == cx) {
    01322                         // works like an on-off switch.
    01323                         // This is just in case start & end are in the same octant.
    01324                         if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
    01325                         else                                               drawoct |= (1 << startoct);
    01326                 }
    01327                 if (stopval_end == cx) {
    01328                         if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
    01329                         else                                             drawoct |= (1 << endoct);
    01330                 }
    01331
    01332                 /*
    01333                 * Update pixels
    01334                 */
    01335                 if (df < 0) {
    01336                         df += d_e;
    01337                         d_e += 2;
    01338                         d_se += 2;
    01339                 } else {
    01340                         df += d_se;
    01341                         d_e += 2;
    01342                         d_se += 4;
    01343                         cy--;
    01344                 }
    01345                 cx++;
    01346         } while (cx <= cy);
    01347
    01348         return (result);
    01349 }
    01350
    01351 /* ----- AA Circle */
    01352
    01364 int aacircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01365 {
    01366         Uint8 *c = (Uint8 *)&color;
    01367         return aaellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01368 }
    01369
    01384 int aacircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01385 {
    01386         /*
    01387         * Draw
    01388         */
    01389         return aaellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
    01390 }
    01391
    01392 /* ----- Filled Circle */
    01393
    01405 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
    01406 {
    01407         Uint8 *c = (Uint8 *)&color;
    01408         return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
    01409 }
    01410
    01425 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01426 {
    01427         int result;
    01428         Sint16 cx = 0;
    01429         Sint16 cy = rad;
    01430         Sint16 ocx = (Sint16) 0xffff;
    01431         Sint16 ocy = (Sint16) 0xffff;
    01432         Sint16 df = 1 - rad;
    01433         Sint16 d_e = 3;
    01434         Sint16 d_se = -2 * rad + 5;
    01435         Sint16 xpcx, xmcx, xpcy, xmcy;
    01436         Sint16 ypcy, ymcy, ypcx, ymcx;
    01437
    01438         /*
    01439         * Sanity check radius
    01440         */
    01441         if (rad < 0) {
    01442                 return (-1);
    01443         }
    01444
    01445         /*
    01446         * Special case for rad=0 - draw a point
    01447         */
    01448         if (rad == 0) {
    01449                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    01450         }
    01451
    01452         /*
    01453         * Set color
    01454         */
    01455         result = 0;
    01456         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01457         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01458
    01459         /*
    01460         * Draw
    01461         */
    01462         do {
    01463                 xpcx = x + cx;
    01464                 xmcx = x - cx;
    01465                 xpcy = x + cy;
    01466                 xmcy = x - cy;
    01467                 if (ocy != cy) {
    01468                         if (cy > 0) {
    01469                                 ypcy = y + cy;
    01470                                 ymcy = y - cy;
    01471                                 result |= hline(renderer, xmcx, xpcx, ypcy);
    01472                                 result |= hline(renderer, xmcx, xpcx, ymcy);
    01473                         } else {
    01474                                 result |= hline(renderer, xmcx, xpcx, y);
    01475                         }
    01476                         ocy = cy;
    01477                 }
    01478                 if (ocx != cx) {
    01479                         if (cx != cy) {
    01480                                 if (cx > 0) {
    01481                                         ypcx = y + cx;
    01482                                         ymcx = y - cx;
    01483                                         result |= hline(renderer, xmcy, xpcy, ymcx);
    01484                                         result |= hline(renderer, xmcy, xpcy, ypcx);
    01485                                 } else {
    01486                                         result |= hline(renderer, xmcy, xpcy, y);
    01487                                 }
    01488                         }
    01489                         ocx = cx;
    01490                 }
    01491
    01492                 /*
    01493                 * Update
    01494                 */
    01495                 if (df < 0) {
    01496                         df += d_e;
    01497                         d_e += 2;
    01498                         d_se += 2;
    01499                 } else {
    01500                         df += d_se;
    01501                         d_e += 2;
    01502                         d_se += 4;
    01503                         cy--;
    01504                 }
    01505                 cx++;
    01506         } while (cx <= cy);
    01507
    01508         return (result);
    01509 }
    01510
    01511 /* ----- Ellipse */
    01512
    01525 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    01526 {
    01527         Uint8 *c = (Uint8 *)&color;
    01528         return ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    01529 }
    01530
    01546 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01547 {
    01548         int result;
    01549         int ix, iy;
    01550         int h, i, j, k;
    01551         int oh, oi, oj, ok;
    01552         int xmh, xph, ypk, ymk;
    01553         int xmi, xpi, ymj, ypj;
    01554         int xmj, xpj, ymi, ypi;
    01555         int xmk, xpk, ymh, yph;
    01556
    01557         /*
    01558         * Sanity check radii
    01559         */
    01560         if ((rx < 0) || (ry < 0)) {
    01561                 return (-1);
    01562         }
    01563
    01564         /*
    01565         * Special case for rx=0 - draw a vline
    01566         */
    01567         if (rx == 0) {
    01568                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    01569         }
    01570         /*
    01571         * Special case for ry=0 - draw a hline
    01572         */
    01573         if (ry == 0) {
    01574                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    01575         }
    01576
    01577         /*
    01578         * Set color
    01579         */
    01580         result = 0;
    01581         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01582         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    01583
    01584         /*
    01585         * Init vars
    01586         */
    01587         oh = oi = oj = ok = 0xFFFF;
    01588
    01589         /*
    01590         * Draw
    01591         */
    01592         if (rx > ry) {
    01593                 ix = 0;
    01594                 iy = rx * 64;
    01595
    01596                 do {
    01597                         h = (ix + 32) >> 6;
    01598                         i = (iy + 32) >> 6;
    01599                         j = (h * ry) / rx;
    01600                         k = (i * ry) / rx;
    01601
    01602                         if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
    01603                                 xph = x + h;
    01604                                 xmh = x - h;
    01605                                 if (k > 0) {
    01606                                         ypk = y + k;
    01607                                         ymk = y - k;
    01608                                         result |= pixel(renderer, xmh, ypk);
    01609                                         result |= pixel(renderer, xph, ypk);
    01610                                         result |= pixel(renderer, xmh, ymk);
    01611                                         result |= pixel(renderer, xph, ymk);
    01612                                 } else {
    01613                                         result |= pixel(renderer, xmh, y);
    01614                                         result |= pixel(renderer, xph, y);
    01615                                 }
    01616                                 ok = k;
    01617                                 xpi = x + i;
    01618                                 xmi = x - i;
    01619                                 if (j > 0) {
    01620                                         ypj = y + j;
    01621                                         ymj = y - j;
    01622                                         result |= pixel(renderer, xmi, ypj);
    01623                                         result |= pixel(renderer, xpi, ypj);
    01624                                         result |= pixel(renderer, xmi, ymj);
    01625                                         result |= pixel(renderer, xpi, ymj);
    01626                                 } else {
    01627                                         result |= pixel(renderer, xmi, y);
    01628                                         result |= pixel(renderer, xpi, y);
    01629                                 }
    01630                                 oj = j;
    01631                         }
    01632
    01633                         ix = ix + iy / rx;
    01634                         iy = iy - ix / rx;
    01635
    01636                 } while (i > h);
    01637         } else {
    01638                 ix = 0;
    01639                 iy = ry * 64;
    01640
    01641                 do {
    01642                         h = (ix + 32) >> 6;
    01643                         i = (iy + 32) >> 6;
    01644                         j = (h * rx) / ry;
    01645                         k = (i * rx) / ry;
    01646
    01647                         if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
    01648                                 xmj = x - j;
    01649                                 xpj = x + j;
    01650                                 if (i > 0) {
    01651                                         ypi = y + i;
    01652                                         ymi = y - i;
    01653                                         result |= pixel(renderer, xmj, ypi);
    01654                                         result |= pixel(renderer, xpj, ypi);
    01655                                         result |= pixel(renderer, xmj, ymi);
    01656                                         result |= pixel(renderer, xpj, ymi);
    01657                                 } else {
    01658                                         result |= pixel(renderer, xmj, y);
    01659                                         result |= pixel(renderer, xpj, y);
    01660                                 }
    01661                                 oi = i;
    01662                                 xmk = x - k;
    01663                                 xpk = x + k;
    01664                                 if (h > 0) {
    01665                                         yph = y + h;
    01666                                         ymh = y - h;
    01667                                         result |= pixel(renderer, xmk, yph);
    01668                                         result |= pixel(renderer, xpk, yph);
    01669                                         result |= pixel(renderer, xmk, ymh);
    01670                                         result |= pixel(renderer, xpk, ymh);
    01671                                 } else {
    01672                                         result |= pixel(renderer, xmk, y);
    01673                                         result |= pixel(renderer, xpk, y);
    01674                                 }
    01675                                 oh = h;
    01676                         }
    01677
    01678                         ix = ix + iy / ry;
    01679                         iy = iy - ix / ry;
    01680
    01681                 } while (i > h);
    01682         }
    01683
    01684         return (result);
    01685 }
    01686
    01687 /* ----- AA Ellipse */
    01688
    01689 /* Windows targets do not have lrint, so provide a local inline version */
    01690 #if defined(_MSC_VER)
    01691 /* Detect 64bit and use intrinsic version */
    01692 #ifdef _M_X64
    01693 #include <emmintrin.h>
    01694 static __inline long
    01695         lrint(float f)
    01696 {
    01697         return _mm_cvtss_si32(_mm_load_ss(&f));
    01698 }
    01699 #elif defined(_M_IX86)
    01700 __inline long int
    01701         lrint (double flt)
    01702 {
    01703         int intgr;
    01704         _asm
    01705         {
    01706                 fld flt
    01707                         fistp intgr
    01708         };
    01709         return intgr;
    01710 }
    01711 #elif defined(_M_ARM)
    01712 #include <armintr.h>
    01713 #pragma warning(push)
    01714 #pragma warning(disable: 4716)
    01715 __declspec(naked) long int
    01716         lrint (double flt)
    01717 {
    01718         __emit(0xEC410B10); // fmdrr  d0, r0, r1
    01719         __emit(0xEEBD0B40); // ftosid s0, d0
    01720         __emit(0xEE100A10); // fmrs   r0, s0
    01721         __emit(0xE12FFF1E); // bx     lr
    01722 }
    01723 #pragma warning(pop)
    01724 #else
    01725 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
    01726 #endif
    01727 #endif
    01728
    01741 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    01742 {
    01743         Uint8 *c = (Uint8 *)&color;
    01744         return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    01745 }
    01746
    01762 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01763 {
    01764         int result;
    01765         int i;
    01766         int a2, b2, ds, dt, dxt, t, s, d;
    01767         Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
    01768         float cp;
    01769         double sab;
    01770         Uint8 weight, iweight;
    01771
    01772         /*
    01773         * Sanity check radii
    01774         */
    01775         if ((rx < 0) || (ry < 0)) {
    01776                 return (-1);
    01777         }
    01778
    01779         /*
    01780         * Special case for rx=0 - draw a vline
    01781         */
    01782         if (rx == 0) {
    01783                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    01784         }
    01785         /*
    01786         * Special case for ry=0 - draw an hline
    01787         */
    01788         if (ry == 0) {
    01789                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    01790         }
    01791
    01792         /* Variable setup */
    01793         a2 = rx * rx;
    01794         b2 = ry * ry;
    01795
    01796         ds = 2 * a2;
    01797         dt = 2 * b2;
    01798
    01799         xc2 = 2 * x;
    01800         yc2 = 2 * y;
    01801
    01802         sab = sqrt((double)(a2 + b2));
    01803         od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
    01804         dxt = (Sint16)lrint((double)a2 / sab) + od;
    01805
    01806         t = 0;
    01807         s = -2 * a2 * ry;
    01808         d = 0;
    01809
    01810         xp = x;
    01811         yp = y - ry;
    01812
    01813         /* Draw */
    01814         result = 0;
    01815         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    01816
    01817         /* "End points" */
    01818         result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
    01819         result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
    01820         result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
    01821         result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
    01822
    01823         for (i = 1; i <= dxt; i++) {
    01824                 xp--;
    01825                 d += t - b2;
    01826
    01827                 if (d >= 0)
    01828                         ys = yp - 1;
    01829                 else if ((d - s - a2) > 0) {
    01830                         if ((2 * d - s - a2) >= 0)
    01831                                 ys = yp + 1;
    01832                         else {
    01833                                 ys = yp;
    01834                                 yp++;
    01835                                 d -= s + a2;
    01836                                 s += ds;
    01837                         }
    01838                 } else {
    01839                         yp++;
    01840                         ys = yp + 1;
    01841                         d -= s + a2;
    01842                         s += ds;
    01843                 }
    01844
    01845                 t -= dt;
    01846
    01847                 /* Calculate alpha */
    01848                 if (s != 0) {
    01849                         cp = (float) abs(d) / (float) abs(s);
    01850                         if (cp > 1.0) {
    01851                                 cp = 1.0;
    01852                         }
    01853                 } else {
    01854                         cp = 1.0;
    01855                 }
    01856
    01857                 /* Calculate weights */
    01858                 weight = (Uint8) (cp * 255);
    01859                 iweight = 255 - weight;
    01860
    01861                 /* Upper half */
    01862                 xx = xc2 - xp;
    01863                 result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
    01864                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
    01865
    01866                 result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
    01867                 result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
    01868
    01869                 /* Lower half */
    01870                 yy = yc2 - yp;
    01871                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
    01872                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
    01873
    01874                 yy = yc2 - ys;
    01875                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
    01876                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
    01877         }
    01878
    01879         /* Replaces original approximation code dyt = abs(yp - yc); */
    01880         dyt = (Sint16)lrint((double)b2 / sab ) + od;
    01881
    01882         for (i = 1; i <= dyt; i++) {
    01883                 yp++;
    01884                 d -= s + a2;
    01885
    01886                 if (d <= 0)
    01887                         xs = xp + 1;
    01888                 else if ((d + t - b2) < 0) {
    01889                         if ((2 * d + t - b2) <= 0)
    01890                                 xs = xp - 1;
    01891                         else {
    01892                                 xs = xp;
    01893                                 xp--;
    01894                                 d += t - b2;
    01895                                 t -= dt;
    01896                         }
    01897                 } else {
    01898                         xp--;
    01899                         xs = xp - 1;
    01900                         d += t - b2;
    01901                         t -= dt;
    01902                 }
    01903
    01904                 s += ds;
    01905
    01906                 /* Calculate alpha */
    01907                 if (t != 0) {
    01908                         cp = (float) abs(d) / (float) abs(t);
    01909                         if (cp > 1.0) {
    01910                                 cp = 1.0;
    01911                         }
    01912                 } else {
    01913                         cp = 1.0;
    01914                 }
    01915
    01916                 /* Calculate weight */
    01917                 weight = (Uint8) (cp * 255);
    01918                 iweight = 255 - weight;
    01919
    01920                 /* Left half */
    01921                 xx = xc2 - xp;
    01922                 yy = yc2 - yp;
    01923                 result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
    01924                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
    01925
    01926                 result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
    01927                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
    01928
    01929                 /* Right half */
    01930                 xx = xc2 - xs;
    01931                 result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
    01932                 result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
    01933
    01934                 result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
    01935                 result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
    01936         }
    01937
    01938         return (result);
    01939 }
    01940
    01941 /* ---- Filled Ellipse */
    01942
    01955 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
    01956 {
    01957         Uint8 *c = (Uint8 *)&color;
    01958         return filledEllipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
    01959 }
    01960
    01976 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    01977 {
    01978         int result;
    01979         int ix, iy;
    01980         int h, i, j, k;
    01981         int oh, oi, oj, ok;
    01982         int xmh, xph;
    01983         int xmi, xpi;
    01984         int xmj, xpj;
    01985         int xmk, xpk;
    01986
    01987         /*
    01988         * Sanity check radii
    01989         */
    01990         if ((rx < 0) || (ry < 0)) {
    01991                 return (-1);
    01992         }
    01993
    01994         /*
    01995         * Special case for rx=0 - draw a vline
    01996         */
    01997         if (rx == 0) {
    01998                 return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
    01999         }
    02000         /*
    02001         * Special case for ry=0 - draw a hline
    02002         */
    02003         if (ry == 0) {
    02004                 return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
    02005         }
    02006
    02007         /*
    02008         * Set color
    02009         */
    02010         result = 0;
    02011         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02012         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02013
    02014         /*
    02015         * Init vars
    02016         */
    02017         oh = oi = oj = ok = 0xFFFF;
    02018
    02019         /*
    02020         * Draw
    02021         */
    02022         if (rx > ry) {
    02023                 ix = 0;
    02024                 iy = rx * 64;
    02025
    02026                 do {
    02027                         h = (ix + 32) >> 6;
    02028                         i = (iy + 32) >> 6;
    02029                         j = (h * ry) / rx;
    02030                         k = (i * ry) / rx;
    02031
    02032                         if ((ok != k) && (oj != k)) {
    02033                                 xph = x + h;
    02034                                 xmh = x - h;
    02035                                 if (k > 0) {
    02036                                         result |= hline(renderer, xmh, xph, y + k);
    02037                                         result |= hline(renderer, xmh, xph, y - k);
    02038                                 } else {
    02039                                         result |= hline(renderer, xmh, xph, y);
    02040                                 }
    02041                                 ok = k;
    02042                         }
    02043                         if ((oj != j) && (ok != j) && (k != j)) {
    02044                                 xmi = x - i;
    02045                                 xpi = x + i;
    02046                                 if (j > 0) {
    02047                                         result |= hline(renderer, xmi, xpi, y + j);
    02048                                         result |= hline(renderer, xmi, xpi, y - j);
    02049                                 } else {
    02050                                         result |= hline(renderer, xmi, xpi, y);
    02051                                 }
    02052                                 oj = j;
    02053                         }
    02054
    02055                         ix = ix + iy / rx;
    02056                         iy = iy - ix / rx;
    02057
    02058                 } while (i > h);
    02059         } else {
    02060                 ix = 0;
    02061                 iy = ry * 64;
    02062
    02063                 do {
    02064                         h = (ix + 32) >> 6;
    02065                         i = (iy + 32) >> 6;
    02066                         j = (h * rx) / ry;
    02067                         k = (i * rx) / ry;
    02068
    02069                         if ((oi != i) && (oh != i)) {
    02070                                 xmj = x - j;
    02071                                 xpj = x + j;
    02072                                 if (i > 0) {
    02073                                         result |= hline(renderer, xmj, xpj, y + i);
    02074                                         result |= hline(renderer, xmj, xpj, y - i);
    02075                                 } else {
    02076                                         result |= hline(renderer, xmj, xpj, y);
    02077                                 }
    02078                                 oi = i;
    02079                         }
    02080                         if ((oh != h) && (oi != h) && (i != h)) {
    02081                                 xmk = x - k;
    02082                                 xpk = x + k;
    02083                                 if (h > 0) {
    02084                                         result |= hline(renderer, xmk, xpk, y + h);
    02085                                         result |= hline(renderer, xmk, xpk, y - h);
    02086                                 } else {
    02087                                         result |= hline(renderer, xmk, xpk, y);
    02088                                 }
    02089                                 oh = h;
    02090                         }
    02091
    02092                         ix = ix + iy / ry;
    02093                         iy = iy - ix / ry;
    02094
    02095                 } while (i > h);
    02096         }
    02097
    02098         return (result);
    02099 }
    02100
    02101 /* ----- Pie */
    02102
    02122 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)
    02123 {
    02124         int result;
    02125         double angle, start_angle, end_angle;
    02126         double deltaAngle;
    02127         double dr;
    02128         int numpoints, i;
    02129         Sint16 *vx, *vy;
    02130
    02131         /*
    02132         * Sanity check radii
    02133         */
    02134         if (rad < 0) {
    02135                 return (-1);
    02136         }
    02137
    02138         /*
    02139         * Fixup angles
    02140         */
    02141         start = start % 360;
    02142         end = end % 360;
    02143
    02144         /*
    02145         * Special case for rad=0 - draw a point
    02146         */
    02147         if (rad == 0) {
    02148                 return (pixelRGBA(renderer, x, y, r, g, b, a));
    02149         }
    02150
    02151         /*
    02152         * Variable setup
    02153         */
    02154         dr = (double) rad;
    02155         deltaAngle = 3.0 / dr;
    02156         start_angle = (double) start *(2.0 * M_PI / 360.0);
    02157         end_angle = (double) end *(2.0 * M_PI / 360.0);
    02158         if (start > end) {
    02159                 end_angle += (2.0 * M_PI);
    02160         }
    02161
    02162         /* We will always have at least 2 points */
    02163         numpoints = 2;
    02164
    02165         /* Count points (rather than calculating it) */
    02166         angle = start_angle;
    02167         while (angle < end_angle) {
    02168                 angle += deltaAngle;
    02169                 numpoints++;
    02170         }
    02171
    02172         /* Allocate combined vertex array */
    02173         vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
    02174         if (vx == NULL) {
    02175                 return (-1);
    02176         }
    02177
    02178         /* Update point to start of vy */
    02179         vy += numpoints;
    02180
    02181         /* Center */
    02182         vx[0] = x;
    02183         vy[0] = y;
    02184
    02185         /* First vertex */
    02186         angle = start_angle;
    02187         vx[1] = x + (int) (dr * cos(angle));
    02188         vy[1] = y + (int) (dr * sin(angle));
    02189
    02190         if (numpoints<3)
    02191         {
    02192                 result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
    02193         }
    02194         else
    02195         {
    02196                 /* Calculate other vertices */
    02197                 i = 2;
    02198                 angle = start_angle;
    02199                 while (angle < end_angle) {
    02200                         angle += deltaAngle;
    02201                         if (angle>end_angle)
    02202                         {
    02203                                 angle = end_angle;
    02204                         }
    02205                         vx[i] = x + (int) (dr * cos(angle));
    02206                         vy[i] = y + (int) (dr * sin(angle));
    02207                         i++;
    02208                 }
    02209
    02210                 /* Draw */
    02211                 if (filled) {
    02212                         result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
    02213                 } else {
    02214                         result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
    02215                 }
    02216         }
    02217
    02218         /* Free combined vertex array */
    02219         free(vx);
    02220
    02221         return (result);
    02222 }
    02223
    02237 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02238         Sint16 start, Sint16 end, Uint32 color)
    02239 {
    02240         Uint8 *c = (Uint8 *)&color;
    02241         return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
    02242 }
    02243
    02260 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02261         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02262 {
    02263         return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
    02264 }
    02265
    02279 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
    02280 {
    02281         Uint8 *c = (Uint8 *)&color;
    02282         return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
    02283 }
    02284
    02301 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
    02302         Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02303 {
    02304         return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
    02305 }
    02306
    02307 /* ------ Trigon */
    02308
    02325 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02326 {
    02327         Sint16 vx[3];
    02328         Sint16 vy[3];
    02329
    02330         vx[0]=x1;
    02331         vx[1]=x2;
    02332         vx[2]=x3;
    02333         vy[0]=y1;
    02334         vy[1]=y2;
    02335         vy[2]=y3;
    02336
    02337         return(polygonColor(renderer,vx,vy,3,color));
    02338 }
    02339
    02357 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02358         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02359 {
    02360         Sint16 vx[3];
    02361         Sint16 vy[3];
    02362
    02363         vx[0]=x1;
    02364         vx[1]=x2;
    02365         vx[2]=x3;
    02366         vy[0]=y1;
    02367         vy[1]=y2;
    02368         vy[2]=y3;
    02369
    02370         return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02371 }
    02372
    02373 /* ------ AA-Trigon */
    02374
    02391 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02392 {
    02393         Sint16 vx[3];
    02394         Sint16 vy[3];
    02395
    02396         vx[0]=x1;
    02397         vx[1]=x2;
    02398         vx[2]=x3;
    02399         vy[0]=y1;
    02400         vy[1]=y2;
    02401         vy[2]=y3;
    02402
    02403         return(aapolygonColor(renderer,vx,vy,3,color));
    02404 }
    02405
    02423 int aatrigonRGBA(SDL_Renderer * renderer,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02424         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02425 {
    02426         Sint16 vx[3];
    02427         Sint16 vy[3];
    02428
    02429         vx[0]=x1;
    02430         vx[1]=x2;
    02431         vx[2]=x3;
    02432         vy[0]=y1;
    02433         vy[1]=y2;
    02434         vy[2]=y3;
    02435
    02436         return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02437 }
    02438
    02439 /* ------ Filled Trigon */
    02440
    02457 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
    02458 {
    02459         Sint16 vx[3];
    02460         Sint16 vy[3];
    02461
    02462         vx[0]=x1;
    02463         vx[1]=x2;
    02464         vx[2]=x3;
    02465         vy[0]=y1;
    02466         vy[1]=y2;
    02467         vy[2]=y3;
    02468
    02469         return(filledPolygonColor(renderer,vx,vy,3,color));
    02470 }
    02471
    02491 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
    02492         Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02493 {
    02494         Sint16 vx[3];
    02495         Sint16 vy[3];
    02496
    02497         vx[0]=x1;
    02498         vx[1]=x2;
    02499         vx[2]=x3;
    02500         vy[0]=y1;
    02501         vy[1]=y2;
    02502         vy[2]=y3;
    02503
    02504         return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
    02505 }
    02506
    02507 /* ---- Polygon */
    02508
    02520 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    02521 {
    02522         Uint8 *c = (Uint8 *)&color;
    02523         return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
    02524 }
    02525
    02536 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
    02537 {
    02538         /*
    02539         * Draw
    02540         */
    02541         int result;
    02542         int i, nn;
    02543         SDL_Point* points;
    02544
    02545         /*
    02546         * Vertex array NULL check
    02547         */
    02548         if (vx == NULL) {
    02549                 return (-1);
    02550         }
    02551         if (vy == NULL) {
    02552                 return (-1);
    02553         }
    02554
    02555         /*
    02556         * Sanity check
    02557         */
    02558         if (n < 3) {
    02559                 return (-1);
    02560         }
    02561
    02562         /*
    02563         * Create array of points
    02564         */
    02565         nn = n + 1;
    02566         points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
    02567         if (points == NULL)
    02568         {
    02569                 return -1;
    02570         }
    02571         for (i=0; i<n; i++)
    02572         {
    02573                 points[i].x = vx[i];
    02574                 points[i].y = vy[i];
    02575         }
    02576         points[n].x = vx[0];
    02577         points[n].y = vy[0];
    02578
    02579         /*
    02580         * Draw
    02581         */
    02582         result |= SDL_RenderDrawLines(renderer, points, nn);
    02583         free(points);
    02584
    02585         return (result);
    02586 }
    02587
    02602 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02603 {
    02604         /*
    02605         * Draw
    02606         */
    02607         int result;
    02608         const Sint16 *x1, *y1, *x2, *y2;
    02609
    02610         /*
    02611         * Vertex array NULL check
    02612         */
    02613         if (vx == NULL) {
    02614                 return (-1);
    02615         }
    02616         if (vy == NULL) {
    02617                 return (-1);
    02618         }
    02619
    02620         /*
    02621         * Sanity check
    02622         */
    02623         if (n < 3) {
    02624                 return (-1);
    02625         }
    02626
    02627         /*
    02628         * Pointer setup
    02629         */
    02630         x1 = x2 = vx;
    02631         y1 = y2 = vy;
    02632         x2++;
    02633         y2++;
    02634
    02635         /*
    02636         * Set color
    02637         */
    02638         result = 0;
    02639         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02640         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02641
    02642         /*
    02643         * Draw
    02644         */
    02645         result |= polygon(renderer, vx, vy, n);
    02646
    02647         return (result);
    02648 }
    02649
    02650 /* ---- AA-Polygon */
    02651
    02663 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    02664 {
    02665         Uint8 *c = (Uint8 *)&color;
    02666         return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
    02667 }
    02668
    02683 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02684 {
    02685         int result;
    02686         int i;
    02687         const Sint16 *x1, *y1, *x2, *y2;
    02688
    02689         /*
    02690         * Vertex array NULL check
    02691         */
    02692         if (vx == NULL) {
    02693                 return (-1);
    02694         }
    02695         if (vy == NULL) {
    02696                 return (-1);
    02697         }
    02698
    02699         /*
    02700         * Sanity check
    02701         */
    02702         if (n < 3) {
    02703                 return (-1);
    02704         }
    02705
    02706         /*
    02707         * Pointer setup
    02708         */
    02709         x1 = x2 = vx;
    02710         y1 = y2 = vy;
    02711         x2++;
    02712         y2++;
    02713
    02714         /*
    02715         * Draw
    02716         */
    02717         result = 0;
    02718         for (i = 1; i < n; i++) {
    02719                 result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
    02720                 x1 = x2;
    02721                 y1 = y2;
    02722                 x2++;
    02723                 y2++;
    02724         }
    02725
    02726         result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
    02727
    02728         return (result);
    02729 }
    02730
    02731 /* ---- Filled Polygon */
    02732
    02741 int _gfxPrimitivesCompareInt(const void *a, const void *b)
    02742 {
    02743         return (*(const int *) a) - (*(const int *) b);
    02744 }
    02745
    02751 static int *gfxPrimitivesPolyIntsGlobal = NULL;
    02752
    02758 static int gfxPrimitivesPolyAllocatedGlobal = 0;
    02759
    02778 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)
    02779 {
    02780         int result;
    02781         int i;
    02782         int y, xa, xb;
    02783         int miny, maxy;
    02784         int x1, y1;
    02785         int x2, y2;
    02786         int ind1, ind2;
    02787         int ints;
    02788         int *gfxPrimitivesPolyInts = NULL;
    02789         int *gfxPrimitivesPolyIntsNew = NULL;
    02790         int gfxPrimitivesPolyAllocated = 0;
    02791
    02792         /*
    02793         * Vertex array NULL check
    02794         */
    02795         if (vx == NULL) {
    02796                 return (-1);
    02797         }
    02798         if (vy == NULL) {
    02799                 return (-1);
    02800         }
    02801
    02802         /*
    02803         * Sanity check number of edges
    02804         */
    02805         if (n < 3) {
    02806                 return -1;
    02807         }
    02808
    02809         /*
    02810         * Map polygon cache
    02811         */
    02812         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    02813                 /* Use global cache */
    02814                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    02815                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    02816         } else {
    02817                 /* Use local cache */
    02818                 gfxPrimitivesPolyInts = *polyInts;
    02819                 gfxPrimitivesPolyAllocated = *polyAllocated;
    02820         }
    02821
    02822         /*
    02823         * Allocate temp array, only grow array
    02824         */
    02825         if (!gfxPrimitivesPolyAllocated) {
    02826                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    02827                 gfxPrimitivesPolyAllocated = n;
    02828         } else {
    02829                 if (gfxPrimitivesPolyAllocated < n) {
    02830                         gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    02831                         if (!gfxPrimitivesPolyIntsNew) {
    02832                                 if (!gfxPrimitivesPolyInts) {
    02833                                         free(gfxPrimitivesPolyInts);
    02834                                         gfxPrimitivesPolyInts = NULL;
    02835                                 }
    02836                                 gfxPrimitivesPolyAllocated = 0;
    02837                         } else {
    02838                                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
    02839                                 gfxPrimitivesPolyAllocated = n;
    02840                         }
    02841                 }
    02842         }
    02843
    02844         /*
    02845         * Check temp array
    02846         */
    02847         if (gfxPrimitivesPolyInts==NULL) {
    02848                 gfxPrimitivesPolyAllocated = 0;
    02849         }
    02850
    02851         /*
    02852         * Update cache variables
    02853         */
    02854         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    02855                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    02856                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    02857         } else {
    02858                 *polyInts = gfxPrimitivesPolyInts;
    02859                 *polyAllocated = gfxPrimitivesPolyAllocated;
    02860         }
    02861
    02862         /*
    02863         * Check temp array again
    02864         */
    02865         if (gfxPrimitivesPolyInts==NULL) {
    02866                 return(-1);
    02867         }
    02868
    02869         /*
    02870         * Determine Y maxima
    02871         */
    02872         miny = vy[0];
    02873         maxy = vy[0];
    02874         for (i = 1; (i < n); i++) {
    02875                 if (vy[i] < miny) {
    02876                         miny = vy[i];
    02877                 } else if (vy[i] > maxy) {
    02878                         maxy = vy[i];
    02879                 }
    02880         }
    02881
    02882         /*
    02883         * Draw, scanning y
    02884         */
    02885         result = 0;
    02886         for (y = miny; (y <= maxy); y++) {
    02887                 ints = 0;
    02888                 for (i = 0; (i < n); i++) {
    02889                         if (!i) {
    02890                                 ind1 = n - 1;
    02891                                 ind2 = 0;
    02892                         } else {
    02893                                 ind1 = i - 1;
    02894                                 ind2 = i;
    02895                         }
    02896                         y1 = vy[ind1];
    02897                         y2 = vy[ind2];
    02898                         if (y1 < y2) {
    02899                                 x1 = vx[ind1];
    02900                                 x2 = vx[ind2];
    02901                         } else if (y1 > y2) {
    02902                                 y2 = vy[ind1];
    02903                                 y1 = vy[ind2];
    02904                                 x2 = vx[ind1];
    02905                                 x1 = vx[ind2];
    02906                         } else {
    02907                                 continue;
    02908                         }
    02909                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    02910                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    02911                         }
    02912                 }
    02913
    02914                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    02915
    02916                 /*
    02917                 * Set color
    02918                 */
    02919                 result = 0;
    02920             result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    02921                 result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    02922
    02923                 for (i = 0; (i < ints); i += 2) {
    02924                         xa = gfxPrimitivesPolyInts[i] + 1;
    02925                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    02926                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    02927                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    02928                         result |= hline(renderer, xa, xb, y);
    02929                 }
    02930         }
    02931
    02932         return (result);
    02933 }
    02934
    02946 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
    02947 {
    02948         Uint8 *c = (Uint8 *)&color;
    02949         return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
    02950 }
    02951
    02966 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    02967 {
    02968         return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
    02969 }
    02970
    02971 /* ---- Textured Polygon */
    02972
    02988 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)
    02989 {
    02990         Sint16 w;
    02991         Sint16 xtmp;
    02992         int result = 0;
    02993         int texture_x_walker;
    02994         int texture_y_start;
    02995         SDL_Rect source_rect,dst_rect;
    02996         int pixels_written,write_width;
    02997
    02998         /*
    02999         * Swap x1, x2 if required to ensure x1<=x2
    03000         */
    03001         if (x1 > x2) {
    03002                 xtmp = x1;
    03003                 x1 = x2;
    03004                 x2 = xtmp;
    03005         }
    03006
    03007         /*
    03008         * Calculate width to draw
    03009         */
    03010         w = x2 - x1 + 1;
    03011
    03012         /*
    03013         * Determine where in the texture we start drawing
    03014         */
    03015         texture_x_walker =   (x1 - texture_dx)  % texture_w;
    03016         if (texture_x_walker < 0){
    03017                 texture_x_walker = texture_w + texture_x_walker ;
    03018         }
    03019
    03020         texture_y_start = (y + texture_dy) % texture_h;
    03021         if (texture_y_start < 0){
    03022                 texture_y_start = texture_h + texture_y_start;
    03023         }
    03024
    03025         // setup the source rectangle; we are only drawing one horizontal line
    03026         source_rect.y = texture_y_start;
    03027         source_rect.x = texture_x_walker;
    03028         source_rect.h = 1;
    03029
    03030         // we will draw to the current y
    03031         dst_rect.y = y;
    03032
    03033         // if there are enough pixels left in the current row of the texture
    03034         // draw it all at once
    03035         if (w <= texture_w -texture_x_walker){
    03036                 source_rect.w = w;
    03037                 source_rect.x = texture_x_walker;
    03038                 dst_rect.x= x1;
    03039                 result = (SDL_RenderCopy(renderer, texture, &source_rect ,&dst_rect) == 0);
    03040         } else { // we need to draw multiple times
    03041                 // draw the first segment
    03042                 pixels_written = texture_w  - texture_x_walker;
    03043                 source_rect.w = pixels_written;
    03044                 source_rect.x = texture_x_walker;
    03045                 dst_rect.x= x1;
    03046                 result |= (SDL_RenderCopy(renderer, texture, &source_rect , &dst_rect) == 0);
    03047                 write_width = texture_w;
    03048
    03049                 // now draw the rest
    03050                 // set the source x to 0
    03051                 source_rect.x = 0;
    03052                 while (pixels_written < w){
    03053                         if (write_width >= w - pixels_written) {
    03054                                 write_width =  w - pixels_written;
    03055                         }
    03056                         source_rect.w = write_width;
    03057                         dst_rect.x = x1 + pixels_written;
    03058                         result  |= (SDL_RenderCopy(renderer,texture,&source_rect , &dst_rect) == 0);
    03059                         pixels_written += write_width;
    03060                 }
    03061         }
    03062
    03063         return result;
    03064 }
    03065
    03082 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
    03083         SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
    03084 {
    03085         int result;
    03086         int i;
    03087         int y, xa, xb;
    03088         int minx,maxx,miny, maxy;
    03089         int x1, y1;
    03090         int x2, y2;
    03091         int ind1, ind2;
    03092         int ints;
    03093         int *gfxPrimitivesPolyInts = NULL;
    03094         int gfxPrimitivesPolyAllocated = 0;
    03095         SDL_Texture *textureAsTexture;
    03096
    03097         /*
    03098         * Sanity check number of edges
    03099         */
    03100         if (n < 3) {
    03101                 return -1;
    03102         }
    03103
    03104         /*
    03105         * Map polygon cache
    03106         */
    03107         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    03108                 /* Use global cache */
    03109                 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
    03110                 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
    03111         } else {
    03112                 /* Use local cache */
    03113                 gfxPrimitivesPolyInts = *polyInts;
    03114                 gfxPrimitivesPolyAllocated = *polyAllocated;
    03115         }
    03116
    03117         /*
    03118         * Allocate temp array, only grow array
    03119         */
    03120         if (!gfxPrimitivesPolyAllocated) {
    03121                 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
    03122                 gfxPrimitivesPolyAllocated = n;
    03123         } else {
    03124                 if (gfxPrimitivesPolyAllocated < n) {
    03125                         gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
    03126                         gfxPrimitivesPolyAllocated = n;
    03127                 }
    03128         }
    03129
    03130         /*
    03131         * Check temp array
    03132         */
    03133         if (gfxPrimitivesPolyInts==NULL) {
    03134                 gfxPrimitivesPolyAllocated = 0;
    03135         }
    03136
    03137         /*
    03138         * Update cache variables
    03139         */
    03140         if ((polyInts==NULL) || (polyAllocated==NULL)) {
    03141                 gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
    03142                 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
    03143         } else {
    03144                 *polyInts = gfxPrimitivesPolyInts;
    03145                 *polyAllocated = gfxPrimitivesPolyAllocated;
    03146         }
    03147
    03148         /*
    03149         * Check temp array again
    03150         */
    03151         if (gfxPrimitivesPolyInts==NULL) {
    03152                 return(-1);
    03153         }
    03154
    03155         /*
    03156         * Determine X,Y minima,maxima
    03157         */
    03158         miny = vy[0];
    03159         maxy = vy[0];
    03160         minx = vx[0];
    03161         maxx = vx[0];
    03162         for (i = 1; (i < n); i++) {
    03163                 if (vy[i] < miny) {
    03164                         miny = vy[i];
    03165                 } else if (vy[i] > maxy) {
    03166                         maxy = vy[i];
    03167                 }
    03168                 if (vx[i] < minx) {
    03169                         minx = vx[i];
    03170                 } else if (vx[i] > maxx) {
    03171                         maxx = vx[i];
    03172                 }
    03173         }
    03174
    03175         /*
    03176         * Draw, scanning y
    03177         */
    03178         result = 0;
    03179         for (y = miny; (y <= maxy); y++) {
    03180                 ints = 0;
    03181                 for (i = 0; (i < n); i++) {
    03182                         if (!i) {
    03183                                 ind1 = n - 1;
    03184                                 ind2 = 0;
    03185                         } else {
    03186                                 ind1 = i - 1;
    03187                                 ind2 = i;
    03188                         }
    03189                         y1 = vy[ind1];
    03190                         y2 = vy[ind2];
    03191                         if (y1 < y2) {
    03192                                 x1 = vx[ind1];
    03193                                 x2 = vx[ind2];
    03194                         } else if (y1 > y2) {
    03195                                 y2 = vy[ind1];
    03196                                 y1 = vy[ind2];
    03197                                 x2 = vx[ind1];
    03198                                 x1 = vx[ind2];
    03199                         } else {
    03200                                 continue;
    03201                         }
    03202                         if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
    03203                                 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
    03204                         }
    03205                 }
    03206
    03207                 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
    03208
    03209                 textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
    03210                 if (textureAsTexture == NULL)
    03211                 {
    03212                         return (-1);
    03213                 }
    03214
    03215                 for (i = 0; (i < ints); i += 2) {
    03216                         xa = gfxPrimitivesPolyInts[i] + 1;
    03217                         xa = (xa >> 16) + ((xa & 32768) >> 15);
    03218                         xb = gfxPrimitivesPolyInts[i+1] - 1;
    03219                         xb = (xb >> 16) + ((xb & 32768) >> 15);
    03220                         result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
    03221                 }
    03222                 SDL_DestroyTexture(textureAsTexture);
    03223         }
    03224
    03225         return (result);
    03226 }
    03227
    03244 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
    03245 {
    03246         /*
    03247         * Draw
    03248         */
    03249         return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
    03250 }
    03251
    03252 /* ---- Character */
    03253
    03257 static SDL_Texture *gfxPrimitivesFont[256];
    03258
    03262 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
    03263
    03267 static Uint32 charWidth = 8;
    03268
    03272 static Uint32 charHeight = 8;
    03273
    03277 static Uint32 charWidthLocal = 8;
    03278
    03282 static Uint32 charHeightLocal = 8;
    03283
    03287 static Uint32 charPitch = 1;
    03288
    03292 static Uint32 charRotation = 0;
    03293
    03297 static Uint32 charSize = 8;
    03298
    03312 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
    03313 {
    03314         int i;
    03315
    03316         if ((fontdata) && (cw) && (ch)) {
    03317                 currentFontdata = (unsigned char *)fontdata;
    03318                 charWidth = cw;
    03319                 charHeight = ch;
    03320         } else {
    03321                 currentFontdata = gfxPrimitivesFontdata;
    03322                 charWidth = 8;
    03323                 charHeight = 8;
    03324         }
    03325
    03326         charPitch = (charWidth+7)/8;
    03327         charSize = charPitch * charHeight;
    03328
    03329         /* Maybe flip width/height for rendering */
    03330         if ((charRotation==1) || (charRotation==3))
    03331         {
    03332                 charWidthLocal = charHeight;
    03333                 charHeightLocal = charWidth;
    03334         }
    03335         else
    03336         {
    03337                 charWidthLocal = charWidth;
    03338                 charHeightLocal = charHeight;
    03339         }
    03340
    03341         /* Clear character cache */
    03342         for (i = 0; i < 256; i++) {
    03343                 if (gfxPrimitivesFont[i]) {
    03344                         SDL_DestroyTexture(gfxPrimitivesFont[i]);
    03345                         gfxPrimitivesFont[i] = NULL;
    03346                 }
    03347         }
    03348 }
    03349
    03358 void gfxPrimitivesSetFontRotation(Uint32 rotation)
    03359 {
    03360         int i;
    03361
    03362         rotation = rotation & 3;
    03363         if (charRotation != rotation)
    03364         {
    03365                 /* Store rotation */
    03366                 charRotation = rotation;
    03367
    03368                 /* Maybe flip width/height for rendering */
    03369                 if ((charRotation==1) || (charRotation==3))
    03370                 {
    03371                         charWidthLocal = charHeight;
    03372                         charHeightLocal = charWidth;
    03373                 }
    03374                 else
    03375                 {
    03376                         charWidthLocal = charWidth;
    03377                         charHeightLocal = charHeight;
    03378                 }
    03379
    03380                 /* Clear character cache */
    03381                 for (i = 0; i < 256; i++) {
    03382                         if (gfxPrimitivesFont[i]) {
    03383                                 SDL_DestroyTexture(gfxPrimitivesFont[i]);
    03384                                 gfxPrimitivesFont[i] = NULL;
    03385                         }
    03386                 }
    03387         }
    03388 }
    03389
    03404 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03405 {
    03406         SDL_Rect srect;
    03407         SDL_Rect drect;
    03408         int result;
    03409         Uint32 ix, iy;
    03410         const unsigned char *charpos;
    03411         Uint8 *curpos;
    03412         Uint8 patt, mask;
    03413         Uint8 *linepos;
    03414         Uint32 pitch;
    03415         SDL_Surface *character;
    03416         SDL_Surface *rotatedCharacter;
    03417         Uint32 ci;
    03418
    03419         /*
    03420         * Setup source rectangle
    03421         */
    03422         srect.x = 0;
    03423         srect.y = 0;
    03424         srect.w = charWidthLocal;
    03425         srect.h = charHeightLocal;
    03426
    03427         /*
    03428         * Setup destination rectangle
    03429         */
    03430         drect.x = x;
    03431         drect.y = y;
    03432         drect.w = charWidthLocal;
    03433         drect.h = charHeightLocal;
    03434
    03435         /* Character index in cache */
    03436         ci = (unsigned char) c;
    03437
    03438         /*
    03439         * Create new charWidth x charHeight bitmap surface if not already present.
    03440         * Might get rotated later.
    03441         */
    03442         if (gfxPrimitivesFont[ci] == NULL) {
    03443                 /*
    03444                 * Redraw character into surface
    03445                 */
    03446                 character =     SDL_CreateRGBSurface(SDL_SWSURFACE,
    03447                         charWidth, charHeight, 32,
    03448                         0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
    03449                 if (character == NULL) {
    03450                         return (-1);
    03451                 }
    03452
    03453                 charpos = currentFontdata + ci * charSize;
    03454                                 linepos = (Uint8 *)character->pixels;
    03455                 pitch = character->pitch;
    03456
    03457                 /*
    03458                 * Drawing loop
    03459                 */
    03460                 patt = 0;
    03461                 for (iy = 0; iy < charHeight; iy++) {
    03462                         mask = 0x00;
    03463                         curpos = linepos;
    03464                         for (ix = 0; ix < charWidth; ix++) {
    03465                                 if (!(mask >>= 1)) {
    03466                                         patt = *charpos++;
    03467                                         mask = 0x80;
    03468                                 }
    03469                                 if (patt & mask) {
    03470                                         *(Uint32 *)curpos = 0xffffffff;
    03471                                 } else {
    03472                                         *(Uint32 *)curpos = 0;
    03473                                 }
    03474                                 curpos += 4;
    03475                         }
    03476                         linepos += pitch;
    03477                 }
    03478
    03479                 /* Maybe rotate and replace cached image */
    03480                 if (charRotation>0)
    03481                 {
    03482                         rotatedCharacter = rotateSurface90Degrees(character, charRotation);
    03483                         SDL_FreeSurface(character);
    03484                         character = rotatedCharacter;
    03485                 }
    03486
    03487                 /* Convert temp surface into texture */
    03488                 gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
    03489                 SDL_FreeSurface(character);
    03490
    03491                 /*
    03492                 * Check pointer
    03493                 */
    03494                 if (gfxPrimitivesFont[ci] == NULL) {
    03495                         return (-1);
    03496                 }
    03497         }
    03498
    03499         /*
    03500         * Set color
    03501         */
    03502         result = 0;
    03503         result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
    03504         result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
    03505
    03506         /*
    03507         * Draw texture onto destination
    03508         */
    03509         result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
    03510
    03511         return (result);
    03512 }
    03513
    03514
    03526 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
    03527 {
    03528         Uint8 *co = (Uint8 *)&color;
    03529         return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
    03530 }
    03531
    03532
    03547 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
    03548 {
    03549         Uint8 *c = (Uint8 *)&color;
    03550         return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
    03551 }
    03552
    03567 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03568 {
    03569         int result = 0;
    03570         Sint16 curx = x;
    03571         Sint16 cury = y;
    03572         const char *curchar = s;
    03573
    03574         while (*curchar && !result) {
    03575                 result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
    03576                 switch (charRotation)
    03577                 {
    03578                 case 0:
    03579                         curx += charWidthLocal;
    03580                         break;
    03581                 case 2:
    03582                         curx -= charWidthLocal;
    03583                         break;
    03584                 case 1:
    03585                         cury += charHeightLocal;
    03586                         break;
    03587                 case 3:
    03588                         cury -= charHeightLocal;
    03589                         break;
    03590                 }
    03591                 curchar++;
    03592         }
    03593
    03594         return (result);
    03595 }
    03596
    03597 /* ---- Bezier curve */
    03598
    03608 double _evaluateBezier (double *data, int ndata, double t)
    03609 {
    03610         double mu, result;
    03611         int n,k,kn,nn,nkn;
    03612         double blend,muk,munk;
    03613
    03614         /* Sanity check bounds */
    03615         if (t<0.0) {
    03616                 return(data[0]);
    03617         }
    03618         if (t>=(double)ndata) {
    03619                 return(data[ndata-1]);
    03620         }
    03621
    03622         /* Adjust t to the range 0.0 to 1.0 */
    03623         mu=t/(double)ndata;
    03624
    03625         /* Calculate interpolate */
    03626         n=ndata-1;
    03627         result=0.0;
    03628         muk = 1;
    03629         munk = pow(1-mu,(double)n);
    03630         for (k=0;k<=n;k++) {
    03631                 nn = n;
    03632                 kn = k;
    03633                 nkn = n - k;
    03634                 blend = muk * munk;
    03635                 muk *= mu;
    03636                 munk /= (1-mu);
    03637                 while (nn >= 1) {
    03638                         blend *= nn;
    03639                         nn--;
    03640                         if (kn > 1) {
    03641                                 blend /= (double)kn;
    03642                                 kn--;
    03643                         }
    03644                         if (nkn > 1) {
    03645                                 blend /= (double)nkn;
    03646                                 nkn--;
    03647                         }
    03648                 }
    03649                 result += data[k] * blend;
    03650         }
    03651
    03652         return (result);
    03653 }
    03654
    03667 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
    03668 {
    03669         Uint8 *c = (Uint8 *)&color;
    03670         return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
    03671 }
    03672
    03688 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    03689 {
    03690         int result;
    03691         int i;
    03692         double *x, *y, t, stepsize;
    03693         Sint16 x1, y1, x2, y2;
    03694
    03695         /*
    03696         * Sanity check
    03697         */
    03698         if (n < 3) {
    03699                 return (-1);
    03700         }
    03701         if (s < 2) {
    03702                 return (-1);
    03703         }
    03704
    03705         /*
    03706         * Variable setup
    03707         */
    03708         stepsize=(double)1.0/(double)s;
    03709
    03710         /* Transfer vertices into float arrays */
    03711         if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    03712                 return(-1);
    03713         }
    03714         if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
    03715                 free(x);
    03716                 return(-1);
    03717         }
    03718         for (i=0; i<n; i++) {
    03719                 x[i]=(double)vx[i];
    03720                 y[i]=(double)vy[i];
    03721         }
    03722         x[n]=(double)vx[0];
    03723         y[n]=(double)vy[0];
    03724
    03725         /*
    03726         * Set color
    03727         */
    03728         result = 0;
    03729         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    03730         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    03731
    03732         /*
    03733         * Draw
    03734         */
    03735         t=0.0;
    03736         x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
    03737         y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
    03738         for (i = 0; i <= (n*s); i++) {
    03739                 t += stepsize;
    03740                 x2=(Sint16)_evaluateBezier(x,n,t);
    03741                 y2=(Sint16)_evaluateBezier(y,n,t);
    03742                 result |= line(renderer, x1, y1, x2, y2);
    03743                 x1 = x2;
    03744                 y1 = y2;
    03745         }
    03746
    03747         /* Clean up temporary array */
    03748         free(x);
    03749         free(y);
    03750
    03751         return (result);
    03752 }
    03753
    03754
    03755 /* ---- Thick Line */
    03756
    03775 int _bresenhamInitialize(SDL2_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
    03776 {
    03777         int temp;
    03778
    03779         if (b==NULL) {
    03780                 return(-1);
    03781         }
    03782
    03783         b->x = x1;
    03784         b->y = y1;
    03785
    03786         /* dx = abs(x2-x1), s1 = sign(x2-x1) */
    03787         if ((b->dx = x2 - x1) != 0) {
    03788                 if (b->dx < 0) {
    03789                         b->dx = -b->dx;
    03790                         b->s1 = -1;
    03791                 } else {
    03792                         b->s1 = 1;
    03793                 }
    03794         } else {
    03795                 b->s1 = 0;
    03796         }
    03797
    03798         /* dy = abs(y2-y1), s2 = sign(y2-y1)    */
    03799         if ((b->dy = y2 - y1) != 0) {
    03800                 if (b->dy < 0) {
    03801                         b->dy = -b->dy;
    03802                         b->s2 = -1;
    03803                 } else {
    03804                         b->s2 = 1;
    03805                 }
    03806         } else {
    03807                 b->s2 = 0;
    03808         }
    03809
    03810         if (b->dy > b->dx) {
    03811                 temp = b->dx;
    03812                 b->dx = b->dy;
    03813                 b->dy = temp;
    03814                 b->swapdir = 1;
    03815         } else {
    03816                 b->swapdir = 0;
    03817         }
    03818
    03819         b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
    03820         b->dy <<= 1;
    03821         b->error = b->dy - b->dx;
    03822         b->dx <<= 1;
    03823
    03824         return(0);
    03825 }
    03826
    03827
    03837 int _bresenhamIterate(SDL2_gfxBresenhamIterator *b)
    03838 {
    03839         if (b==NULL) {
    03840                 return (-1);
    03841         }
    03842
    03843         /* last point check */
    03844         if (b->count==0) {
    03845                 return (2);
    03846         }
    03847
    03848         while (b->error >= 0) {
    03849                 if (b->swapdir) {
    03850                         b->x += b->s1;
    03851                 } else  {
    03852                         b->y += b->s2;
    03853                 }
    03854
    03855                 b->error -= b->dx;
    03856         }
    03857
    03858         if (b->swapdir) {
    03859                 b->y += b->s2;
    03860         } else {
    03861                 b->x += b->s1;
    03862         }
    03863
    03864         b->error += b->dy;
    03865         b->count--;
    03866
    03867         /* count==0 indicates "end-of-line" */
    03868         return ((b->count) ? 0 : 1);
    03869 }
    03870
    03871
    03880 void _murphyParaline(SDL2_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
    03881 {
    03882         int p;
    03883         d1 = -d1;
    03884
    03885         for (p = 0; p <= m->u; p++) {
    03886
    03887                 pixel(m->renderer, x, y);
    03888
    03889                 if (d1 <= m->kt) {
    03890                         if (m->oct2 == 0) {
    03891                                 x++;
    03892                         } else {
    03893                                 if (m->quad4 == 0) {
    03894                                         y++;
    03895                                 } else {
    03896                                         y--;
    03897                                 }
    03898                         }
    03899                         d1 += m->kv;
    03900                 } else {
    03901                         x++;
    03902                         if (m->quad4 == 0) {
    03903                                 y++;
    03904                         } else {
    03905                                 y--;
    03906                         }
    03907                         d1 += m->kd;
    03908                 }
    03909         }
    03910
    03911         m->tempx = x;
    03912         m->tempy = y;
    03913 }
    03914
    03930 void _murphyIteration(SDL2_gfxMurphyIterator *m, Uint8 miter,
    03931         Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
    03932         Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
    03933 {
    03934         int atemp1, atemp2;
    03935         int ftmp1, ftmp2;
    03936         Uint16 m1x, m1y, m2x, m2y;
    03937         Uint16 fix, fiy, lax, lay, curx, cury;
    03938         Sint16 px[4], py[4];
    03939         SDL2_gfxBresenhamIterator b;
    03940
    03941         if (miter > 1) {
    03942                 if (m->first1x != -32768) {
    03943                         fix = (m->first1x + m->first2x) / 2;
    03944                         fiy = (m->first1y + m->first2y) / 2;
    03945                         lax = (m->last1x + m->last2x) / 2;
    03946                         lay = (m->last1y + m->last2y) / 2;
    03947                         curx = (ml1x + ml2x) / 2;
    03948                         cury = (ml1y + ml2y) / 2;
    03949
    03950                         atemp1 = (fix - curx);
    03951                         atemp2 = (fiy - cury);
    03952                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    03953                         atemp1 = (lax - curx);
    03954                         atemp2 = (lay - cury);
    03955                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    03956
    03957                         if (ftmp1 <= ftmp2) {
    03958                                 m1x = m->first1x;
    03959                                 m1y = m->first1y;
    03960                                 m2x = m->first2x;
    03961                                 m2y = m->first2y;
    03962                         } else {
    03963                                 m1x = m->last1x;
    03964                                 m1y = m->last1y;
    03965                                 m2x = m->last2x;
    03966                                 m2y = m->last2y;
    03967                         }
    03968
    03969                         atemp1 = (m2x - ml2x);
    03970                         atemp2 = (m2y - ml2y);
    03971                         ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
    03972                         atemp1 = (m2x - ml2bx);
    03973                         atemp2 = (m2y - ml2by);
    03974                         ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
    03975
    03976                         if (ftmp2 >= ftmp1) {
    03977                                 ftmp1 = ml2bx;
    03978                                 ftmp2 = ml2by;
    03979                                 ml2bx = ml2x;
    03980                                 ml2by = ml2y;
    03981                                 ml2x = ftmp1;
    03982                                 ml2y = ftmp2;
    03983                                 ftmp1 = ml1bx;
    03984                                 ftmp2 = ml1by;
    03985                                 ml1bx = ml1x;
    03986                                 ml1by = ml1y;
    03987                                 ml1x = ftmp1;
    03988                                 ml1y = ftmp2;
    03989                         }
    03990
    03991                         /*
    03992                         * Lock the surface
    03993                         */
    03994                         _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
    03995                         do {
    03996                                 pixel(m->renderer, b.x, b.y);
    03997                         } while (_bresenhamIterate(&b)==0);
    03998
    03999                         _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
    04000                         do {
    04001                                 pixel(m->renderer, b.x, b.y);
    04002                         } while (_bresenhamIterate(&b)==0);
    04003
    04004                         _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
    04005                         do {
    04006                                 pixel(m->renderer, b.x, b.y);
    04007                         } while (_bresenhamIterate(&b)==0);
    04008
    04009                         _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
    04010                         do {
    04011                                 pixel(m->renderer, b.x, b.y);
    04012                         } while (_bresenhamIterate(&b)==0);
    04013
    04014                         px[0] = m1x;
    04015                         px[1] = m2x;
    04016                         px[2] = ml1bx;
    04017                         px[3] = ml2bx;
    04018                         py[0] = m1y;
    04019                         py[1] = m2y;
    04020                         py[2] = ml1by;
    04021                         py[3] = ml2by;
    04022                         polygon(m->renderer, px, py, 4);
    04023                 }
    04024         }
    04025
    04026         m->last1x = ml1x;
    04027         m->last1y = ml1y;
    04028         m->last2x = ml2x;
    04029         m->last2y = ml2y;
    04030         m->first1x = ml1bx;
    04031         m->first1y = ml1by;
    04032         m->first2x = ml2bx;
    04033         m->first2y = ml2by;
    04034 }
    04035
    04036
    04037 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
    04038
    04053 void _murphyWideline(SDL2_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
    04054 {
    04055         float offset = (float)width / 2.f;
    04056
    04057         Sint16 temp;
    04058         Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
    04059
    04060         int d0, d1;             /* difference terms d0=perpendicular to line, d1=along line */
    04061
    04062         int q;                  /* pel counter,q=perpendicular to line */
    04063         int tmp;
    04064
    04065         int dd;                 /* distance along line */
    04066         int tk;                 /* thickness threshold */
    04067         double ang;             /* angle for initial point calculation */
    04068         double sang, cang;
    04069
    04070         /* Initialisation */
    04071         m->u = x2 - x1; /* delta x */
    04072         m->v = y2 - y1; /* delta y */
    04073
    04074         if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
    04075                 temp = x1;
    04076                 x1 = x2;
    04077                 x2 = temp;
    04078                 temp = y1;
    04079                 y1 = y2;
    04080                 y2 = temp;
    04081                 m->u *= -1;
    04082                 m->v *= -1;
    04083         }
    04084
    04085         if (m->v < 0) { /* swap to 1st quadrant and flag */
    04086                 m->v *= -1;
    04087                 m->quad4 = 1;
    04088         } else {
    04089                 m->quad4 = 0;
    04090         }
    04091
    04092         if (m->v > m->u) {      /* swap things if in 2 octant */
    04093                 tmp = m->u;
    04094                 m->u = m->v;
    04095                 m->v = tmp;
    04096                 m->oct2 = 1;
    04097         } else {
    04098                 m->oct2 = 0;
    04099         }
    04100
    04101         m->ku = m->u + m->u;    /* change in l for square shift */
    04102         m->kv = m->v + m->v;    /* change in d for square shift */
    04103         m->kd = m->kv - m->ku;  /* change in d for diagonal shift */
    04104         m->kt = m->u - m->kv;   /* diag/square decision threshold */
    04105
    04106         d0 = 0;
    04107         d1 = 0;
    04108         dd = 0;
    04109
    04110         ang = atan((double) m->v / (double) m->u);      /* calc new initial point - offset both sides of ideal */
    04111         sang = sin(ang);
    04112         cang = cos(ang);
    04113
    04114         if (m->oct2 == 0) {
    04115                 ptx = x1 + (Sint16)lrint(offset * sang);
    04116                 if (m->quad4 == 0) {
    04117                         pty = y1 - (Sint16)lrint(offset * cang);
    04118                 } else {
    04119                         pty = y1 + (Sint16)lrint(offset * cang);
    04120                 }
    04121         } else {
    04122                 ptx = x1 - (Sint16)lrint(offset * cang);
    04123                 if (m->quad4 == 0) {
    04124                         pty = y1 + (Sint16)lrint(offset * sang);
    04125                 } else {
    04126                         pty = y1 - (Sint16)lrint(offset * sang);
    04127                 }
    04128         }
    04129
    04130         /* used here for constant thickness line */
    04131         tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
    04132
    04133         if (miter == 0) {
    04134                 m->first1x = -32768;
    04135                 m->first1y = -32768;
    04136                 m->first2x = -32768;
    04137                 m->first2y = -32768;
    04138                 m->last1x = -32768;
    04139                 m->last1y = -32768;
    04140                 m->last2x = -32768;
    04141                 m->last2y = -32768;
    04142         }
    04143         ptxx = ptx;
    04144         ptxy = pty;
    04145
    04146         for (q = 0; dd <= tk; q++) {    /* outer loop, stepping perpendicular to line */
    04147
    04148                 _murphyParaline(m, ptx, pty, d1);       /* call to inner loop - right edge */
    04149                 if (q == 0) {
    04150                         ml1x = ptx;
    04151                         ml1y = pty;
    04152                         ml1bx = m->tempx;
    04153                         ml1by = m->tempy;
    04154                 } else {
    04155                         ml2x = ptx;
    04156                         ml2y = pty;
    04157                         ml2bx = m->tempx;
    04158                         ml2by = m->tempy;
    04159                 }
    04160                 if (d0 < m->kt) {       /* square move */
    04161                         if (m->oct2 == 0) {
    04162                                 if (m->quad4 == 0) {
    04163                                         pty++;
    04164                                 } else {
    04165                                         pty--;
    04166                                 }
    04167                         } else {
    04168                                 ptx++;
    04169                         }
    04170                 } else {        /* diagonal move */
    04171                         dd += m->kv;
    04172                         d0 -= m->ku;
    04173                         if (d1 < m->kt) {       /* normal diagonal */
    04174                                 if (m->oct2 == 0) {
    04175                                         ptx--;
    04176                                         if (m->quad4 == 0) {
    04177                                                 pty++;
    04178                                         } else {
    04179                                                 pty--;
    04180                                         }
    04181                                 } else {
    04182                                         ptx++;
    04183                                         if (m->quad4 == 0) {
    04184                                                 pty--;
    04185                                         } else {
    04186                                                 pty++;
    04187                                         }
    04188                                 }
    04189                                 d1 += m->kv;
    04190                         } else {        /* double square move, extra parallel line */
    04191                                 if (m->oct2 == 0) {
    04192                                         ptx--;
    04193                                 } else {
    04194                                         if (m->quad4 == 0) {
    04195                                                 pty--;
    04196                                         } else {
    04197                                                 pty++;
    04198                                         }
    04199                                 }
    04200                                 d1 += m->kd;
    04201                                 if (dd > tk) {
    04202                                         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    04203                                         return; /* breakout on the extra line */
    04204                                 }
    04205                                 _murphyParaline(m, ptx, pty, d1);
    04206                                 if (m->oct2 == 0) {
    04207                                         if (m->quad4 == 0) {
    04208                                                 pty++;
    04209                                         } else {
    04210
    04211                                                 pty--;
    04212                                         }
    04213                                 } else {
    04214                                         ptx++;
    04215                                 }
    04216                         }
    04217                 }
    04218                 dd += m->ku;
    04219                 d0 += m->kv;
    04220         }
    04221
    04222         _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
    04223 }
    04224
    04225
    04239 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
    04240 {
    04241         Uint8 *c = (Uint8 *)&color;
    04242         return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
    04243 }
    04244
    04261 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
    04262 {
    04263         int result;
    04264         int wh;
    04265         SDL2_gfxMurphyIterator m;
    04266
    04267         if (renderer == NULL) {
    04268                 return -1;
    04269         }
    04270         if (width < 1) {
    04271                 return -1;
    04272         }
    04273
    04274         /* Special case: thick "point" */
    04275         if ((x1 == x2) && (y1 == y2)) {
    04276                 wh = width / 2;
    04277                 return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
    04278         }
    04279
    04280         /*
    04281         * Set color
    04282         */
    04283         result = 0;
    04284         result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
    04285         result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
    04286
    04287         /*
    04288         * Draw
    04289         */
    04290         m.renderer = renderer;
    04291         _murphyWideline(&m, x1, y1, x2, y2, width, 0);
    04292         _murphyWideline(&m, x1, y1, x2, y2, width, 1);
    04293
    04294         return(0);
    04295 }