/*
* SDL Graphics Extension
* Drawing primitives
*
* Started 990815 (split from sge_draw 010611)
*
* License: LGPL v2+ (see the file LICENSE)
* (c)1999-2003 Anders Lindström
*/
/*********************************************************************
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
*********************************************************************/
/*
* Some of this code is taken from the "Introduction to SDL" and
* John Garrison's PowerPak
*/
#include "SDL.h"
#include <math.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "sge_primitives.h"
#include "sge_surface.h"
/* Globals used for sge_Update/sge_Lock (defined in sge_surface) */
extern Uint8 _sge_update;
extern Uint8 _sge_lock;
#define SWAP(x,y,temp) temp=x;x=y;y=temp
/**********************************************************************************/
/** 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;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
return;
if(x1<Surface->clip_minx)
x1=Surface->clip_minx;
if(x2>Surface->clip_maxx)
x2=Surface->clip_maxx;
#endif
SDL_Rect l;
l.x=x1; l.y=y; l.w=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;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
return;
if(x1<Surface->clip_minx)
x1=Surface->clip_minx;
if(x2>Surface->clip_maxx)
x2=Surface->clip_maxx;
#endif
SDL_Rect l;
l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
SDL_FillRect(Surface, &l, Color);
sge_UpdateRect(Surface, x1, y, x2-x1+1, 1);
}
//==================================================================================
// 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 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_sge_lock = 0;
sge_FilledRectAlpha(Surface, x1,y,x2,y, Color, alpha);
_sge_update = update;
_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
//==================================================================================
void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
{
if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
return;
if(y1<Surface->clip_miny)
y1=Surface->clip_miny;
if(y2>Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect l;
l.x=x; l.y=y1; l.w=1; l.h=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;}
//Do the clipping
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
return;
if(y1<Surface->clip_miny)
y1=Surface->clip_miny;
if(y2>Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect l;
l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
SDL_FillRect(Surface, &l, Color);
sge_UpdateRect(Surface, x, y1, 1, y2-y1+1);
}
//==================================================================================
// 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)
//==================================================================================
void _VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
{
Uint8 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_sge_lock = 0;
sge_FilledRectAlpha(Surface, x,y1,x,y2, Color, alpha);
_sge_update = update;
_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))
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;
}
int clipLine(SDL_Surface *dst, Sint16 *x1, Sint16 *y1, Sint16 *x2, Sint16 *y2)
{
int code1, code2;
bool draw = false;
Sint16 tmp;
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){
code1 = clipEncode(*x1, *y1, left, top, right, bottom);
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)){
tmp = *x2;
*x2 = *x1;
*x1 = tmp;
tmp = *y2;
*y2 = *y1;
*y1 = tmp;
tmp = code2;
code2 = code1;
code1 = tmp;
}
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, x, y;
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;
Sint16 pixx = surface->format->BytesPerPixel;
Sint16 pixy = 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(x=0; x < dx; x++) {
*pixel = color;
y += dy;
if (y >= dx) {
y -= dx;
pixel += pixy;
}
pixel += pixx;
}
}
break;
case 2: {
for(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(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(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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
/* Draw the line */
_Line(Surface, x1,y1, x2,y2, Color);
/* unlock the display */
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
//==================================================================================
// 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 (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_LineAlpha(Surface, x1, y1, x2, y2, Color, alpha);
/* unlock the display */
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
//==================================================================================
// 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 tmp, 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, tmp);
SWAP(xx0, xx1, tmp);
}
/* Calculate distance */
Sint16 dx = xx1 - xx0;
Sint16 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 = ((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 = ((dy << 16) / 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 ( SDL_MUSTLOCK(dst) && _sge_lock )
if ( SDL_LockSurface(dst) < 0 )
return;
_AALineAlpha(dst,x1,y1,x2,y2,color,alpha);
/* unlock the display */
if (SDL_MUSTLOCK(dst) && _sge_lock) {
SDL_UnlockSurface(dst);
}
sge_UpdateRect(dst, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
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 (SDL_MUSTLOCK(Surface) && _sge_lock)
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
//==================================================================================
// 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 tmp, 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, tmp);
SWAP(xx0, xx1, tmp);
SWAP(r1, r2, a);
SWAP(g1, g2, a);
SWAP(b1, b2, a);
}
/* Calculate distance */
Sint16 dx = xx1 - xx0;
Sint16 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 = ((dx << 16) / 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;
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 = ((dy << 16) / 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;
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 ( SDL_MUSTLOCK(dst) && _sge_lock )
if ( SDL_LockSurface(dst) < 0 )
return;
_AAmcLineAlpha(dst, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, alpha);
if (SDL_MUSTLOCK(dst) && _sge_lock)
SDL_UnlockSurface(dst);
sge_UpdateRect(dst, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
}
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);
sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
}
//==================================================================================
// 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 (SDL_MUSTLOCK(Surface) && _sge_lock)
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
}
//==================================================================================
// 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;
}
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
SDL_VERSIONNUM(1, 1, 5)
if(x2<Surface->clip_minx || x1>Surface->clip_maxx || y2<Surface->clip_miny || y1>Surface->clip_maxy)
return;
if (x1 < Surface->clip_minx)
x1=Surface->clip_minx;
if (x2 > Surface->clip_maxx)
x2=Surface->clip_maxx;
if (y1 < Surface->clip_miny)
y1=Surface->clip_miny;
if (y2 > Surface->clip_maxy)
y2=Surface->clip_maxy;
#endif
SDL_Rect area;
area.x=x1; area.y=y1;
area.w=x2-x1+1; area.h=y2-y1+1;
SDL_FillRect(Surface,&area,color);
sge_UpdateRect(Surface, x1, y1, x2-x1+1, y2-y1+1);
}
//==================================================================================
// 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 (SDL_MUSTLOCK(surface) && _sge_lock)
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 (SDL_MUSTLOCK(surface) && _sge_lock) {
SDL_UnlockSurface(surface);
}
sge_UpdateRect(surface, x1, y1, x2-x1+1, y2-y1+1);
}
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, Sint16 rx, Sint16 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, Sint16 rx, Sint16 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, Sint16 rx, Sint16 ry, Uint32 color)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
sge_DoEllipse(Surface, x, y, rx, ry, color, _PutPixel);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws an ellipse (RGB)
//==================================================================================
void sge_Ellipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 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, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_sge_alpha_hack = alpha;
sge_DoEllipse(Surface, x, y, rx, ry, color, callback_alpha_hack);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws an ellipse (alpha - RGB)
//==================================================================================
void sge_EllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 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, Sint16 rx, Sint16 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);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws a filled ellipse (RGB)
//==================================================================================
void sge_FilledEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 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, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
if (SDL_MUSTLOCK(Surface) && _sge_lock)
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws a filled ellipse (alpha - RGB)
//==================================================================================
void sge_FilledEllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 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 an anti-aliased ellipse (alpha)
// Some of this code is taken from "TwinLib" (http://www.twinlib.org) written by
// Nicolas Roard (nicolas@roard.com)
//==================================================================================
void sge_AAEllipseAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
{
/* 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;
int 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;
Uint8 s_alpha, p_alpha;
float alpha_pp = float(alpha)/255;
/* Lock surface */
if ( SDL_MUSTLOCK(surface) && _sge_lock )
if ( SDL_LockSurface(surface) < 0 )
return;
/* "End points" */
_PutPixelAlpha(surface, x, y, color, alpha);
_PutPixelAlpha(surface, 2*xc-x, y, color, alpha);
_PutPixelAlpha(surface, x, 2*yc-y, color, alpha);
_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, alpha);
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 = float( cp * imax + 0.1 );
ip = float( imax - is + 0.2 );
/* Overflow check */
if( is > 1.0 )
is = 1.0;
if( ip > 1.0 )
ip = 1.0;
/* Calculate alpha level */
s_alpha = Uint8(is*255);
p_alpha = Uint8(ip*255);
if( alpha != 255 ){
s_alpha = Uint8(s_alpha*alpha_pp);
p_alpha = Uint8(p_alpha*alpha_pp);
}
/* Upper half */
_PutPixelAlpha(surface, x, y, color, p_alpha);
_PutPixelAlpha(surface, 2*xc-x, y, color, p_alpha);
_PutPixelAlpha(surface, x, ys, color, s_alpha);
_PutPixelAlpha(surface, 2*xc-x, ys, color, s_alpha);
/* Lower half */
_PutPixelAlpha(surface, x, 2*yc-y, color, p_alpha);
_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, p_alpha);
_PutPixelAlpha(surface, x, 2*yc-ys, color, s_alpha);
_PutPixelAlpha(surface, 2*xc-x, 2*yc-ys, color, s_alpha);
}
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 = float( cp * imax + 0.1 );
ip = float( imax - is + 0.2 );
/* Overflow check */
if( is > 1.0 )
is = 1.0;
if( ip > 1.0 )
ip = 1.0;
/* Calculate alpha level */
s_alpha = Uint8(is*255);
p_alpha = Uint8(ip*255);
if( alpha != 255 ){
s_alpha = Uint8(s_alpha*alpha_pp);
p_alpha = Uint8(p_alpha*alpha_pp);
}
/* Upper half */
_PutPixelAlpha(surface, x, y, color, p_alpha);
_PutPixelAlpha(surface, 2*xc-x, y, color, p_alpha);
_PutPixelAlpha(surface, xs, y, color, s_alpha);
_PutPixelAlpha(surface, 2*xc-xs, y, color, s_alpha);
/* Lower half*/
_PutPixelAlpha(surface, x, 2*yc-y, color, p_alpha);
_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, p_alpha);
_PutPixelAlpha(surface, xs, 2*yc-y, color, s_alpha);
_PutPixelAlpha(surface, 2*xc-xs, 2*yc-y, color, s_alpha);
}
/* unlock surface */
if (SDL_MUSTLOCK(surface) && _sge_lock) {
SDL_UnlockSurface(surface);
}
/* Update surface if needed */
sge_UpdateRect(surface, xc-rx, yc-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws an anti-aliased ellipse (alpha - RGB)
//==================================================================================
void sge_AAEllipseAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_AAEllipseAlpha(surface,xc,yc,rx,ry,SDL_MapRGB(surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws an anti-aliased ellipse
//==================================================================================
void sge_AAEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
{
sge_AAEllipseAlpha(surface,xc,yc,rx,ry,color,255);
}
//==================================================================================
// Draws an anti-aliased ellipse (RGB)
//==================================================================================
void sge_AAEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
{
sge_AAEllipseAlpha(surface,xc,yc,rx,ry,SDL_MapRGB(surface->format, R, G, B),255);
}
//==================================================================================
// Draws a filled anti-aliased ellipse
// This is just a quick hack...
//==================================================================================
void sge_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 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;
int 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 ( SDL_MUSTLOCK(surface) && _sge_lock )
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 (SDL_MUSTLOCK(surface) && _sge_lock)
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 ( SDL_MUSTLOCK(surface) && _sge_lock )
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 (SDL_MUSTLOCK(surface) && _sge_lock)
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 ( SDL_MUSTLOCK(surface) && _sge_lock )
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 (SDL_MUSTLOCK(surface) && _sge_lock)
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);
}
/* Update surface if needed */
sge_UpdateRect(surface, xc-rx, yc-ry, 2*rx+1, 2*ry+1);
}
//==================================================================================
// Draws a filled anti-aliased ellipse (RGB)
//==================================================================================
void sge_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 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, Sint16 r, Uint32 color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
{
Sint16 cx = 0;
Sint16 cy = r;
Sint16 df = 1 - 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, Sint16 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, Sint16 r, Uint32 color)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
if (SDL_LockSurface(Surface) < 0)
return;
}
sge_DoCircle(Surface, x, y, r, color, _PutPixel);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a circle (RGB)
//==================================================================================
void sge_Circle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 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, Sint16 r, Uint32 color, Uint8 alpha)
{
if (SDL_MUSTLOCK(Surface) && _sge_lock)
if (SDL_LockSurface(Surface) < 0)
return;
_sge_alpha_hack = alpha;
sge_DoCircle(Surface, x, y, r, color, callback_alpha_hack);
if (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a circle (alpha - RGB)
//==================================================================================
void sge_CircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 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, Sint16 r, Uint32 color)
{
Sint16 cx = 0;
Sint16 cy = r;
bool draw=true;
Sint16 df = 1 - 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);
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a filled circle (RGB)
//==================================================================================
void sge_FilledCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 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, Sint16 r, Uint32 color, Uint8 alpha)
{
Sint16 cx = 0;
Sint16 cy = r;
bool draw=true;
Sint16 df = 1 - r;
Sint16 d_e = 3;
Sint16 d_se = -2 * r + 5;
if (SDL_MUSTLOCK(Surface) && _sge_lock)
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 (SDL_MUSTLOCK(Surface) && _sge_lock) {
SDL_UnlockSurface(Surface);
}
sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
}
//==================================================================================
// Draws a filled circle (alpha - RGB)
//==================================================================================
void sge_FilledCircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_FilledCircleAlpha(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws an anti-aliased circle (alpha)
//==================================================================================
void sge_AACircleAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint32 color, Uint8 alpha)
{
sge_AAEllipseAlpha(surface, xc, yc, r, r, color, alpha);
}
//==================================================================================
// Draws an anti-aliased circle (alpha - RGB)
//==================================================================================
void sge_AACircleAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
{
sge_AAEllipseAlpha(surface,xc,yc,r,r,SDL_MapRGB(surface->format, R, G, B),alpha);
}
//==================================================================================
// Draws an anti-aliased circle
//==================================================================================
void sge_AACircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint32 color)
{
sge_AAEllipseAlpha(surface,xc,yc,r,r,color,255);
}
//==================================================================================
// Draws an anti-aliased circle (RGB)
//==================================================================================
void sge_AACircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
{
sge_AAEllipseAlpha(surface,xc,yc,r,r,SDL_MapRGB(surface->format, R, G, B),255);
}
//==================================================================================
// Draws a filled anti-aliased circle
//==================================================================================
void sge_AAFilledCircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 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, Sint16 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.
*/\
float 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;\
int i;\
int n = 1;\
Sint16 xmax=x1, ymax=y1, xmin=x1, ymin=y1;\
\
/* compute number of iterations */\
if(level < 1)\
level=1;\
if(level >= 15)\
level=15; \
while (level-- > 0)\
n*= 2;\
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 (SDL_MUSTLOCK(surface) && _sge_lock) {\
if (SDL_LockSurface(surface) < 0)\
return;\
}\
\
/* iterate */\
for (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;\
if(_sge_update==1){\
xmax= (xmax>Sint16(xp))? xmax : Sint16(xp); ymax= (ymax>Sint16(yp))? ymax : Sint16(yp);\
xmin= (xmin<Sint16(xp))? xmin : Sint16(xp); ymin= (ymin<Sint16(yp))? ymin : Sint16(yp);\
xmax= (xmax>Sint16(x))? xmax : Sint16(x); ymax= (ymax>Sint16(y))? ymax : Sint16(y);\
xmin= (xmin<Sint16(x))? xmin : Sint16(x); ymin= (ymin<Sint16(y))? ymin : Sint16(y);\
}\
}\
xp = x; yp = y;\
}\
\
/* unlock the display */\
if (SDL_MUSTLOCK(surface) && _sge_lock) {\
SDL_UnlockSurface(surface);\
}\
\
/* Update the area */\
sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
//==================================================================================
// 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 update = _sge_update;
Uint8 lock = _sge_lock;
_sge_update = 0;
_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_update = update;
_sge_lock = lock;
sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
}
//==================================================================================
// 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);
}