// Copyright (C) 1999 - 2003 Anders Lindström
// Copyright (C) 2009 - 2021 Marc Vester (XaserLE)
// Copyright (C) 2009 - 2021 Settlers Freaks <sf-team at siedler25.org>
//
// SPDX-License-Identifier: LGPL-2.1-or-later

/*
 *	SDL Graphics Extension
 *	Drawing primitives
 *
 *	Started 990815 (split from sge_draw 010611)
 */

/*
 *  Some of this code is taken from the "Introduction to SDL" and
 *  John Garrison's PowerPak
 */

#include "sge_primitives.h"
#include "sge_primitives_int.h"
#include "sge_surface.h"
#include <cmath>
#include <cstdlib>
#include <utility>

/* Globals used for sge_Lock (defined in sge_surface) */
extern Uint8 _sge_lock;

using std::swap;

/**********************************************************************************/
/**                             Line functions                                   **/
/**********************************************************************************/

//==================================================================================
// Internal draw horizontal line
//==================================================================================
void _HLine(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
{
    if(x1 > x2)
    {
        Sint16 tmp = x1;
        x1 = x2;
        x2 = tmp;
    }

    SDL_Rect l;
    l.x = x1;
    l.y = y;
    l.w = (Uint16)(x2 - x1) + 1;
    l.h = 1;

    SDL_FillRect(Surface, &l, Color);
}

//==================================================================================
// Draw horizontal line
//==================================================================================
void sge_HLine(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
{
    if(x1 > x2)
    {
        Sint16 tmp = x1;
        x1 = x2;
        x2 = tmp;
    }

    SDL_Rect l;
    l.x = x1;
    l.y = y;
    l.w = (Uint16)(x2 - x1) + 1;
    l.h = 1;

    SDL_FillRect(Surface, &l, Color);
}

//==================================================================================
// Draw horizontal line (RGB)
//==================================================================================
void sge_HLine(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B)
{
    sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Internal draw horizontal line (alpha)
//==================================================================================
void _HLineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
{
    Uint8 lock = _sge_lock;
    _sge_lock = 0;
    sge_FilledRectAlpha(Surface, x1, y, x2, y, Color, alpha);
    _sge_lock = lock;
}

//==================================================================================
// Draw horizontal line (alpha)
//==================================================================================
void sge_HLineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
{
    sge_FilledRectAlpha(Surface, x1, y, x2, y, Color, alpha);
}

//==================================================================================
// Draw horizontal line (alpha RGB)
//==================================================================================
void sge_HLineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_HLineAlpha(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Internal draw vertical line
//==================================================================================
static void _VLine(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
{
    if(y1 > y2)
    {
        Sint16 tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    SDL_Rect l;
    l.x = x;
    l.y = y1;
    l.w = 1;
    l.h = (Uint16)(y2 - y1) + 1;

    SDL_FillRect(Surface, &l, Color);
}

//==================================================================================
// Draw vertical line
//==================================================================================
void sge_VLine(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
{
    if(y1 > y2)
    {
        Sint16 tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    SDL_Rect l;
    l.x = x;
    l.y = y1;
    l.w = 1;
    l.h = (Uint16)(y2 - y1) + 1;

    SDL_FillRect(Surface, &l, Color);
}

//==================================================================================
// Draw vertical line (RGB)
//==================================================================================
void sge_VLine(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
    sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Internal draw vertical line (alpha - no update)
//==================================================================================
static void _VLineAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
{
    Uint8 lock = _sge_lock;
    _sge_lock = 0;
    sge_FilledRectAlpha(Surface, x, y1, x, y2, Color, alpha);
    _sge_lock = lock;
}

//==================================================================================
// Draw vertical line (alpha)
//==================================================================================
void sge_VLineAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
{
    sge_FilledRectAlpha(Surface, x, y1, x, y2, Color, alpha);
}

//==================================================================================
// Draw vertical line (alpha RGB)
//==================================================================================
void sge_VLineAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_VLineAlpha(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Performs Callback at each line point. (From PowerPak)
//==================================================================================
void sge_DoLine(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color,
                void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    Sint16 dx, dy, sdx, sdy, x, y, px, py;

    dx = x2 - x1;
    dy = y2 - y1;

    sdx = (dx < 0) ? -1 : 1;
    sdy = (dy < 0) ? -1 : 1;

    dx = sdx * dx + 1;
    dy = sdy * dy + 1;

    x = y = 0;

    px = x1;
    py = y1;

    if(dx >= dy)
    {
        for(x = 0; x < dx; x++)
        {
            Callback(Surface, px, py, Color);

            y += dy;
            if(y >= dx)
            {
                y -= dx;
                py += sdy;
            }
            px += sdx;
        }
    } else
    {
        for(y = 0; y < dy; y++)
        {
            Callback(Surface, px, py, Color);

            x += dx;
            if(x >= dy)
            {
                x -= dy;
                px += sdx;
            }
            py += sdy;
        }
    }
}

//==================================================================================
// Performs Callback at each line point. (RGB)
//==================================================================================
void sge_DoLine(SDL_Surface* Surface, Sint16 X1, Sint16 Y1, Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
                void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    sge_DoLine(Surface, X1, Y1, X2, Y2, SDL_MapRGB(Surface->format, R, G, B), Callback);
}

//==================================================================================
// Line clipping
// Standard Cohen-Sutherland algorithm (from gfxPrimitives)
//==================================================================================
#define CLIP_LEFT_EDGE 0x1
#define CLIP_RIGHT_EDGE 0x2
#define CLIP_BOTTOM_EDGE 0x4
#define CLIP_TOP_EDGE 0x8
#define CLIP_INSIDE(a) (!(a))
#define CLIP_REJECT(a, b) ((a) & (b))
#define CLIP_ACCEPT(a, b) (!((a) | (b)))

static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
{
    int code = 0;

    if(x < left)
        code |= CLIP_LEFT_EDGE;
    else if(x > right)
        code |= CLIP_RIGHT_EDGE;

    if(y < top)
        code |= CLIP_TOP_EDGE;
    else if(y > bottom)
        code |= CLIP_BOTTOM_EDGE;

    return code;
}

static int clipLine(SDL_Surface* dst, Sint16* x1, Sint16* y1, Sint16* x2, Sint16* y2)
{
    bool draw = false;

    float m;

    /* Get clipping boundary */
    Sint16 left, right, top, bottom;
    left = sge_clip_xmin(dst);
    right = sge_clip_xmax(dst);
    top = sge_clip_ymin(dst);
    bottom = sge_clip_ymax(dst);

    while(true)
    {
        int code1 = clipEncode(*x1, *y1, left, top, right, bottom);
        int code2 = clipEncode(*x2, *y2, left, top, right, bottom);

        if(CLIP_ACCEPT(code1, code2))
        {
            draw = true;
            break;
        } else if(CLIP_REJECT(code1, code2))
            break;
        else
        {
            if(CLIP_INSIDE(code1))
            {
                swap(*x1, *x2);
                swap(*y1, *y2);
                swap(code1, code2);
            }
            if(*x2 != *x1)
                m = (*y2 - *y1) / float(*x2 - *x1);
            else
                m = 1.0;

            if(code1 & CLIP_LEFT_EDGE)
            {
                *y1 += Sint16((left - *x1) * m);
                *x1 = left;
            } else if(code1 & CLIP_RIGHT_EDGE)
            {
                *y1 += Sint16((right - *x1) * m);
                *x1 = right;
            } else if(code1 & CLIP_BOTTOM_EDGE)
            {
                if(*x2 != *x1)
                {
                    *x1 += Sint16((bottom - *y1) / m);
                }
                *y1 = bottom;
            } else if(code1 & CLIP_TOP_EDGE)
            {
                if(*x2 != *x1)
                {
                    *x1 += Sint16((top - *y1) / m);
                }
                *y1 = top;
            }
        }
    }

    return draw;
}

//==================================================================================
// Draws a line
//==================================================================================
void _Line(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
    if(!clipLine(surface, &x1, &y1, &x2, &y2))
        return;

    Sint16 dx, dy, sdx, sdy;

    dx = x2 - x1;
    dy = y2 - y1;

    sdx = (dx < 0) ? -1 : 1;
    sdy = (dy < 0) ? -1 : 1;

    dx = sdx * dx + 1;
    dy = sdy * dy + 1;

    Sint16 y = 0;

    Sint16 pixx = surface->format->BytesPerPixel;
    auto pixy = (Sint16)surface->pitch;
    Uint8* pixel = (Uint8*)surface->pixels + y1 * pixy + x1 * pixx;

    pixx *= sdx;
    pixy *= sdy;

    if(dx < dy)
    {
        Sint32 tmp = dx;
        dx = dy;
        dy = Sint16(tmp);
        tmp = pixx;
        pixx = pixy;
        pixy = tmp;
    }

    switch(surface->format->BytesPerPixel)
    {
        case 1:
        {
            for(int x = 0; x < dx; x++)
            {
                *pixel = color;

                y += dy;
                if(y >= dx)
                {
                    y -= dx;
                    pixel += pixy;
                }
                pixel += pixx;
            }
        }
        break;

        case 2:
        {
            for(int x = 0; x < dx; x++)
            {
                *(Uint16*)pixel = color;

                y += dy;
                if(y >= dx)
                {
                    y -= dx;
                    pixel += pixy;
                }
                pixel += pixx;
            }
        }
        break;

        case 3:
        {
            Uint8 rshift8 = surface->format->Rshift / 8;
            Uint8 gshift8 = surface->format->Gshift / 8;
            Uint8 bshift8 = surface->format->Bshift / 8;
            Uint8 ashift8 = surface->format->Ashift / 8;

            Uint8 R = (color >> surface->format->Rshift) & 0xff;
            Uint8 G = (color >> surface->format->Gshift) & 0xff;
            Uint8 B = (color >> surface->format->Bshift) & 0xff;
            Uint8 A = (color >> surface->format->Ashift) & 0xff;

            for(int x = 0; x < dx; x++)
            {
                *(pixel + rshift8) = R;
                *(pixel + gshift8) = G;
                *(pixel + bshift8) = B;
                *(pixel + ashift8) = A;

                y += dy;
                if(y >= dx)
                {
                    y -= dx;
                    pixel += pixy;
                }
                pixel += pixx;
            }
        }
        break;

        case 4:
        {
            for(int x = 0; x < dx; x++)
            {
                *(Uint32*)pixel = color;

                y += dy;
                if(y >= dx)
                {
                    y -= dx;
                    pixel += pixy;
                }
                pixel += pixx;
            }
        }
        break;
    }
}

void sge_Line(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        if(SDL_LockSurface(Surface) < 0)
            return;
    }

    /* Draw the line */
    _Line(Surface, x1, y1, x2, y2, Color);

    /* unlock the display */
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a line (RGB)
//==================================================================================
void sge_Line(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
    sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// A quick hack to get alpha working with callbacks
//==================================================================================
Uint8 _sge_alpha_hack = 0;
void callback_alpha_hack(SDL_Surface* surf, Sint16 x, Sint16 y, Uint32 color)
{
    _PutPixelAlpha(surf, x, y, color, _sge_alpha_hack);
}

//==================================================================================
// Draws a line (alpha)
//==================================================================================
void _LineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, Uint8 alpha)
{
    _sge_alpha_hack = alpha;

    /* Draw the line */
    sge_DoLine(Surface, x1, y1, x2, y2, Color, callback_alpha_hack);
}

void sge_LineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    _LineAlpha(Surface, x1, y1, x2, y2, Color, alpha);

    /* unlock the display */
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a line (alpha - RGB)
//==================================================================================
void sge_LineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B,
                   Uint8 alpha)
{
    sge_LineAlpha(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Anti-aliased line
// From SDL_gfxPrimitives written by A. Schiffler (aschiffler@home.com)
//==================================================================================
#define AAbits 8
#define AAlevels 256 /* 2^AAbits */
void _AALineAlpha(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
    Uint32 erracc = 0, erradj;
    Uint32 erracctmp, wgt;
    Sint16 y0p1, x0pxdir;
    Uint8 a;

    /* Keep on working with 32bit numbers */
    Sint32 xx0 = x1;
    Sint32 yy0 = y1;
    Sint32 xx1 = x2;
    Sint32 yy1 = y2;

    /* Reorder points if required */
    if(yy0 > yy1)
    {
        swap(yy0, yy1);
        swap(xx0, xx1);
    }

    /* Calculate distance */
    Sint16 dx = xx1 - xx0;
    Uint16 dy = yy1 - yy0;

    /* Adjust for negative dx and set xdir */
    Sint16 xdir = 1;
    if(dx < 0)
    {
        xdir = -1;
        dx = (-dx);
    }

    /* Check for special cases */
    if(dx == 0 || dy == 0 || dx == dy)
    {
        if(alpha == SDL_ALPHA_OPAQUE)
            _Line(dst, x1, y1, x2, y2, color);
        else
            _LineAlpha(dst, x1, y1, x2, y2, color, alpha);
        return;
    }

    float alpha_pp = float(alpha) / 255; /* Used to calculate alpha level if alpha != 255 */

    Uint32 intshift = 32 - AAbits; /* # of bits by which to shift erracc to get intensity level */

    /* Draw the initial pixel in the foreground color */
    if(alpha == SDL_ALPHA_OPAQUE)
        _PutPixel(dst, x1, y1, color);
    else
        _PutPixelAlpha(dst, x1, y1, color, alpha);

    /* x-major or y-major? */
    if(dy > dx)
    {
        /* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
        X advances every time Y advances 1 pixel, truncating the result so that
        we won't overrun the endpoint along the X axis */
        erradj = ((Uint32)(dx << 16) / dy) << 16;

        /* draw all pixels other than the first and last */
        x0pxdir = xx0 + xdir;
        while(--dy)
        {
            erracctmp = erracc;
            erracc += erradj;
            if(erracc <= erracctmp)
            {
                /* rollover in error accumulator, x coord advances */
                xx0 = x0pxdir;
                x0pxdir += xdir;
            }
            yy0++; /* y-major so always advance Y */

            /* the AAbits most significant bits of erracc give us the intensity
            weighting for this pixel, and the complement of the weighting for
            the paired pixel. */
            wgt = (erracc >> intshift) & 255;

            a = Uint8(255 - wgt);
            if(alpha != SDL_ALPHA_OPAQUE)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, yy0, color, a);

            a = Uint8(wgt);
            if(alpha != SDL_ALPHA_OPAQUE)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, x0pxdir, yy0, color, a);
        }
    } else
    {
        /* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
        that Y advances each time X advances 1 pixel, truncating the result so
        that we won't overrun the endpoint along the X axis. */
        erradj = (((Uint32)dy << 16) / (Uint32)dx) << 16;

        /* draw all pixels other than the first and last */
        y0p1 = yy0 + 1;
        while(--dx)
        {
            erracctmp = erracc;
            erracc += erradj;
            if(erracc <= erracctmp)
            {
                /* Accumulator turned over, advance y */
                yy0 = y0p1;
                y0p1++;
            }
            xx0 += xdir; /* x-major so always advance X */

            /* the AAbits most significant bits of erracc give us the intensity
            weighting for this pixel, and the complement of the weighting for
            the paired pixel. */
            wgt = (erracc >> intshift) & 255;

            a = Uint8(255 - wgt);
            if(alpha != SDL_ALPHA_OPAQUE)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, yy0, color, a);

            a = Uint8(wgt);
            if(alpha != SDL_ALPHA_OPAQUE)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, y0p1, color, a);
        }
    }

    /* Draw final pixel, always exactly intersected by the line and doesn't
    need to be weighted. */
    if(alpha == SDL_ALPHA_OPAQUE)
        _PutPixel(dst, x2, y2, color);
    else
        _PutPixelAlpha(dst, x2, y2, color, alpha);
}

void sge_AALineAlpha(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
    /* Lock surface */
    if(_sge_lock && SDL_MUSTLOCK(dst))
        if(SDL_LockSurface(dst) < 0)
            return;

    _AALineAlpha(dst, x1, y1, x2, y2, color, alpha);

    /* unlock the display */
    if(_sge_lock && SDL_MUSTLOCK(dst))
    {
        SDL_UnlockSurface(dst);
    }
}

void sge_AALineAlpha(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b,
                     Uint8 alpha)
{
    sge_AALineAlpha(dst, x1, y1, x2, y2, SDL_MapRGB(dst->format, r, g, b), alpha);
}

void sge_AALine(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
    sge_AALineAlpha(dst, x1, y1, x2, y2, color, SDL_ALPHA_OPAQUE);
}

void sge_AALine(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b)
{
    sge_AALineAlpha(dst, x1, y1, x2, y2, SDL_MapRGB(dst->format, r, g, b), SDL_ALPHA_OPAQUE);
}

//==================================================================================
// Draws a multicolored line
//==================================================================================
void sge_DomcLine(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                  Uint8 r2, Uint8 g2, Uint8 b2, void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    Sint16 dx, dy, sdx, sdy, x, y, px, py;

    dx = x2 - x1;
    dy = y2 - y1;

    sdx = (dx < 0) ? -1 : 1;
    sdy = (dy < 0) ? -1 : 1;

    dx = sdx * dx + 1;
    dy = sdy * dy + 1;

    x = y = 0;

    px = x1;
    py = y1;

    /* We use fixedpoint math for the color fading */
    Sint32 R = r1 << 16;
    Sint32 G = g1 << 16;
    Sint32 B = b1 << 16;
    Sint32 rstep;
    Sint32 gstep;
    Sint32 bstep;

    if(dx >= dy)
    {
        rstep = Sint32((r2 - r1) << 16) / Sint32(dx);
        gstep = Sint32((g2 - g1) << 16) / Sint32(dx);
        bstep = Sint32((b2 - b1) << 16) / Sint32(dx);

        for(x = 0; x < dx; x++)
        {
            Callback(surface, px, py, SDL_MapRGB(surface->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)));

            y += dy;
            if(y >= dx)
            {
                y -= dx;
                py += sdy;
            }
            px += sdx;

            R += rstep;
            G += gstep;
            B += bstep;
        }
    } else
    {
        rstep = Sint32((r2 - r1) << 16) / Sint32(dy);
        gstep = Sint32((g2 - g1) << 16) / Sint32(dy);
        bstep = Sint32((b2 - b1) << 16) / Sint32(dy);

        for(y = 0; y < dy; y++)
        {
            Callback(surface, px, py, SDL_MapRGB(surface->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)));

            x += dx;
            if(x >= dy)
            {
                x -= dy;
                px += sdx;
            }
            py += sdy;

            R += rstep;
            G += gstep;
            B += bstep;
        }
    }
}

void sge_mcLine(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                Uint8 r2, Uint8 g2, Uint8 b2)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        if(SDL_LockSurface(Surface) < 0)
            return;
    }

    /* Draw the line */
    sge_DomcLine(Surface, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, _PutPixel);

    /* unlock the display */
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

void sge_mcLineAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                     Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    _sge_alpha_hack = alpha;

    /* Draw the line */
    sge_DomcLine(Surface, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, callback_alpha_hack);

    /* unlock the display */
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a anti-aliased multicolored line
//==================================================================================
void _AAmcLineAlpha(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                    Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
{
    Uint32 erracc = 0, erradj;
    Uint32 erracctmp, wgt;
    Sint16 y0p1, x0pxdir;

    /* Keep on working with 32bit numbers */
    Sint32 xx0 = x1;
    Sint32 yy0 = y1;
    Sint32 xx1 = x2;
    Sint32 yy1 = y2;

    /* Reorder points if required */
    if(yy0 > yy1)
    {
        swap(yy0, yy1);
        swap(xx0, xx1);

        swap(r1, r2);
        swap(g1, g2);
        swap(b1, b2);
    }

    /* Calculate distance */
    Sint16 dx = xx1 - xx0;
    Uint16 dy = yy1 - yy0;

    /* Adjust for negative dx and set xdir */
    Sint16 xdir = 1;
    if(dx < 0)
    {
        xdir = -1;
        dx = (-dx);
    }

    /* Check for special cases */
    if(dx == 0 || dy == 0 || dx == dy)
    {
        sge_mcLineAlpha(dst, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, alpha);
        return;
    }

    /* We use fixedpoint math for the color fading */
    Sint32 R = r1 << 16;
    Sint32 G = g1 << 16;
    Sint32 B = b1 << 16;
    Sint32 rstep;
    Sint32 gstep;
    Sint32 bstep;

    float alpha_pp = float(alpha) / 255; /* Used to calculate alpha level if alpha != 255 */
    Uint32 intshift = 32 - AAbits;       /* # of bits by which to shift erracc to get intensity level */

    if(alpha == 255)
        _PutPixel(dst, x1, y1,
                  SDL_MapRGB(dst->format, r1, g1, b1)); /* Draw the initial pixel in the foreground color */
    else
        _PutPixelAlpha(dst, x1, y1, SDL_MapRGB(dst->format, r1, g1, b1), alpha);

    /* x-major or y-major? */
    if(dy > dx)
    {
        /* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
        X advances every time Y advances 1 pixel, truncating the result so that
        we won't overrun the endpoint along the X axis */
        erradj = (((Uint32)dx << 16) / (Uint32)dy) << 16;

        rstep = Sint32((r2 - r1) << 16) / Sint32(dy);
        gstep = Sint32((g2 - g1) << 16) / Sint32(dy);
        bstep = Sint32((b2 - b1) << 16) / Sint32(dy);

        /* draw all pixels other than the first and last */
        x0pxdir = xx0 + xdir;
        while(--dy)
        {
            R += rstep;
            G += gstep;
            B += bstep;

            erracctmp = erracc;
            erracc += erradj;
            if(erracc <= erracctmp)
            {
                /* rollover in error accumulator, x coord advances */
                xx0 = x0pxdir;
                x0pxdir += xdir;
            }
            yy0++; /* y-major so always advance Y */

            /* the AAbits most significant bits of erracc give us the intensity
            weighting for this pixel, and the complement of the weighting for
            the paired pixel. */
            wgt = (erracc >> intshift) & 255;

            auto a = Uint8(255 - wgt);
            if(alpha != 255)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, yy0, SDL_MapRGB(dst->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)), a);

            a = Uint8(wgt);
            if(alpha != 255)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, x0pxdir, yy0, SDL_MapRGB(dst->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)),
                           a);
        }
    } else
    {
        /* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
        that Y advances each time X advances 1 pixel, truncating the result so
        that we won't overrun the endpoint along the X axis. */
        erradj = (((Uint32)dy << 16) / (Uint32)dx) << 16;

        rstep = Sint32((r2 - r1) << 16) / Sint32(dx);
        gstep = Sint32((g2 - g1) << 16) / Sint32(dx);
        bstep = Sint32((b2 - b1) << 16) / Sint32(dx);

        /* draw all pixels other than the first and last */
        y0p1 = yy0 + 1;
        while(--dx)
        {
            R += rstep;
            G += gstep;
            B += bstep;

            erracctmp = erracc;
            erracc += erradj;
            if(erracc <= erracctmp)
            {
                /* Accumulator turned over, advance y */
                yy0 = y0p1;
                y0p1++;
            }
            xx0 += xdir; /* x-major so always advance X */

            /* the AAbits most significant bits of erracc give us the intensity
            weighting for this pixel, and the complement of the weighting for
            the paired pixel. */
            wgt = (erracc >> intshift) & 255;

            auto a = Uint8(255 - wgt);
            if(alpha != 255)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, yy0, SDL_MapRGB(dst->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)), a);

            a = Uint8(wgt);
            if(alpha != 255)
                a = Uint8(a * alpha_pp);

            _PutPixelAlpha(dst, xx0, y0p1, SDL_MapRGB(dst->format, Uint8(R >> 16), Uint8(G >> 16), Uint8(B >> 16)), a);
        }
    }

    /* Draw final pixel, always exactly intersected by the line and doesn't
    need to be weighted. */
    if(alpha == 255)
        _PutPixel(dst, x2, y2, SDL_MapRGB(dst->format, r2, g2, b2));
    else
        _PutPixelAlpha(dst, x2, y2, SDL_MapRGB(dst->format, r2, g2, b2), alpha);
}

void sge_AAmcLineAlpha(SDL_Surface* dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                       Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(dst))
        if(SDL_LockSurface(dst) < 0)
            return;

    _AAmcLineAlpha(dst, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, alpha);

    if(_sge_lock && SDL_MUSTLOCK(dst))
        SDL_UnlockSurface(dst);
}

void sge_AAmcLine(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1,
                  Uint8 r2, Uint8 g2, Uint8 b2)
{
    sge_AAmcLineAlpha(Surface, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, SDL_ALPHA_OPAQUE);
}

/**********************************************************************************/
/**                           Figure functions                                   **/
/**********************************************************************************/

//==================================================================================
// Draws a rectangle
//==================================================================================
void sge_Rect(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
    _HLine(Surface, x1, x2, y1, color);
    _HLine(Surface, x1, x2, y2, color);
    _VLine(Surface, x1, y1, y2, color);
    _VLine(Surface, x2, y1, y2, color);
}

//==================================================================================
// Draws a rectangle (RGB)
//==================================================================================
void sge_Rect(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
    sge_Rect(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws a rectangle (alpha)
//==================================================================================
void sge_RectAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    _HLineAlpha(Surface, x1, x2, y1, color, alpha);
    _HLineAlpha(Surface, x1, x2, y2, color, alpha);
    _VLineAlpha(Surface, x1, y1, y2, color, alpha);
    _VLineAlpha(Surface, x2, y1, y2, color, alpha);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a rectangle (RGB)
//==================================================================================
void sge_RectAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B,
                   Uint8 alpha)
{
    sge_RectAlpha(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws a filled rectangle
//==================================================================================
void sge_FilledRect(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
{
    Sint16 tmp;
    if(x1 > x2)
    {
        tmp = x1;
        x1 = x2;
        x2 = tmp;
    }
    if(y1 > y2)
    {
        tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    SDL_Rect area;
    area.x = x1;
    area.y = y1;
    area.w = static_cast<Uint16>(x2 - x1) + 1;
    area.h = static_cast<Uint16>(y2 - y1) + 1;

    SDL_FillRect(Surface, &area, color);
}

//==================================================================================
// Draws a filled rectangle (RGB)
//==================================================================================
void sge_FilledRect(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
{
    sge_FilledRect(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws a filled rectangle (alpha)
//==================================================================================
void sge_FilledRectAlpha(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
{
    /*if( alpha == 255 ){
        sge_FilledRect(surface,x1,y1,x2,y2,color);
        return;
    }*/

    /* Fix coords */
    Sint16 tmp;
    if(x1 > x2)
    {
        tmp = x1;
        x1 = x2;
        x2 = tmp;
    }
    if(y1 > y2)
    {
        tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    /* Clipping */
    if(x2 < sge_clip_xmin(surface) || x1 > sge_clip_xmax(surface) || y2 < sge_clip_ymin(surface)
       || y1 > sge_clip_ymax(surface))
        return;
    if(x1 < sge_clip_xmin(surface))
        x1 = sge_clip_xmin(surface);
    if(x2 > sge_clip_xmax(surface))
        x2 = sge_clip_xmax(surface);
    if(y1 < sge_clip_ymin(surface))
        y1 = sge_clip_ymin(surface);
    if(y2 > sge_clip_ymax(surface))
        y2 = sge_clip_ymax(surface);

    Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask,
           Amask = surface->format->Amask;
    Uint32 R, G, B, A = 0;
    Sint16 x, y;

    if(_sge_lock && SDL_MUSTLOCK(surface))
        if(SDL_LockSurface(surface) < 0)
            return;

    switch(surface->format->BytesPerPixel)
    {
        case 1:
        { /* Assuming 8-bpp */
            Uint8 *row, *pixel;
            Uint8 dR, dG, dB;

            Uint8 sR = surface->format->palette->colors[color].r;
            Uint8 sG = surface->format->palette->colors[color].g;
            Uint8 sB = surface->format->palette->colors[color].b;

            for(y = y1; y <= y2; y++)
            {
                row = (Uint8*)surface->pixels + y * surface->pitch;
                for(x = x1; x <= x2; x++)
                {
                    pixel = row + x;

                    dR = surface->format->palette->colors[*pixel].r;
                    dG = surface->format->palette->colors[*pixel].g;
                    dB = surface->format->palette->colors[*pixel].b;

                    dR = dR + (((sR - dR) * alpha) >> 8);
                    dG = dG + (((sG - dG) * alpha) >> 8);
                    dB = dB + (((sB - dB) * alpha) >> 8);

                    *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
                }
            }
        }
        break;

        case 2:
        { /* Probably 15-bpp or 16-bpp */
            Uint16 *row, *pixel;
            Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);

            for(y = y1; y <= y2; y++)
            {
                row = (Uint16*)surface->pixels + y * surface->pitch / 2;
                for(x = x1; x <= x2; x++)
                {
                    pixel = row + x;

                    R = ((*pixel & Rmask) + (((dR - (*pixel & Rmask)) * alpha) >> 8)) & Rmask;
                    G = ((*pixel & Gmask) + (((dG - (*pixel & Gmask)) * alpha) >> 8)) & Gmask;
                    B = ((*pixel & Bmask) + (((dB - (*pixel & Bmask)) * alpha) >> 8)) & Bmask;
                    if(Amask)
                        A = ((*pixel & Amask) + (((dA - (*pixel & Amask)) * alpha) >> 8)) & Amask;

                    *pixel = R | G | B | A;
                }
            }
        }
        break;

        case 3:
        { /* Slow 24-bpp mode, usually not used */
            Uint8 *row, *pix;
            Uint8 dR, dG, dB, dA;
            Uint8 rshift8 = surface->format->Rshift / 8;
            Uint8 gshift8 = surface->format->Gshift / 8;
            Uint8 bshift8 = surface->format->Bshift / 8;
            Uint8 ashift8 = surface->format->Ashift / 8;

            Uint8 sR = (color >> surface->format->Rshift) & 0xff;
            Uint8 sG = (color >> surface->format->Gshift) & 0xff;
            Uint8 sB = (color >> surface->format->Bshift) & 0xff;
            Uint8 sA = (color >> surface->format->Ashift) & 0xff;

            for(y = y1; y <= y2; y++)
            {
                row = (Uint8*)surface->pixels + y * surface->pitch;
                for(x = x1; x <= x2; x++)
                {
                    pix = row + x * 3;

                    dR = *((pix) + rshift8);
                    dG = *((pix) + gshift8);
                    dB = *((pix) + bshift8);
                    dA = *((pix) + ashift8);

                    dR = dR + (((sR - dR) * alpha) >> 8);
                    dG = dG + (((sG - dG) * alpha) >> 8);
                    dB = dB + (((sB - dB) * alpha) >> 8);
                    dA = dA + (((sA - dA) * alpha) >> 8);

                    *((pix) + rshift8) = dR;
                    *((pix) + gshift8) = dG;
                    *((pix) + bshift8) = dB;
                    *((pix) + ashift8) = dA;
                }
            }
        }
        break;

        case 4:
        { /* Probably 32-bpp */
            Uint32 *row, *pixel;
            Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);

            for(y = y1; y <= y2; y++)
            {
                row = (Uint32*)surface->pixels + y * surface->pitch / 4;
                for(x = x1; x <= x2; x++)
                {
                    pixel = row + x;

                    R = ((*pixel & Rmask) + (((dR - (*pixel & Rmask)) * alpha) >> 8)) & Rmask;
                    G = ((*pixel & Gmask) + (((dG - (*pixel & Gmask)) * alpha) >> 8)) & Gmask;
                    B = ((*pixel & Bmask) + (((dB - (*pixel & Bmask)) * alpha) >> 8)) & Bmask;
                    if(Amask)
                        A = ((*pixel & Amask) + (((dA - (*pixel & Amask)) * alpha) >> 8)) & Amask;

                    *pixel = R | G | B | A;
                }
            }
        }
        break;
    }

    if(_sge_lock && SDL_MUSTLOCK(surface))
    {
        SDL_UnlockSurface(surface);
    }
}

void sge_FilledRectAlpha(SDL_Surface* Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B,
                         Uint8 alpha)
{
    sge_FilledRectAlpha(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Performs Callback at each ellipse point.
// (from Allegro)
//==================================================================================
void sge_DoEllipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint32 color,
                   void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    int ix, iy;
    int h, i, j, k;
    int oh, oi, oj, ok;

    if(rx < 1)
        rx = 1;

    if(ry < 1)
        ry = 1;

    h = i = j = k = 0xFFFF;

    if(rx > ry)
    {
        ix = 0;
        iy = rx * 64;

        do
        {
            oh = h;
            oi = i;
            oj = j;
            ok = k;

            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * ry) / rx;
            k = (i * ry) / rx;

            if(((h != oh) || (k != ok)) && (h < oi))
            {
                Callback(Surface, x + h, y + k, color);
                if(h)
                    Callback(Surface, x - h, y + k, color);
                if(k)
                {
                    Callback(Surface, x + h, y - k, color);
                    if(h)
                        Callback(Surface, x - h, y - k, color);
                }
            }

            if(((i != oi) || (j != oj)) && (h < i))
            {
                Callback(Surface, x + i, y + j, color);
                if(i)
                    Callback(Surface, x - i, y + j, color);
                if(j)
                {
                    Callback(Surface, x + i, y - j, color);
                    if(i)
                        Callback(Surface, x - i, y - j, color);
                }
            }

            ix = ix + iy / rx;
            iy = iy - ix / rx;

        } while(i > h);
    } else
    {
        ix = 0;
        iy = ry * 64;

        do
        {
            oh = h;
            oi = i;
            oj = j;
            ok = k;

            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * rx) / ry;
            k = (i * rx) / ry;

            if(((j != oj) || (i != oi)) && (h < i))
            {
                Callback(Surface, x + j, y + i, color);
                if(j)
                    Callback(Surface, x - j, y + i, color);
                if(i)
                {
                    Callback(Surface, x + j, y - i, color);
                    if(j)
                        Callback(Surface, x - j, y - i, color);
                }
            }

            if(((k != ok) || (h != oh)) && (h < oi))
            {
                Callback(Surface, x + k, y + h, color);
                if(k)
                    Callback(Surface, x - k, y + h, color);
                if(h)
                {
                    Callback(Surface, x + k, y - h, color);
                    if(k)
                        Callback(Surface, x - k, y - h, color);
                }
            }

            ix = ix + iy / ry;
            iy = iy - ix / ry;

        } while(i > h);
    }
}

//==================================================================================
// Performs Callback at each ellipse point. (RGB)
//==================================================================================
void sge_DoEllipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B,
                   void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    sge_DoEllipse(Surface, x, y, rx, ry, SDL_MapRGB(Surface->format, R, G, B), Callback);
}

//==================================================================================
// Draws an ellipse
//==================================================================================
void sge_Ellipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint32 color)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        if(SDL_LockSurface(Surface) < 0)
            return;
    }

    sge_DoEllipse(Surface, x, y, rx, ry, color, _PutPixel);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws an ellipse (RGB)
//==================================================================================
void sge_Ellipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
    sge_Ellipse(Surface, x, y, rx, ry, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws an ellipse (alpha)
//==================================================================================
void sge_EllipseAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint32 color, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    _sge_alpha_hack = alpha;
    sge_DoEllipse(Surface, x, y, rx, ry, color, callback_alpha_hack);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws an ellipse (alpha - RGB)
//==================================================================================
void sge_EllipseAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B,
                      Uint8 alpha)
{
    sge_EllipseAlpha(Surface, x, y, rx, ry, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws a filled ellipse
//==================================================================================
void sge_FilledEllipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint32 color)
{
    int ix, iy;
    int h, i, j, k;
    int oh, oi, oj, ok;

    if(rx < 1)
        rx = 1;

    if(ry < 1)
        ry = 1;

    oh = oi = oj = ok = 0xFFFF;

    if(rx > ry)
    {
        ix = 0;
        iy = rx * 64;

        do
        {
            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * ry) / rx;
            k = (i * ry) / rx;

            if((k != ok) && (k != oj))
            {
                if(k)
                {
                    _HLine(Surface, x - h, x + h, y - k, color);
                    _HLine(Surface, x - h, x + h, y + k, color);
                } else
                    _HLine(Surface, x - h, x + h, y, color);
                ok = k;
            }

            if((j != oj) && (j != ok) && (k != j))
            {
                if(j)
                {
                    _HLine(Surface, x - i, x + i, y - j, color);
                    _HLine(Surface, x - i, x + i, y + j, color);
                } else
                    _HLine(Surface, x - i, x + i, y, color);
                oj = j;
            }

            ix = ix + iy / rx;
            iy = iy - ix / rx;

        } while(i > h);
    } else
    {
        ix = 0;
        iy = ry * 64;

        do
        {
            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * rx) / ry;
            k = (i * rx) / ry;

            if((i != oi) && (i != oh))
            {
                if(i)
                {
                    _HLine(Surface, x - j, x + j, y - i, color);
                    _HLine(Surface, x - j, x + j, y + i, color);
                } else
                    _HLine(Surface, x - j, x + j, y, color);
                oi = i;
            }

            if((h != oh) && (h != oi) && (i != h))
            {
                if(h)
                {
                    _HLine(Surface, x - k, x + k, y - h, color);
                    _HLine(Surface, x - k, x + k, y + h, color);
                } else
                    _HLine(Surface, x - k, x + k, y, color);
                oh = h;
            }

            ix = ix + iy / ry;
            iy = iy - ix / ry;

        } while(i > h);
    }
}

//==================================================================================
// Draws a filled ellipse (RGB)
//==================================================================================
void sge_FilledEllipse(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
    sge_FilledEllipse(Surface, x, y, rx, ry, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws a filled ellipse (alpha)
//==================================================================================
void sge_FilledEllipseAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint32 color, Uint8 alpha)
{
    int ix, iy;
    int h, i, j, k;
    int oh, oi, oj, ok;

    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    if(rx < 1)
        rx = 1;

    if(ry < 1)
        ry = 1;

    oh = oi = oj = ok = 0xFFFF;

    if(rx > ry)
    {
        ix = 0;
        iy = rx * 64;

        do
        {
            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * ry) / rx;
            k = (i * ry) / rx;

            if((k != ok) && (k != oj))
            {
                if(k)
                {
                    _HLineAlpha(Surface, x - h, x + h, y - k, color, alpha);
                    _HLineAlpha(Surface, x - h, x + h, y + k, color, alpha);
                } else
                    _HLineAlpha(Surface, x - h, x + h, y, color, alpha);
                ok = k;
            }

            if((j != oj) && (j != ok) && (k != j))
            {
                if(j)
                {
                    _HLineAlpha(Surface, x - i, x + i, y - j, color, alpha);
                    _HLineAlpha(Surface, x - i, x + i, y + j, color, alpha);
                } else
                    _HLineAlpha(Surface, x - i, x + i, y, color, alpha);
                oj = j;
            }

            ix = ix + iy / rx;
            iy = iy - ix / rx;

        } while(i > h);
    } else
    {
        ix = 0;
        iy = ry * 64;

        do
        {
            h = (ix + 32) >> 6;
            i = (iy + 32) >> 6;
            j = (h * rx) / ry;
            k = (i * rx) / ry;

            if((i != oi) && (i != oh))
            {
                if(i)
                {
                    _HLineAlpha(Surface, x - j, x + j, y - i, color, alpha);
                    _HLineAlpha(Surface, x - j, x + j, y + i, color, alpha);
                } else
                    _HLineAlpha(Surface, x - j, x + j, y, color, alpha);
                oi = i;
            }

            if((h != oh) && (h != oi) && (i != h))
            {
                if(h)
                {
                    _HLineAlpha(Surface, x - k, x + k, y - h, color, alpha);
                    _HLineAlpha(Surface, x - k, x + k, y + h, color, alpha);
                } else
                    _HLineAlpha(Surface, x - k, x + k, y, color, alpha);
                oh = h;
            }

            ix = ix + iy / ry;
            iy = iy - ix / ry;

        } while(i > h);
    }

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a filled ellipse (alpha - RGB)
//==================================================================================
void sge_FilledEllipseAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B,
                            Uint8 alpha)
{
    sge_FilledEllipseAlpha(Surface, x, y, rx, ry, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws a filled anti-aliased ellipse
// This is just a quick hack...
//==================================================================================
void sge_AAFilledEllipse(SDL_Surface* surface, Sint16 xc, Sint16 yc, Uint16 rx, Uint16 ry, Uint32 color)
{
    /* Sanity check */
    if(rx < 1)
        rx = 1;
    if(ry < 1)
        ry = 1;

    int a2 = rx * rx;
    int b2 = ry * ry;

    int ds = 2 * a2;
    int dt = 2 * b2;

    auto dxt = int(a2 / sqrt(a2 + b2));

    int t = 0;
    int s = -2 * a2 * ry;
    int d = 0;

    Sint16 x = xc;
    Sint16 y = yc - ry;

    Sint16 xs, ys, dyt;
    float cp, is, ip, imax = 1.0;

    /* Lock surface */
    if(_sge_lock && SDL_MUSTLOCK(surface))
        if(SDL_LockSurface(surface) < 0)
            return;

    /* "End points" */
    _PutPixel(surface, x, y, color);
    _PutPixel(surface, 2 * xc - x, y, color);

    _PutPixel(surface, x, 2 * yc - y, color);
    _PutPixel(surface, 2 * xc - x, 2 * yc - y, color);

    /* unlock surface */
    if(_sge_lock && SDL_MUSTLOCK(surface))
        SDL_UnlockSurface(surface);

    _VLine(surface, x, y + 1, 2 * yc - y - 1, color);

    int i;

    for(i = 1; i <= dxt; i++)
    {
        x--;
        d += t - b2;

        if(d >= 0)
            ys = y - 1;
        else if((d - s - a2) > 0)
        {
            if((2 * d - s - a2) >= 0)
                ys = y + 1;
            else
            {
                ys = y;
                y++;
                d -= s + a2;
                s += ds;
            }
        } else
        {
            y++;
            ys = y + 1;
            d -= s + a2;
            s += ds;
        }

        t -= dt;

        /* Calculate alpha */
        cp = (float)abs(d) / abs(s);
        is = cp * imax;
        ip = imax - is;

        /* Lock surface */
        if(_sge_lock && SDL_MUSTLOCK(surface))
            if(SDL_LockSurface(surface) < 0)
                return;

        /* Upper half */
        _PutPixelAlpha(surface, x, y, color, Uint8(ip * 255));
        _PutPixelAlpha(surface, 2 * xc - x, y, color, Uint8(ip * 255));

        _PutPixelAlpha(surface, x, ys, color, Uint8(is * 255));
        _PutPixelAlpha(surface, 2 * xc - x, ys, color, Uint8(is * 255));

        /* Lower half */
        _PutPixelAlpha(surface, x, 2 * yc - y, color, Uint8(ip * 255));
        _PutPixelAlpha(surface, 2 * xc - x, 2 * yc - y, color, Uint8(ip * 255));

        _PutPixelAlpha(surface, x, 2 * yc - ys, color, Uint8(is * 255));
        _PutPixelAlpha(surface, 2 * xc - x, 2 * yc - ys, color, Uint8(is * 255));

        /* unlock surface */
        if(_sge_lock && SDL_MUSTLOCK(surface))
            SDL_UnlockSurface(surface);

        /* Fill */
        _VLine(surface, x, y + 1, 2 * yc - y - 1, color);
        _VLine(surface, 2 * xc - x, y + 1, 2 * yc - y - 1, color);
        _VLine(surface, x, ys + 1, 2 * yc - ys - 1, color);
        _VLine(surface, 2 * xc - x, ys + 1, 2 * yc - ys - 1, color);
    }

    dyt = abs(y - yc);

    for(i = 1; i <= dyt; i++)
    {
        y++;
        d -= s + a2;

        if(d <= 0)
            xs = x + 1;
        else if((d + t - b2) < 0)
        {
            if((2 * d + t - b2) <= 0)
                xs = x - 1;
            else
            {
                xs = x;
                x--;
                d += t - b2;
                t -= dt;
            }
        } else
        {
            x--;
            xs = x - 1;
            d += t - b2;
            t -= dt;
        }

        s += ds;

        /* Calculate alpha */
        cp = (float)abs(d) / abs(t);
        is = cp * imax;
        ip = imax - is;

        /* Lock surface */
        if(_sge_lock && SDL_MUSTLOCK(surface))
            if(SDL_LockSurface(surface) < 0)
                return;

        /* Upper half */
        _PutPixelAlpha(surface, x, y, color, Uint8(ip * 255));
        _PutPixelAlpha(surface, 2 * xc - x, y, color, Uint8(ip * 255));

        _PutPixelAlpha(surface, xs, y, color, Uint8(is * 255));
        _PutPixelAlpha(surface, 2 * xc - xs, y, color, Uint8(is * 255));

        /* Lower half*/
        _PutPixelAlpha(surface, x, 2 * yc - y, color, Uint8(ip * 255));
        _PutPixelAlpha(surface, 2 * xc - x, 2 * yc - y, color, Uint8(ip * 255));

        _PutPixelAlpha(surface, xs, 2 * yc - y, color, Uint8(is * 255));
        _PutPixelAlpha(surface, 2 * xc - xs, 2 * yc - y, color, Uint8(is * 255));

        /* unlock surface */
        if(_sge_lock && SDL_MUSTLOCK(surface))
            SDL_UnlockSurface(surface);

        /* Fill */
        _HLine(surface, x + 1, 2 * xc - x - 1, y, color);
        _HLine(surface, xs + 1, 2 * xc - xs - 1, y, color);
        _HLine(surface, x + 1, 2 * xc - x - 1, 2 * yc - y, color);
        _HLine(surface, xs + 1, 2 * xc - xs - 1, 2 * yc - y, color);
    }
}

//==================================================================================
// Draws a filled anti-aliased ellipse (RGB)
//==================================================================================
void sge_AAFilledEllipse(SDL_Surface* surface, Sint16 xc, Sint16 yc, Uint16 rx, Uint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
    sge_AAFilledEllipse(surface, xc, yc, rx, ry, SDL_MapRGB(surface->format, R, G, B));
}

//==================================================================================
// Performs Callback at each circle point.
//==================================================================================
void sge_DoCircle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint32 color,
                  void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    Sint16 cx = 0;
    auto cy = (Sint16)r;
    Sint16 df = 1 - (Sint16)r;
    Sint16 d_e = 3;
    Sint16 d_se = -2 * r + 5;

    do
    {
        Callback(Surface, x + cx, y + cy, color);
        Callback(Surface, x - cx, y + cy, color);
        Callback(Surface, x + cx, y - cy, color);
        Callback(Surface, x - cx, y - cy, color);
        Callback(Surface, x + cy, y + cx, color);
        Callback(Surface, x + cy, y - cx, color);
        Callback(Surface, x - cy, y + cx, color);
        Callback(Surface, x - cy, y - cx, color);

        if(df < 0)
        {
            df += d_e;
            d_e += 2;
            d_se += 2;
        } else
        {
            df += d_se;
            d_e += 2;
            d_se += 4;
            cy--;
        }

        cx++;

    } while(cx <= cy);
}

//==================================================================================
// Performs Callback at each circle point. (RGB)
//==================================================================================
void sge_DoCircle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint8 R, Uint8 G, Uint8 B,
                  void Callback(SDL_Surface* Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
    sge_DoCircle(Surface, x, y, r, SDL_MapRGB(Surface->format, R, G, B), Callback);
}

//==================================================================================
// Draws a circle
//==================================================================================
void sge_Circle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint32 color)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        if(SDL_LockSurface(Surface) < 0)
            return;
    }

    sge_DoCircle(Surface, x, y, r, color, _PutPixel);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a circle (RGB)
//==================================================================================
void sge_Circle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint8 R, Uint8 G, Uint8 B)
{
    sge_Circle(Surface, x, y, r, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws a circle (alpha)
//==================================================================================
void sge_CircleAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint32 color, Uint8 alpha)
{
    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    _sge_alpha_hack = alpha;
    sge_DoCircle(Surface, x, y, r, color, callback_alpha_hack);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a circle (alpha - RGB)
//==================================================================================
void sge_CircleAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_CircleAlpha(Surface, x, y, r, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws a filled circle
//==================================================================================
void sge_FilledCircle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint32 color)
{
    Sint16 cx = 0;
    auto cy = (Sint16)r;
    bool draw = true;
    Sint16 df = 1 - (Sint16)r;
    Sint16 d_e = 3;
    Sint16 d_se = -2 * r + 5;

    do
    {
        if(draw)
        {
            _HLine(Surface, x - cx, x + cx, y + cy, color);
            _HLine(Surface, x - cx, x + cx, y - cy, color);
            draw = false;
        }
        if(cx != cy)
        {
            if(cx)
            {
                _HLine(Surface, x - cy, x + cy, y - cx, color);
                _HLine(Surface, x - cy, x + cy, y + cx, color);
            } else
                _HLine(Surface, x - cy, x + cy, y, color);
        }

        if(df < 0)
        {
            df += d_e;
            d_e += 2;
            d_se += 2;
        } else
        {
            df += d_se;
            d_e += 2;
            d_se += 4;
            cy--;
            draw = true;
        }
        cx++;
    } while(cx <= cy);
}

//==================================================================================
// Draws a filled circle (RGB)
//==================================================================================
void sge_FilledCircle(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint8 R, Uint8 G, Uint8 B)
{
    sge_FilledCircle(Surface, x, y, r, SDL_MapRGB(Surface->format, R, G, B));
}

//==================================================================================
// Draws a filled circle (alpha)
//==================================================================================
void sge_FilledCircleAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint32 color, Uint8 alpha)
{
    Sint16 cx = 0;
    auto cy = (Sint16)r;
    bool draw = true;
    Sint16 df = 1 - (Sint16)r;
    Sint16 d_e = 3;
    Sint16 d_se = -2 * r + 5;

    if(_sge_lock && SDL_MUSTLOCK(Surface))
        if(SDL_LockSurface(Surface) < 0)
            return;

    do
    {
        if(draw)
        {
            _HLineAlpha(Surface, x - cx, x + cx, y + cy, color, alpha);
            _HLineAlpha(Surface, x - cx, x + cx, y - cy, color, alpha);
            draw = false;
        }
        if(cx != cy)
        {
            if(cx)
            {
                _HLineAlpha(Surface, x - cy, x + cy, y - cx, color, alpha);
                _HLineAlpha(Surface, x - cy, x + cy, y + cx, color, alpha);
            } else
                _HLineAlpha(Surface, x - cy, x + cy, y, color, alpha);
        }

        if(df < 0)
        {
            df += d_e;
            d_e += 2;
            d_se += 2;
        } else
        {
            df += d_se;
            d_e += 2;
            d_se += 4;
            cy--;
            draw = true;
        }
        cx++;
    } while(cx <= cy);

    if(_sge_lock && SDL_MUSTLOCK(Surface))
    {
        SDL_UnlockSurface(Surface);
    }
}

//==================================================================================
// Draws a filled circle (alpha - RGB)
//==================================================================================
void sge_FilledCircleAlpha(SDL_Surface* Surface, Sint16 x, Sint16 y, Uint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_FilledCircleAlpha(Surface, x, y, r, SDL_MapRGB(Surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws a filled anti-aliased circle
//==================================================================================
void sge_AAFilledCircle(SDL_Surface* surface, Sint16 xc, Sint16 yc, Uint16 r, Uint32 color)
{
    sge_AAFilledEllipse(surface, xc, yc, r, r, color);
}

//==================================================================================
// Draws a filled anti-aliased circle (RGB)
//==================================================================================
void sge_AAFilledCircle(SDL_Surface* surface, Sint16 xc, Sint16 yc, Uint16 r, Uint8 R, Uint8 G, Uint8 B)
{
    sge_AAFilledEllipse(surface, xc, yc, r, r, SDL_MapRGB(surface->format, R, G, B));
}

//==================================================================================
// Draws a bezier line
//==================================================================================
/* Macro to do the line... 'function' is the line drawing routine */
#define DO_BEZIER(function)                                                                                        \
    /*                                                                                                          */ \
    /*  Note: I don't think there is any great performance win in translating this to fixed-point integer math, */ \
    /*  most of the time is spent in the line drawing routine.                                                  */ \
    /*                                                                                                          */ \
    auto x = float(x1), y = float(y1);                                                                             \
    float xp = x, yp = y;                                                                                          \
    float delta;                                                                                                   \
    float dx, d2x, d3x;                                                                                            \
    float dy, d2y, d3y;                                                                                            \
    float a, b, c;                                                                                                 \
                                                                                                                   \
    /* compute number of iterations */                                                                             \
    if(level < 1)                                                                                                  \
        level = 1;                                                                                                 \
    if(level >= 15)                                                                                                \
        level = 15;                                                                                                \
    const int n = 1 << level;                                                                                      \
    delta = float(1.0 / float(n));                                                                                 \
                                                                                                                   \
    /* compute finite differences */                                                                               \
    /* a, b, c are the coefficient of the polynom in t defining the parametric curve */                            \
    /* The computation is done independently for x and y */                                                        \
    a = float(-x1 + 3 * x2 - 3 * x3 + x4);                                                                         \
    b = float(3 * x1 - 6 * x2 + 3 * x3);                                                                           \
    c = float(-3 * x1 + 3 * x2);                                                                                   \
                                                                                                                   \
    d3x = 6 * a * delta * delta * delta;                                                                           \
    d2x = d3x + 2 * b * delta * delta;                                                                             \
    dx = a * delta * delta * delta + b * delta * delta + c * delta;                                                \
                                                                                                                   \
    a = float(-y1 + 3 * y2 - 3 * y3 + y4);                                                                         \
    b = float(3 * y1 - 6 * y2 + 3 * y3);                                                                           \
    c = float(-3 * y1 + 3 * y2);                                                                                   \
                                                                                                                   \
    d3y = 6 * a * delta * delta * delta;                                                                           \
    d2y = d3y + 2 * b * delta * delta;                                                                             \
    dy = a * delta * delta * delta + b * delta * delta + c * delta;                                                \
                                                                                                                   \
    if(_sge_lock && SDL_MUSTLOCK(surface))                                                                         \
    {                                                                                                              \
        if(SDL_LockSurface(surface) < 0)                                                                           \
            return;                                                                                                \
    }                                                                                                              \
                                                                                                                   \
    /* iterate */                                                                                                  \
    for(int i = 0; i < n; i++)                                                                                     \
    {                                                                                                              \
        x += dx;                                                                                                   \
        dx += d2x;                                                                                                 \
        d2x += d3x;                                                                                                \
        y += dy;                                                                                                   \
        dy += d2y;                                                                                                 \
        d2y += d3y;                                                                                                \
        if(Sint16(xp) != Sint16(x) || Sint16(yp) != Sint16(y))                                                     \
        {                                                                                                          \
            function;                                                                                              \
        }                                                                                                          \
        xp = x;                                                                                                    \
        yp = y;                                                                                                    \
    }                                                                                                              \
                                                                                                                   \
    /* unlock the display */                                                                                       \
    if(_sge_lock && SDL_MUSTLOCK(surface))                                                                         \
    {                                                                                                              \
        SDL_UnlockSurface(surface);                                                                                \
    }

//==================================================================================
// Draws a bezier line
//==================================================================================
void sge_Bezier(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                Sint16 y4, int level, Uint32 color)
{
    DO_BEZIER(_Line(surface, Sint16(xp), Sint16(yp), Sint16(x), Sint16(y), color));
}

//==================================================================================
// Draws a bezier line (RGB)
//==================================================================================
void sge_Bezier(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
{
    sge_Bezier(surface, x1, y1, x2, y2, x3, y3, x4, y4, level, SDL_MapRGB(surface->format, R, G, B));
}

//==================================================================================
// Draws a bezier line (alpha)
//==================================================================================
void sge_BezierAlpha(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                     Sint16 y4, int level, Uint32 color, Uint8 alpha)
{
    _sge_alpha_hack = alpha;

    DO_BEZIER(sge_DoLine(surface, Sint16(xp), Sint16(yp), Sint16(x), Sint16(y), color, callback_alpha_hack));
}

//==================================================================================
// Draws a bezier line (alpha - RGB)
//==================================================================================
void sge_BezierAlpha(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                     Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_BezierAlpha(surface, x1, y1, x2, y2, x3, y3, x4, y4, level, SDL_MapRGB(surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws an AA bezier line (alpha)
//==================================================================================
void sge_AABezierAlpha(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
                       Sint16 x4, Sint16 y4, int level, Uint32 color, Uint8 alpha)
{
    Uint8 lock = _sge_lock;
    _sge_lock = 0;

    if(SDL_MUSTLOCK(surface) && lock)
        if(SDL_LockSurface(surface) < 0)
            return;

    DO_BEZIER(sge_AALineAlpha(surface, Sint16(xp), Sint16(yp), Sint16(x), Sint16(y), color, alpha));

    if(SDL_MUSTLOCK(surface) && lock)
    {
        SDL_UnlockSurface(surface);
    }

    _sge_lock = lock;
}

//==================================================================================
// Draws an AA bezier line (alpha - RGB)
//==================================================================================
void sge_AABezierAlpha(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
                       Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
    sge_AABezierAlpha(surface, x1, y1, x2, y2, x3, y3, x4, y4, level, SDL_MapRGB(surface->format, R, G, B), alpha);
}

//==================================================================================
// Draws an AA bezier line
//==================================================================================
void sge_AABezier(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                  Sint16 y4, int level, Uint32 color)
{
    sge_AABezierAlpha(surface, x1, y1, x2, y2, x3, y3, x4, y4, level, color, 255);
}

//==================================================================================
// Draws an AA bezier line (RGB)
//==================================================================================
void sge_AABezier(SDL_Surface* surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Sint16 x4,
                  Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
{
    sge_AABezierAlpha(surface, x1, y1, x2, y2, x3, y3, x4, y4, level, SDL_MapRGB(surface->format, R, G, B), 255);
}
