|
|
@@ -31,8 +31,16 @@ |
|
|
|
#include "pipi.h" |
|
|
|
#include "pipi_internals.h" |
|
|
|
|
|
|
|
/* math.h doesn't like y1 (sucker) */ |
|
|
|
float floorf(float x); |
|
|
|
float truncf(float x); |
|
|
|
float fabsf(float x); |
|
|
|
|
|
|
|
#if !defined TEMPLATE_FILE /* This file uses the template system */ |
|
|
|
|
|
|
|
static float fractf(float d) { return (d - floorf(d)); } |
|
|
|
static float fractinvf(float d) { return (1 - (d - floorf(d))); } |
|
|
|
|
|
|
|
struct line |
|
|
|
{ |
|
|
|
int x1, y1; |
|
|
@@ -56,8 +64,6 @@ struct line |
|
|
|
|
|
|
|
static void clip_line(pipi_image_t*, struct line*); |
|
|
|
static uint8_t clip_bits(pipi_image_t*, int, int); |
|
|
|
static void draw_antialiased_line_float(pipi_image_t *img, struct line* s); |
|
|
|
static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s); |
|
|
|
|
|
|
|
int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa) |
|
|
|
{ |
|
|
@@ -86,7 +92,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t |
|
|
|
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */ |
|
|
|
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = draw_antialiased_line_float; |
|
|
|
s.draw = antialiased_line; |
|
|
|
} |
|
|
|
} |
|
|
|
else if(img->last_modified == PIPI_PIXELS_Y_F) |
|
|
@@ -95,7 +101,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t |
|
|
|
dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels; |
|
|
|
s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray; |
|
|
|
s.draw = aa == 0 ? aliased_line_gray : antialiased_line_gray; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -105,7 +111,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t |
|
|
|
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */ |
|
|
|
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = aa==0?aliased_line:draw_antialiased_line_float; |
|
|
|
s.draw = aa == 0 ? aliased_line : antialiased_line; |
|
|
|
} |
|
|
|
|
|
|
|
clip_line(img, &s); |
|
|
@@ -137,16 +143,16 @@ int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[], |
|
|
|
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */ |
|
|
|
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = draw_antialiased_line_float; |
|
|
|
s.draw = antialiased_line; |
|
|
|
} |
|
|
|
} |
|
|
|
else if(img->last_modified == PIPI_PIXELS_Y_F) |
|
|
|
{ |
|
|
|
float *dstdata; |
|
|
|
dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels; |
|
|
|
s.colorf[0] = c/255.0f; /* XXX FIXME */ |
|
|
|
s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray; |
|
|
|
s.draw = aa == 0 ? aliased_line_gray : antialiased_line_gray; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -156,7 +162,7 @@ int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[], |
|
|
|
s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */ |
|
|
|
s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */ |
|
|
|
s.buf_f = dstdata; |
|
|
|
s.draw = aa==0?aliased_line:draw_antialiased_line_float; |
|
|
|
s.draw = aa == 0 ? aliased_line : antialiased_line; |
|
|
|
img->last_modified = PIPI_PIXELS_RGBA_F; |
|
|
|
} |
|
|
|
|
|
|
@@ -244,51 +250,176 @@ static uint8_t clip_bits(pipi_image_t *img, int x, int y) |
|
|
|
return b; |
|
|
|
} |
|
|
|
|
|
|
|
/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */ |
|
|
|
#else /* XXX: the following functions use the template system */ |
|
|
|
|
|
|
|
/* math.h doesn't like y1 (sucker) */ |
|
|
|
float floorf(float x); |
|
|
|
float truncf(float x); |
|
|
|
float fabsf(float x); |
|
|
|
/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */ |
|
|
|
|
|
|
|
static float fractf(float d) { return (d - floorf(d)); } |
|
|
|
static float fractinvf(float d) { return (1 - (d - floorf(d))); } |
|
|
|
#define PLOT(x, y, c) \ |
|
|
|
if(FLAG_GRAY) \ |
|
|
|
{ \ |
|
|
|
if(FLAG_8BIT) \ |
|
|
|
{ \ |
|
|
|
/* TODO */ \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
s->buf_f[((int)(x))+((int)(y))*img->w] = \ |
|
|
|
(c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \ |
|
|
|
if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) \ |
|
|
|
s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \ |
|
|
|
if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) \ |
|
|
|
s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \ |
|
|
|
if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) \ |
|
|
|
s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
if(FLAG_8BIT) \ |
|
|
|
{ \ |
|
|
|
/* TODO */ \ |
|
|
|
} \ |
|
|
|
else \ |
|
|
|
{ \ |
|
|
|
int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\ |
|
|
|
int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \ |
|
|
|
int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \ |
|
|
|
s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \ |
|
|
|
s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \ |
|
|
|
s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \ |
|
|
|
if(s->buf_f[qwer] > 1.0f) \ |
|
|
|
s->buf_f[qwer] = 1.0f; \ |
|
|
|
if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) \ |
|
|
|
s->buf_f[qwer] = 0.0f; \ |
|
|
|
if(s->buf_f[qweg] > 1.0f) \ |
|
|
|
s->buf_f[qweg] = 1.0f; \ |
|
|
|
if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) \ |
|
|
|
s->buf_f[qweg] = 0.0f; \ |
|
|
|
if(s->buf_f[qweb] > 1.0f) \ |
|
|
|
s->buf_f[qweb] = 1.0f; \ |
|
|
|
if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) \ |
|
|
|
s->buf_f[qweb] = 0.0f; \ |
|
|
|
} \ |
|
|
|
} |
|
|
|
|
|
|
|
static void draw_antialiased_line_float(pipi_image_t *img, struct line* s) |
|
|
|
static void SUFFIX(antialiased_line)(pipi_image_t *img, struct line* s) |
|
|
|
{ |
|
|
|
/* Is that an horrible mess ? Yes, it is. */ |
|
|
|
#undef PLOT |
|
|
|
#define PLOT(x, y, c) \ |
|
|
|
{ int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\ |
|
|
|
int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \ |
|
|
|
int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \ |
|
|
|
s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \ |
|
|
|
s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \ |
|
|
|
s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \ |
|
|
|
if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \ |
|
|
|
if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) s->buf_f[qwer] = 0.0f; \ |
|
|
|
if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \ |
|
|
|
if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) s->buf_f[qweg] = 0.0f; \ |
|
|
|
if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \ |
|
|
|
if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) s->buf_f[qweb] = 0.0f; } |
|
|
|
|
|
|
|
#include "aline_template.h" |
|
|
|
} |
|
|
|
float x1 = s->x1, y1 = s->y1, x2 = s->x2, y2 = s->y2; |
|
|
|
float g, xd, yd, xgap, xend, yend, xf, yf, val1, val2; |
|
|
|
int x, y, ix1, ix2, iy1, iy2; |
|
|
|
|
|
|
|
xd = x2 - x1; |
|
|
|
yd = y2 - y1; |
|
|
|
|
|
|
|
static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s) |
|
|
|
{ |
|
|
|
#undef PLOT |
|
|
|
#define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] = \ |
|
|
|
(c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \ |
|
|
|
if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \ |
|
|
|
if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \ |
|
|
|
if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; |
|
|
|
|
|
|
|
#include "aline_template.h" |
|
|
|
/* "Horizontal" line (X greater than Y)*/ |
|
|
|
if (fabsf(xd) > fabsf(yd)) |
|
|
|
{ |
|
|
|
if (x1 > x2) |
|
|
|
{ |
|
|
|
float tmp; |
|
|
|
tmp = x1; x1 = x2; x2 = tmp; |
|
|
|
tmp = y1; y1 = y2; y2 = tmp; |
|
|
|
xd = (x2-x1); |
|
|
|
yd = (y2-y1); |
|
|
|
} |
|
|
|
g = yd/xd; |
|
|
|
|
|
|
|
xend = truncf(x1+0.5); |
|
|
|
yend = y1 + g*(xend-x1); |
|
|
|
xgap = fractinvf(x1+0.5); |
|
|
|
ix1 = (int)xend; |
|
|
|
iy1 = (int)yend; |
|
|
|
val1 = fractinvf(yend)*xgap; |
|
|
|
val2 = fractf(yend)*xgap; |
|
|
|
|
|
|
|
PLOT(ix1, iy1, val1); |
|
|
|
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2); |
|
|
|
|
|
|
|
yf = yend+g; |
|
|
|
xend = truncf(x2+0.5); |
|
|
|
yend = y2 + g*(xend-x2); |
|
|
|
xgap = fractinvf(x2-0.5); |
|
|
|
ix2 = (int)xend; |
|
|
|
iy2 = (int)yend; |
|
|
|
val1 = fractinvf(yend)*xgap; |
|
|
|
val2 = fractf(yend)*xgap; |
|
|
|
|
|
|
|
PLOT(ix2, iy2, val1); |
|
|
|
PLOT(ix2, iy2+1<y2?iy2+1:iy2, val2); |
|
|
|
|
|
|
|
for (x = (ix1+1); x < ix2; x++) |
|
|
|
{ |
|
|
|
float focus; |
|
|
|
|
|
|
|
val1 = fractinvf(yf); |
|
|
|
val2 = fractf(yf); |
|
|
|
focus = (1.0 - fabsf(val1-val2)); |
|
|
|
val1 += 0.3*focus; |
|
|
|
val2 += 0.3*focus; |
|
|
|
|
|
|
|
PLOT(x, yf, val1); |
|
|
|
PLOT(x, (yf+1)<y1?(yf+1):yf, val2); |
|
|
|
|
|
|
|
yf = yf + g; |
|
|
|
} |
|
|
|
} |
|
|
|
/* "Vertical" line (Y greater than X)*/ |
|
|
|
else |
|
|
|
{ |
|
|
|
if (x1 > x2) |
|
|
|
{ |
|
|
|
float tmp; |
|
|
|
tmp = x1; x1 = x2; x2 = tmp; |
|
|
|
tmp = y1; y1 = y2; y2 = tmp; |
|
|
|
xd = (x2-x1); |
|
|
|
yd = (y2-y1); |
|
|
|
} |
|
|
|
|
|
|
|
g = xd/yd; |
|
|
|
|
|
|
|
xend = truncf(x1+0.5); |
|
|
|
yend = y1 + g*(xend-x1); |
|
|
|
xgap = fractf(x1+0.5); |
|
|
|
ix1 = (int)xend; |
|
|
|
iy1 = (int)yend; |
|
|
|
val1 = fractinvf(yend)*xgap; |
|
|
|
val2 = fractf(yend)*xgap; |
|
|
|
|
|
|
|
PLOT(ix1, iy1, val1); |
|
|
|
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2); |
|
|
|
|
|
|
|
xf = xend + g; |
|
|
|
|
|
|
|
xend = truncf(x2+0.5); |
|
|
|
yend = y2 + g*(xend-x2); |
|
|
|
xgap = fractinvf(x2-0.5); |
|
|
|
ix2 = (int)xend; |
|
|
|
iy2 = (int)yend; |
|
|
|
val1 = fractinvf(yend)*xgap; |
|
|
|
val2 = fractf(yend)*xgap; |
|
|
|
|
|
|
|
PLOT(ix2, iy2, val1); |
|
|
|
PLOT(ix2, (iy2+1)<y2?(iy2+1):iy2, val2); |
|
|
|
|
|
|
|
|
|
|
|
for (y = (iy1+1); y < iy2; y++) |
|
|
|
{ |
|
|
|
float focus; |
|
|
|
int vx = xf; |
|
|
|
val1 = fractinvf(xf); |
|
|
|
val2 = fractf(xf); |
|
|
|
focus = (1.0 - fabsf(val1-val2)); |
|
|
|
val1 += 0.3*focus; |
|
|
|
val2 += 0.3*focus; |
|
|
|
PLOT(vx, y, val1); |
|
|
|
vx++; |
|
|
|
PLOT(vx, y, val2); |
|
|
|
xf = xf + g; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#else /* XXX: the following functions use the template system */ |
|
|
|
#undef PLOT |
|
|
|
|
|
|
|
/* Solid line drawing function, using Bresenham's mid-point line |
|
|
|
* scan-conversion algorithm. */ |
|
|
|