jose's AA rendering patches are in! :)

SVN revision: 10507
This commit is contained in:
Carsten Haitzler 2004-06-15 02:36:58 +00:00
parent 3f3e5f1e3b
commit 5600603ad9
12 changed files with 5685 additions and 2602 deletions

View File

@ -19,10 +19,11 @@ lib_LTLIBRARIES = libImlib2.la
include_HEADERS = Imlib2.h
libImlib2_la_SOURCES = scale.c image.c blend.c file.c rgbadraw.c api.c \
updates.c colormod.c format.c grad.c rotate.c \
span.c line.c rectangle.c ellipse.c polygon.c \
filter.c script.c dynamic_filters.c color_helpers.c \
font_main.c font_load.c font_query.c font_draw.c \
Imlib2.h image.h scale.h blend.h updates.h colormod.h \
file.h common.h rgbadraw.h font.h format.h \
file.h common.h span.h rgbadraw.h font.h format.h \
rotate.h grad.h filter.h script.h dynamic_filters.h \
color_helpers.h loaderpath.h

221
src/api.c
View File

@ -11,6 +11,7 @@
#include "image.h"
#include "scale.h"
#include "blend.h"
#include "span.h"
#ifndef X_DISPLAY_MISSING
#include "context.h"
#include "color.h"
@ -2704,6 +2705,7 @@ Imlib_Updates
imlib_image_draw_pixel(int x, int y, char make_updates)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -2715,38 +2717,22 @@ imlib_image_draw_pixel(int x, int y, char make_updates)
if (!(im->data))
return NULL;
__imlib_DirtyImage(im);
if (ctx->cliprect.w == 0)
{
__imlib_draw_set_point(im, x, y,
(DATA8) ctx->color.red,
(DATA8) ctx->color.green,
(DATA8) ctx->color.blue,
(DATA8) ctx->color.alpha, ctx->operation);
}
else
{
__imlib_draw_set_point_clipped(im, x, y,
ctx->cliprect.x,
ctx->cliprect.x +
ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y +
ctx->cliprect.h - 1,
(DATA8) ctx->color.red,
(DATA8) ctx->color.green,
(DATA8) ctx->color.blue,
(DATA8) ctx->color.alpha,
ctx->operation);
}
if (!make_updates)
return (Imlib_Updates) NULL;
return (Imlib_Updates) __imlib_AddUpdate(NULL, x, y, 1, 1);
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
return (Imlib_Updates) __imlib_Point_DrawToImage(x, y, color, im,
ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend,
make_updates);
}
Imlib_Updates
imlib_image_draw_line(int x1, int y1, int x2, int y2, char make_updates)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -2758,40 +2744,22 @@ imlib_image_draw_line(int x1, int y1, int x2, int y2, char make_updates)
if (!(im->data))
return NULL;
__imlib_DirtyImage(im);
if (ctx->cliprect.w)
{
return (Imlib_Updates) __imlib_draw_line_clipped(im, x1, y1, x2, y2,
ctx->cliprect.x,
ctx->cliprect.x +
ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y +
ctx->cliprect.h - 1,
(DATA8) ctx->color.red,
(DATA8) ctx->color.
green,
(DATA8) ctx->color.
blue,
(DATA8) ctx->color.
alpha, ctx->operation,
(char)make_updates);
}
else
{
return (Imlib_Updates) __imlib_draw_line(im, x1, y1, x2, y2,
(DATA8) ctx->color.red,
(DATA8) ctx->color.green,
(DATA8) ctx->color.blue,
(DATA8) ctx->color.alpha,
ctx->operation,
(char)make_updates);
}
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
return (Imlib_Updates) __imlib_Line_DrawToImage(x1, y1, x2, y2, color, im,
ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend,
ctx->anti_alias, make_updates);
}
void
imlib_image_draw_rectangle(int x, int y, int width, int height)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -2802,28 +2770,21 @@ imlib_image_draw_rectangle(int x, int y, int width, int height)
if (!(im->data))
return;
__imlib_DirtyImage(im);
if (ctx->cliprect.w)
{
__imlib_draw_box_clipped(im, x, y, width, height, ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
else
{
__imlib_draw_box(im, x, y, width, height, ctx->color.red,
ctx->color.green, ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Rectangle_DrawToImage(x, y, width, height, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend);
}
void
imlib_image_fill_rectangle(int x, int y, int width, int height)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -2834,23 +2795,14 @@ imlib_image_fill_rectangle(int x, int y, int width, int height)
if (!(im->data))
return;
__imlib_DirtyImage(im);
if (ctx->cliprect.w)
{
__imlib_draw_filled_box_clipped(im, x, y, width, height,
ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
else
{
__imlib_draw_filled_box(im, x, y, width, height, ctx->color.red,
ctx->color.green, ctx->color.blue,
ctx->color.alpha, ctx->operation);
}
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Rectangle_FillToImage(x, y, width, height, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend);
}
void
@ -3731,7 +3683,7 @@ imlib_polygon_add_point(ImlibPolygon poly, int x, int y)
if (!ctx)
ctx = imlib_context_new();
CHECK_PARAM_POINTER("imlib_polygon_add_point", "polygon", poly);
__imlib_polygon_add_point(poly, x, y);
__imlib_polygon_add_point((ImlibPoly) poly, x, y);
}
void
@ -3740,13 +3692,14 @@ imlib_polygon_free(ImlibPolygon poly)
if (!ctx)
ctx = imlib_context_new();
CHECK_PARAM_POINTER("imlib_polygon_free", "polygon", poly);
__imlib_polygon_free(poly);
__imlib_polygon_free((ImlibPoly) poly);
}
void
imlib_image_draw_polygon(ImlibPolygon poly, unsigned char closed)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -3757,27 +3710,21 @@ imlib_image_draw_polygon(ImlibPolygon poly, unsigned char closed)
if (!(im->data))
return;
__imlib_DirtyImage(im);
if (ctx->cliprect.w)
{
__imlib_draw_polygon_clipped(im, poly, closed, ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h - 1,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
else
{
__imlib_draw_polygon(im, poly, closed, ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha, ctx->operation);
}
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Polygon_DrawToImage((ImlibPoly) poly, closed, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend, ctx->anti_alias);
}
void
imlib_image_fill_polygon(ImlibPolygon poly)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -3788,13 +3735,14 @@ imlib_image_fill_polygon(ImlibPolygon poly)
if (!(im->data))
return;
__imlib_DirtyImage(im);
__imlib_draw_polygon_filled(im, poly, ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h - 1,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation, ctx->anti_alias);
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Polygon_FillToImage((ImlibPoly) poly, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend, ctx->anti_alias);
}
void
@ -3804,13 +3752,14 @@ imlib_polygon_get_bounds(ImlibPolygon poly, int *px1, int *py1, int *px2,
if (!ctx)
ctx = imlib_context_new();
CHECK_PARAM_POINTER("imlib_polygon_get_bounds", "polygon", poly);
__imlib_polygon_get_bounds(poly, px1, py1, px2, py2);
__imlib_polygon_get_bounds((ImlibPoly) poly, px1, py1, px2, py2);
}
void
imlib_image_draw_ellipse(int xc, int yc, int a, int b)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -3821,31 +3770,21 @@ imlib_image_draw_ellipse(int xc, int yc, int a, int b)
if (!(im->data))
return;
__imlib_DirtyImage(im);
if (ctx->cliprect.w)
{
__imlib_draw_ellipse_clipped(im, xc, yc, a, b, ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h - 1,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
else
{
__imlib_draw_ellipse_clipped(im, xc, yc, a, b, 0,
im->w - 1, 0, im->h - 1,
ctx->color.red, ctx->color.green,
ctx->color.blue, ctx->color.alpha,
ctx->operation);
}
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Ellipse_DrawToImage(xc, yc, a, b, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend, ctx->anti_alias);
}
void
imlib_image_fill_ellipse(int xc, int yc, int a, int b)
{
ImlibImage *im;
DATA32 color;
if (!ctx)
ctx = imlib_context_new();
@ -3856,13 +3795,14 @@ imlib_image_fill_ellipse(int xc, int yc, int a, int b)
if (!(im->data))
return;
__imlib_DirtyImage(im);
__imlib_fill_ellipse(im, xc, yc, a, b, ctx->cliprect.x,
ctx->cliprect.x + ctx->cliprect.w - 1,
ctx->cliprect.y,
ctx->cliprect.y + ctx->cliprect.h - 1, ctx->color.red,
ctx->color.green, ctx->color.blue, ctx->color.alpha,
ctx->operation, ctx->anti_alias);
A_VAL(&color) = (DATA8) ctx->color.alpha;
R_VAL(&color) = (DATA8) ctx->color.red;
G_VAL(&color) = (DATA8) ctx->color.green;
B_VAL(&color) = (DATA8) ctx->color.blue;
__imlib_Ellipse_FillToImage(xc, yc, a, b, color,
im, ctx->cliprect.x, ctx->cliprect.y,
ctx->cliprect.w, ctx->cliprect.h,
ctx->operation, ctx->blend, ctx->anti_alias);
}
unsigned char
@ -3870,9 +3810,8 @@ imlib_polygon_contains_point(ImlibPolygon poly, int x, int y)
{
if (!ctx)
ctx = imlib_context_new();
CHECK_PARAM_POINTER_RETURN("imlib_polygon_contains_point", "polygon", poly,
0);
return __imlib_polygon_contains_point(poly, x, y);
CHECK_PARAM_POINTER_RETURN("imlib_polygon_contains_point", "polygon", poly, 0);
return __imlib_polygon_contains_point((ImlibPoly) poly, x, y);
}
void

File diff suppressed because it is too large Load Diff

View File

@ -188,7 +188,8 @@ else \
* b) Include source alpha in the calculation for new destination alpha?
* If source alpha is not used, then destination alpha is preserved.
* If source alpha is used, a "copy" sets the new alpha to the source
* alpha, and a "blend" adds them together (with saturation).
* alpha, and a "blend" increases it by a factor given by the product
* of the source alpha with one minus the destination alpha.
* c) Should the source pixels be passed through a color modifier before the
* calculations are performed?
*
@ -296,6 +297,19 @@ else \
*
* Notice the color values created by this operation are in the range
* (-256, 512), and thus must be saturated at 0 and 255 (from above and below).
*
* For all the operations, when the "blend" version involves computing new
* destination alpha values via the use of some source alpha, we have that:
*
* nalpha = alpha + ((255 - alpha) * (a / 255))
*
* We can use the previous argument for approximating division by 255, and
* calculate this by:
*
* tmp = (255 - alpha) * a;
* nalpha = alpha + ((tmp + (tmp >> 8) + 0x80) >> 8);
*
* This is again in the range [0, 255], so no saturation is needed.
*/
#define BLEND_COLOR(a, nc, c, cc) \
@ -303,58 +317,57 @@ tmp = ((c) - (cc)) * (a); \
nc = (cc) + ((tmp + (tmp >> 8) + 0x80) >> 8);
#define ADD_COLOR_WITH_ALPHA(a, nc, c, cc) \
tmp = (cc) + (((c) * (a)) >> 8); \
SATURATE_UPPER(nc, tmp);
tmp = (c) * (a); \
tmp = (cc) + ((tmp + (tmp >> 8) + 0x80) >> 8); \
nc = (tmp | (-(tmp >> 8)));
#define ADD_COLOR(nc, c, cc) \
tmp = (cc) + (c); \
SATURATE_UPPER(nc, tmp);
nc = (tmp | (-(tmp >> 8)));
#define SUB_COLOR_WITH_ALPHA(a, nc, c, cc) \
tmp = (cc) - (((c) * (a)) >> 8); \
SATURATE_LOWER((nc), (tmp));
tmp = (c) * (a); \
tmp = (cc) - ((tmp + (tmp >> 8) + 0x80) >> 8); \
nc = (tmp & (~(tmp >> 8)));
#define SUB_COLOR(nc, c, cc) \
tmp = (cc) - (c); \
SATURATE_LOWER(nc, tmp);
nc = (tmp & (~(tmp >> 8)));
#define RESHADE_COLOR_WITH_ALPHA(a, nc, c, cc) \
tmp = (cc) + ((((c) - 127) * (a)) >> 7); \
SATURATE_BOTH(nc, tmp);
nc = (tmp | (-(tmp >> 8))) & (~(tmp >> 9));
#define RESHADE_COLOR(nc, c, cc) \
tmp = (cc) + (((c) - 127) << 1); \
SATURATE_BOTH(nc, tmp);
nc = (tmp | (-(tmp >> 8))) & (~(tmp >> 9));
extern int pow_lut_initialized;
extern DATA8 pow_lut[256][256];
#define BLEND_DST_ALPHA(r1, g1, b1, a1, dest) \
{ int _aa; \
{ DATA8 _aa; \
_aa = pow_lut[a1][A_VAL(dest)]; \
BLEND_COLOR(a1, A_VAL(dest), 255, A_VAL(dest)); \
BLEND_COLOR(_aa, R_VAL(dest), r1, R_VAL(dest)); \
BLEND_COLOR(_aa, G_VAL(dest), g1, G_VAL(dest)); \
BLEND_COLOR(_aa, B_VAL(dest), b1, B_VAL(dest)); \
A_VAL(dest) = A_VAL(dest) + ((a1 * (255 - A_VAL(dest))) / 255); \
}
#define BLEND(r1, g1, b1, a1, dest) \
BLEND_COLOR(a1, R_VAL(dest), r1, R_VAL(dest)); \
BLEND_COLOR(a1, G_VAL(dest), g1, G_VAL(dest)); \
BLEND_COLOR(a1, B_VAL(dest), b1, B_VAL(dest)); \
SATURATE_UPPER(A_VAL(dest), (a1) + A_VAL(dest));
BLEND_COLOR(a1, B_VAL(dest), b1, B_VAL(dest));
#define BLEND_ADD(r1, g1, b1, a1, dest) \
ADD_COLOR_WITH_ALPHA(a1, R_VAL(dest), r1, R_VAL(dest)); \
ADD_COLOR_WITH_ALPHA(a1, G_VAL(dest), g1, G_VAL(dest)); \
ADD_COLOR_WITH_ALPHA(a1, B_VAL(dest), b1, B_VAL(dest)); \
SATURATE_UPPER(A_VAL(dest), (a1) + A_VAL(dest));
ADD_COLOR_WITH_ALPHA(a1, B_VAL(dest), b1, B_VAL(dest));
#define BLEND_SUB(r1, g1, b1, a1, dest) \
SUB_COLOR_WITH_ALPHA(a1, R_VAL(dest), r1, R_VAL(dest)); \
SUB_COLOR_WITH_ALPHA(a1, G_VAL(dest), g1, G_VAL(dest)); \
SUB_COLOR_WITH_ALPHA(a1, B_VAL(dest), b1, B_VAL(dest)); \
SATURATE_UPPER(A_VAL(dest), (a1) + A_VAL(dest));
SUB_COLOR_WITH_ALPHA(a1, B_VAL(dest), b1, B_VAL(dest));
#define BLEND_RE(r1, g1, b1, a1, dest) \
RESHADE_COLOR_WITH_ALPHA(a1, R_VAL(dest), r1, R_VAL(dest)); \

725
src/ellipse.c Normal file
View File

@ -0,0 +1,725 @@
#include "common.h"
#include "colormod.h"
#include "image.h"
#include "blend.h"
#include "span.h"
#include "updates.h"
#include "rgbadraw.h"
static void
__imlib_Ellipse_DrawToData(int xc, int yc, int a, int b, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
int xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
DATA32 a2, b2, *tp, *bp;
DATA64 dx, dy;
if (A_VAL(&color) == 0xff)
blend = 0;
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc)
return;
xc -= clx;
yc -= cly;
dst += (dstw * cly) + clx;
a2 = a*a; b2 = b*b;
yy = b << 16;
prev_y = b;
dx = a2 * b;
dy = 0;
ty = yc - b - 1;
by = yc + b;
lx = xc - 1;
rx = xc;
tp = dst + (dstw * ty) + lx;
bp = dst + (dstw * by) + lx;
while (dy < dx)
{
int len;
y = yy >> 16;
y += ((yy - (y << 16)) >> 15);
if (prev_y != y)
{
prev_y = y;
dx -= a2;
ty++; by--;
tp += dstw;
bp -= dstw;
}
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(color, tp);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(color, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(color, bp);
if (IN_RANGE(rx, by, clw, clh))
pfunc(color, bp + len);
dy += b2;
yy -= ((dy << 16) / dx);
lx--; rx++;
tp--; bp--;
if ( (lx < 0) && (rx > clw) )
return;
if ( (ty > clh) || (by < 0) )
return;
}
xx = yy;
prev_x = xx >> 16;
dx = dy;
ty++;
by--;
tp += dstw;
bp -= dstw;
while (ty < yc)
{
int len;
x = xx >> 16;
x += ((xx - (x << 16)) >> 15);
if (prev_x != x)
{
prev_x = x;
dy += b2;
lx--; rx++;
tp--; bp--;
}
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(color, tp);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(color, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(color, bp);
if (IN_RANGE(rx, by, clw, clh))
pfunc(color, bp + len);
dx -= a2;
xx += ((dx << 16) / dy);
ty++; by--;
tp += dstw;
bp -= dstw;
if ( (lx < 0) && (rx > clw) )
return;
if ( (ty > clh) || (by < 0) )
return;
}
}
static void
__imlib_Ellipse_DrawToData_AA(int xc, int yc, int a, int b, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
int xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
DATA32 a2, b2, col0, col1, *tp, *bp;
DATA64 dx, dy;
DATA8 ca = A_VAL(&color);
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc)
return;
xc -= clx;
yc -= cly;
dst += (dstw * cly) + clx;
col0 = col1 = color;
a2 = a*a; b2 = b*b;
yy = b << 16;
prev_y = b;
dx = a2 * b;
dy = 0;
ty = yc - b - 2;
by = yc + b + 1;
lx = xc - 1;
rx = xc;
tp = dst + (dstw * ty) + lx;
bp = dst + (dstw * by) + lx;
while (dy < dx)
{
int len;
DATA32 tmp;
y = yy >> 16;
if (prev_y != y)
{
prev_y = y;
dx -= a2;
ty++; by--;
tp += dstw;
bp -= dstw;
}
A_VAL(&col1) = (yy - (y << 16)) >> 8;
A_VAL(&col0) = 255 - A_VAL(&col1);
if (ca < 255)
{
MULT(A_VAL(&col0), ca, A_VAL(&col0), tmp)
MULT(A_VAL(&col1), ca, A_VAL(&col1), tmp)
}
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(col1, tp);
if (IN_RANGE(lx, ty + 1, clw, clh))
pfunc(col0, tp + dstw);
if (IN_RANGE(rx, ty + 1, clw, clh))
pfunc(col0, tp + dstw + len);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(col1, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(col1, bp);
if (IN_RANGE(lx, by - 1, clw, clh))
pfunc(col0, bp - dstw);
if (IN_RANGE(rx, by - 1, clw, clh))
pfunc(col0, bp - dstw + len);
if (IN_RANGE(rx, by, clw, clh))
pfunc(col1, bp + len);
dy += b2;
yy -= ((dy << 16) / dx);
lx--; rx++;
tp--; bp--;
if ( (lx < 0) && (rx > clw) )
return;
if ( (ty > clh) || (by < 0) )
return;
}
y = yy >> 16;
xx = yy;
prev_x = y;
dx = dy;
ty++;
by--;
tp += dstw;
bp -= dstw;
while (ty < yc)
{
int len;
DATA32 tmp;
x = xx >> 16;
if (prev_x != x)
{
prev_x = x;
dy += b2;
lx--; rx++;
tp--; bp--;
}
A_VAL(&col1) = (xx - (x << 16)) >> 8;
A_VAL(&col0) = 255 - A_VAL(&col1);
if (ca < 255)
{
MULT(A_VAL(&col0), ca, A_VAL(&col0), tmp)
MULT(A_VAL(&col1), ca, A_VAL(&col1), tmp)
}
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(col1, tp);
if (IN_RANGE(lx + 1, ty, clw, clh) && (x != y))
pfunc(col0, tp + 1);
if (IN_RANGE(rx - 1, ty, clw, clh) && (x != y))
pfunc(col0, tp + len - 1);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(col1, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(col1, bp);
if (IN_RANGE(lx + 1, by, clw, clh) && (x != y))
pfunc(col0, bp + 1);
if (IN_RANGE(rx - 1, by, clw, clh) && (x != y))
pfunc(col0, bp + len - 1);
if (IN_RANGE(rx, by, clw, clh))
pfunc(col1, bp + len);
dx -= a2;
xx += ((dx << 16) / dy);
ty++; by--;
tp += dstw;
bp -= dstw;
if ( (lx < 0) && (rx > clw) )
return;
if ( (ty > clh) || (by < 0) )
return;
}
}
static void
__imlib_Ellipse_FillToData(int xc, int yc, int a, int b, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
ImlibSpanDrawFunction sfunc;
int xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
DATA32 a2, b2, *tp, *bp;
DATA64 dx, dy;
if (A_VAL(&color) == 0xff)
blend = 0;
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
sfunc = __imlib_GetSpanDrawFunction(op, dst_alpha, blend);
if ((!sfunc) || (!pfunc))
return;
xc -= clx;
yc -= cly;
dst += (dstw * cly) + clx;
a2 = a*a; b2 = b*b;
yy = b << 16;
prev_y = b;
dx = a2 * b;
dy = 0;
ty = yc - b - 1;
by = yc + b;
lx = xc - 1;
rx = xc;
tp = dst + (dstw * ty) + lx;
bp = dst + (dstw * by) + lx;
while (dy < dx)
{
int len;
DATA32 *tpp, *bpp;
y = yy >> 16;
y += ((yy - (y << 16)) >> 15);
if (prev_y != y)
{
prev_y = y;
dx -= a2;
ty++; by--;
tp += dstw;
bp -= dstw;
tpp = tp + 1;
bpp = bp + 1;
len = rx;
if (len > clw) len = clw;
len -= (lx + 1);
if (lx < -1)
{
len += (lx + 1);
tpp -= (lx + 1);
bpp -= (lx + 1);
}
if ( ((unsigned)(ty) < clh) && (len > 0) )
sfunc(color, tpp, len);
if ( ((unsigned)(by) < clh) && (len > 0) )
sfunc(color, bpp, len);
}
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(color, tp);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(color, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(color, bp);
if (IN_RANGE(rx, by, clw, clh))
pfunc(color, bp + len);
dy += b2;
yy -= ((dy << 16) / dx);
lx--; rx++;
tp--; bp--;
}
xx = yy;
prev_x = xx >> 16;
dx = dy;
ty++;
by--;
tp += dstw;
bp -= dstw;
while (ty < yc)
{
int len;
DATA32 *tpp, *bpp;
x = xx >> 16;
x += ((xx - (x << 16)) >> 15);
if (prev_x != x)
{
prev_x = x;
dy += b2;
lx--; rx++;
tp--; bp--;
}
tpp = tp;
bpp = bp;
len = rx + 1;
if (len > clw) len = clw;
len -= lx;
if (lx < 0)
{
len += lx;
tpp -= lx;
bpp -= lx;
}
if ( ((unsigned)(ty) < clh) && (len > 0) )
sfunc(color, tpp, len);
if ( ((unsigned)(by) < clh) && (len > 0) )
sfunc(color, bpp, len);
dx -= a2;
xx += ((dx << 16) / dy);
ty++; by--;
tp += dstw;
bp -= dstw;
}
}
static void
__imlib_Ellipse_FillToData_AA(int xc, int yc, int a, int b, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
ImlibSpanDrawFunction sfunc;
int xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
DATA32 a2, b2, col1, *tp, *bp;
DATA64 dx, dy;
DATA8 ca = A_VAL(&color);
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (ca == 0xff)
blend = 0;
sfunc = __imlib_GetSpanDrawFunction(op, dst_alpha, blend);
if ((!pfunc) || (!sfunc))
return;
xc -= clx;
yc -= cly;
dst += (dstw * cly) + clx;
col1 = color;
a2 = a*a; b2 = b*b;
yy = b << 16;
prev_y = b;
dx = a2 * b;
dy = 0;
ty = yc - b - 2;
by = yc + b + 1;
lx = xc - 1;
rx = xc;
tp = dst + (dstw * ty) + lx;
bp = dst + (dstw * by) + lx;
while (dy < dx)
{
int len;
DATA32 tmp, *tpp, *bpp;
y = yy >> 16;
if (prev_y != y)
{
prev_y = y;
dx -= a2;
ty++; by--;
tp += dstw;
bp -= dstw;
tpp = tp + 1;
bpp = bp + 1;
len = rx;
if (len > clw) len = clw;
len -= (lx + 1);
if (lx < -1)
{
len += (lx + 1);
tpp -= (lx + 1);
bpp -= (lx + 1);
}
if ( ((unsigned)(ty) < clh) && (len > 0) )
sfunc(color, tpp, len);
if ( ((unsigned)(by) < clh) && (len > 0) )
sfunc(color, bpp, len);
}
A_VAL(&col1) = ((yy - (y << 16)) >> 8);
if (ca < 255)
MULT(A_VAL(&col1), ca, A_VAL(&col1), tmp)
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(col1, tp);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(col1, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(col1, bp);
if (IN_RANGE(rx, by, clw, clh))
pfunc(col1, bp + len);
dy += b2;
yy -= ((dy << 16) / dx);
lx--; rx++;
tp--; bp--;
}
y = yy >> 16;
xx = yy;
prev_x = y;
dx = dy;
ty++;
by--;
tp += dstw;
bp -= dstw;
while (ty < yc)
{
int len;
DATA32 tmp, *tpp, *bpp;
x = xx >> 16;
if (prev_x != x)
{
prev_x = x;
dy += b2;
lx--; rx++;
tp--; bp--;
}
tpp = tp + 1;
bpp = bp + 1;
len = rx;
if (len > clw) len = clw;
len -= (lx + 1);
if (lx < -1)
{
len += (lx + 1);
tpp -= (lx + 1);
bpp -= (lx + 1);
}
if ( ((unsigned)(ty) < clh) && (len > 0) )
sfunc(color, tpp, len);
if ( ((unsigned)(by) < clh) && (len > 0) )
sfunc(color, bpp, len);
A_VAL(&col1) = ((xx - (x << 16)) >> 8);
if (ca < 255)
MULT(A_VAL(&col1), ca, A_VAL(&col1), tmp)
len = rx - lx;
if (IN_RANGE(lx, ty, clw, clh))
pfunc(col1, tp);
if (IN_RANGE(rx, ty, clw, clh))
pfunc(col1, tp + len);
if (IN_RANGE(lx, by, clw, clh))
pfunc(col1, bp);
if (IN_RANGE(rx, by, clw, clh))
pfunc(col1, bp + len);
dx -= a2;
xx += ((dx << 16) / dy);
ty++; by--;
tp += dstw;
bp -= dstw;
}
}
void
__imlib_Ellipse_DrawToImage(int xc, int yc, int a, int b, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias)
{
int x, y, w, h;
if ((a == 0) || (b == 0))
{
(void) __imlib_Line_DrawToImage(xc - a, yc - b, xc + a, yc + b, color,
im, clx, cly, clw, clh,
op, blend, anti_alias, 0);
return;
}
if (blend && (!A_VAL(&color)))
return;
if (clw < 0)
return;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
if ((clw < 1) || (clh < 1))
return;
if (a < 0) a = -a;
if (b < 0) b = -b;
if (a > 65535) a = 65535;
if (b > 65535) b = 65535;
w = 2 * (a + 1);
h = 2 * (b + 1);
x = xc - a - 1;
y = yc - b - 1;
if (anti_alias)
{
w += 2; h += 2;
x--; y--;
}
CLIP_RECT_TO_RECT(x, y, w, h, clx, cly, clw, clh);
if ((w < 1) || (h < 1))
return;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
if (anti_alias)
__imlib_Ellipse_DrawToData_AA(xc, yc, a, b, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
else
__imlib_Ellipse_DrawToData(xc, yc, a, b, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
}
void
__imlib_Ellipse_FillToImage(int xc, int yc, int a, int b, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias)
{
int x, y, w, h;
if ((a == 0) || (b == 0))
{
(void) __imlib_Line_DrawToImage(xc - a, yc - b, xc + a, yc + b, color,
im, clx, cly, clw, clh,
op, blend, anti_alias, 0);
return;
}
if (blend && (!A_VAL(&color)))
return;
if (clw < 0)
return;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
if ((clw < 1) || (clh < 1))
return;
if (a < 0) a = -a;
if (b < 0) b = -b;
if (a > 65535) a = 65535;
if (b > 65535) b = 65535;
w = 2 * (a + 1);
h = 2 * (b + 1);
x = xc - a - 1;
y = yc - b - 1;
if (anti_alias)
{
w += 2; h += 2;
x--; y--;
}
CLIP_RECT_TO_RECT(x, y, w, h, clx, cly, clw, clh);
if ((w < 1) || (h < 1))
return;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
if (anti_alias)
__imlib_Ellipse_FillToData_AA(xc, yc, a, b, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
else
__imlib_Ellipse_FillToData(xc, yc, a, b, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
}

711
src/line.c Normal file
View File

@ -0,0 +1,711 @@
#include "common.h"
#include "colormod.h"
#include "image.h"
#include "blend.h"
#include "span.h"
#include "updates.h"
#include "rgbadraw.h"
#define EXCHANGE_POINTS(x0, y0, x1, y1) \
{ \
int _tmp = y0; \
\
y0 = y1; \
y1 = _tmp; \
\
_tmp = x0; \
x0 = x1; \
x1 = _tmp; \
}
ImlibUpdate *
__imlib_Point_DrawToImage(int x, int y, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char make_updates)
{
ImlibPointDrawFunction pfunc;
if (blend && (!A_VAL(&color)))
return NULL;
if (!IN_RANGE(x, y, im->w, im->h))
return NULL;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
if (!IN_RECT(x,y,clx,cly,clw,clh))
return NULL;
if (A_VAL(&color) == 0xff)
blend = 0;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
pfunc = __imlib_GetPointDrawFunction(op, IMAGE_HAS_ALPHA(im), blend);
if (pfunc)
pfunc(color, im->data + (im->w * y) + x);
if (make_updates)
return __imlib_AddUpdate(NULL, x, y, 1, 1);
return NULL;
}
static int
__imlib_SimpleLine_DrawToData(int x0, int y0, int x1, int y1, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
int *cl_x0, int *cl_y0, int *cl_x1, int *cl_y1,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
ImlibSpanDrawFunction sfunc;
int dx, dy, len, lx, ty, rx, by;
DATA32 *p;
if (A_VAL(&color) == 0xff) blend = 0;
if (y0 > y1)
EXCHANGE_POINTS(x0, y0, x1, y1)
dx = x1 - x0;
dy = y1 - y0;
lx = clx;
rx = clx + clw - 1;
ty = cly;
by = cly + clh - 1;
if ((x0 < lx) && (x1 < lx)) return 0;
if ((x0 > rx) && (x1 > rx)) return 0;
if ((y0 > by) || (y1 < ty)) return 0;
if (dy == 0)
{
sfunc = __imlib_GetSpanDrawFunction(op, dst_alpha, blend);
if (!sfunc) return 0;
if (dx < 0)
{
int tmp = x1;
x1 = x0;
x0 = tmp;
}
if (x0 < lx) x0 = lx;
if (x1 > rx) x1 = rx;
len = x1 - x0 + 1;
p = dst + (dstw * y0) + x0;
sfunc(color, p, len);
*cl_x0 = x0;
*cl_y0 = y0;
*cl_x1 = x1;
*cl_y1 = y1;
return 1;
}
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc) return 0;
if (dx == 0)
{
if (y0 < ty) y0 = ty;
if (y1 > by) y1 = by;
len = y1 - y0 + 1;
p = dst + (dstw * y0) + x0;
while (len--)
{
pfunc(color, p);
p += dstw;
}
*cl_x0 = x0;
*cl_y0 = y0;
*cl_x1 = x1;
*cl_y1 = y1;
return 1;
}
if ((dy == dx) || (dy == -dx))
{
int p0_in, p1_in;
p0_in = (IN_RECT(x0, y0, clx, cly, clw, clh) ? 1 : 0);
p1_in = (IN_RECT(x1, y1, clx, cly, clw, clh) ? 1 : 0);
if (dx > 0)
{
if (!p0_in)
{
x0 = x0 + (ty - y0);
y0 = ty;
if (x0 > rx) return 0;
if (x0 < lx)
{
y0 = y0 + (lx - x0);
x0 = lx;
if ((y0 < ty) || (y0 > by)) return 0;
}
}
if (!p1_in)
{
x1 = x0 + (by - y0);
y1 = by;
if (x1 < lx) return 0;
if (x1 > rx)
{
y1 = y0 + (rx - x0);
x1 = rx;
if ((y1 < ty) || (y1 > by)) return 0;
}
}
}
else
{
if (!p0_in)
{
x0 = x0 - (ty - y0);
y0 = ty;
if (x0 < lx) return 0;
if (x0 > rx)
{
y0 = y0 - (rx - x0);
x0 = rx;
if ((y0 < ty) || (y0 > by)) return 0;
}
}
if (!p1_in)
{
x1 = x0 - (by - y0);
y1 = by;
if (x1 > rx) return 0;
if (x1 < lx)
{
y1 = y0 - (lx - x0);
x1 = lx;
if ((y1 < ty) || (y1 > by)) return 0;
}
}
}
len = y1 - y0 + 1;
p = dst + (dstw * y0) + x0;
if (dx > 0) dstw++;
else dstw--;
while (len--)
{
pfunc(color, p);
p += dstw;
}
}
*cl_x0 = x0;
*cl_y0 = y0;
*cl_x1 = x1;
*cl_y1 = y1;
return 1;
}
#define SETUP_LINE_SHALLOW \
if (x0 > x1) \
{ \
EXCHANGE_POINTS(x0, y0, x1, y1) \
dx = -dx; \
dy = -dy; \
} \
\
px = x0; \
py = y0; \
\
p0_in = (IN_RANGE(x0 ,y0 , clw, clh) ? 1 : 0); \
p1_in = (IN_RANGE(x1 ,y1 , clw, clh) ? 1 : 0); \
\
dely = 1; \
dh = dstw; \
if (dy < 0) \
{ \
dely = -1; \
dh = -dstw; \
} \
\
dyy = (dy << 16) / dx; \
\
if (!p0_in) \
{ \
dxx = (dx << 16) / dy; \
if (px < 0) \
{ \
x = -px; px = 0; \
yy = x * dyy; \
y = yy >> 16; \
if (!a_a) \
y += (yy - (y << 16)) >> 15; \
py += y; \
if ((dely > 0) && (py >= clh)) \
return 0; \
else if ((dely < 0) && (py < -1)) \
return 0; \
} \
\
y = 0; \
if ((dely > 0) && (py < -1)) \
y = (-1 - py); \
else if ((dely < 0) && (py >= clh)) \
y = (clh - 1 - py); \
\
xx = y * dxx; \
x = xx >> 16; \
if (!a_a) \
x += (xx - (x << 16)) >> 15; \
px += x; \
if (px >= clw) return 0; \
\
yy = x * dyy; \
y = yy >> 16; \
if (!a_a) \
y += (yy - (y << 16)) >> 15; \
py += y; \
if ((dely > 0) && (py >= clh)) \
return 0; \
else if ((dely < 0) && (py < -1)) \
return 0; \
} \
\
p = dst + (dstw * py) + px; \
\
x = px - x0; \
yy = x * dyy; \
prev_y = (yy >> 16); \
\
rx = MIN(x1 + 1, clw); \
by = clh - 1;
#define SETUP_LINE_STEEP \
if (y0 > y1) \
{ \
EXCHANGE_POINTS(x0, y0, x1, y1) \
dx = -dx; \
dy = -dy; \
} \
\
px = x0; \
py = y0; \
\
p0_in = (IN_RANGE(x0 ,y0 , clw, clh) ? 1 : 0); \
p1_in = (IN_RANGE(x1 ,y1 , clw, clh) ? 1 : 0); \
\
delx = 1; \
if (dx < 0) \
delx = -1; \
\
dxx = (dx << 16) / dy; \
\
if (!p0_in) \
{ \
dyy = (dy << 16) / dx; \
\
if (py < 0) \
{ \
y = -py; py = 0; \
xx = y * dxx; \
x = xx >> 16; \
if (!a_a) \
x += (xx - (x << 16)) >> 15; \
px += x; \
if ((delx > 0) && (px >= clw)) \
return 0; \
else if ((delx < 0) && (px < -1)) \
return 0; \
} \
\
x = 0; \
if ((delx > 0) && (px < -1)) \
x = (-1 - px); \
else if ((delx < 0) && (px >= clw)) \
x = (clw - 1 - px); \
\
yy = x * dyy; \
y = yy >> 16; \
if (!a_a) \
y += (yy - (y << 16)) >> 15; \
py += y; \
if (py >= clh) return 0; \
\
xx = y * dxx; \
x = xx >> 16; \
if (!a_a) \
x += (xx - (x << 16)) >> 15; \
px += x; \
if ((delx > 0) && (px >= clw)) \
return 0; \
else if ((delx < 0) && (px < -1)) \
return 0; \
} \
\
p = dst + (dstw * py) + px; \
\
y = py - y0; \
xx = y * dxx; \
prev_x = (xx >> 16); \
\
by = MIN(y1 + 1, clh); \
rx = clw - 1;
static int
__imlib_Line_DrawToData(int x0, int y0, int x1, int y1, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
int *cl_x0, int *cl_y0, int *cl_x1, int *cl_y1,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
int px, py, x, y, prev_x, prev_y;
int dx, dy, rx, by, p0_in, p1_in, dh, a_a = 0;
int delx, dely, xx, yy, dxx, dyy;
DATA32 *p;
dx = x1 - x0;
dy = y1 - y0;
if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
return __imlib_SimpleLine_DrawToData(x0, y0, x1, y1, color,
dst, dstw, clx, cly, clw, clh,
cl_x0, cl_y0, cl_x1, cl_y1,
op, dst_alpha, blend);
if (A_VAL(&color) == 0xff) blend = 0;
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc) return 0;
dst += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW
*cl_x0 = px + clx;
*cl_y0 = py + cly;
while (px < rx)
{
y = (yy >> 16);
y += ((yy - (y << 16)) >> 15);
if (prev_y != y)
{
prev_y = y;
p += dh;
py += dely;
}
if (!p1_in)
{
if ((py < 0) && (dely < 0)) break;
if ((py > by) && (dely > 0)) break;
}
if (IN_RANGE(px, py, clw, clh))
pfunc(color, p);
yy += dyy;
px++;
p++;
}
*cl_x1 = px + clx;
*cl_y1 = py + cly;
return 1;
}
/* steep: y-parametric */
SETUP_LINE_STEEP
*cl_x0 = px + clx;
*cl_y0 = py + cly;
while (py < by)
{
x = (xx >> 16);
x += ((xx - (x << 16)) >> 15);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
}
if (!p1_in)
{
if ((px < 0) && (delx < 0)) break;
if ((px > rx) && (delx > 0)) break;
}
if (IN_RANGE(px, py, clw, clh))
pfunc(color, p);
xx += dxx;
py++;
p += dstw;
}
*cl_x1 = px + clx;
*cl_y1 = py + cly;
return 1;
}
static int
__imlib_Line_DrawToData_AA(int x0, int y0, int x1, int y1, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
int *cl_x0, int *cl_y0, int *cl_x1, int *cl_y1,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
int px, py, x, y, prev_x, prev_y;
int dx, dy, rx, by, p0_in, p1_in, dh, a_a = 1;
int delx, dely, xx, yy, dxx, dyy;
DATA32 *p;
DATA8 ca = A_VAL(&color);
dx = x1 - x0;
dy = y1 - y0;
if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
return __imlib_SimpleLine_DrawToData(x0, y0, x1, y1, color,
dst, dstw, clx, cly, clw, clh,
cl_x0, cl_y0, cl_x1, cl_y1,
op, dst_alpha, blend);
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc) return 0;
dst += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW
*cl_x0 = px + clx;
*cl_y0 = py + cly;
while (px < rx)
{
DATA32 tmp;
DATA8 aa;
y = (yy >> 16);
if (prev_y != y)
{
prev_y = y;
p += dh;
py += dely;
}
if (!p1_in)
{
if ((py < -1) && (dely < 0)) break;
if ((py > by) && (dely > 0)) break;
}
if ((unsigned)(px) < clw)
{
aa = (yy - (y << 16)) >> 8;
A_VAL(&color) = 255 - aa;
if (ca < 255)
MULT(A_VAL(&color), ca, A_VAL(&color), tmp)
if ((unsigned)(py) < clh)
pfunc(color, p);
if ((unsigned)(py + 1) < clh)
{
A_VAL(&color) = aa;
if (ca < 255)
MULT(A_VAL(&color), ca, A_VAL(&color), tmp)
pfunc(color, p + dstw);
}
}
yy += dyy;
px++;
p++;
}
*cl_x1 = px + clx;
*cl_y1 = py + cly;
return 1;
}
/* steep: y-parametric */
SETUP_LINE_STEEP
*cl_x0 = px + clx;
*cl_y0 = py + cly;
while (py < by)
{
DATA32 tmp;
DATA8 aa;
x = (xx >> 16);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
}
if (!p1_in)
{
if ((px < -1) && (delx < 0)) break;
if ((px > rx) && (delx > 0)) break;
}
if ((unsigned)(py) < clh)
{
aa = (xx - (x << 16)) >> 8;
A_VAL(&color) = 255 - aa;
if (ca < 255)
MULT(A_VAL(&color), ca, A_VAL(&color), tmp)
if ((unsigned)(px) < clw)
pfunc(color, p);
if ((unsigned)(px + 1) < clw)
{
A_VAL(&color) = aa;
if (ca < 255)
MULT(A_VAL(&color), ca, A_VAL(&color), tmp)
pfunc(color, p + 1);
}
}
xx += dxx;
py++;
p += dstw;
}
*cl_x1 = px + clx;
*cl_y1 = py + cly;
return 1;
}
ImlibUpdate *
__imlib_Line_DrawToImage(int x0, int y0, int x1, int y1, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias,
char make_updates)
{
int cl_x0, cl_y0, cl_x1, cl_y1, drew;
if ((x0 == x1) && (y0 == y1))
return __imlib_Point_DrawToImage(x0, y0, color,
im, clx, cly, clw, clh,
op, blend, make_updates);
if (blend && (!A_VAL(&color))) return NULL;
if (clw < 0) return NULL;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
if ((clw < 1) || (clh < 1))
return NULL;
if ((x0 < clx) && (x1 < clx)) return NULL;
if ((x0 >= (clx + clw)) && (x1 >= (clx + clw))) return NULL;
if ((y0 < cly) && (y1 < cly)) return NULL;
if ((y0 >= (cly + clh)) && (y1 >= (cly + clh))) return NULL;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
if (anti_alias)
drew = __imlib_Line_DrawToData_AA(x0, y0, x1, y1, color,
im->data, im->w, clx, cly, clw, clh,
&cl_x0, &cl_y0, &cl_x1, &cl_y1,
op, IMAGE_HAS_ALPHA(im), blend);
else
drew = __imlib_Line_DrawToData(x0, y0, x1, y1, color,
im->data, im->w, clx, cly, clw, clh,
&cl_x0, &cl_y0, &cl_x1, &cl_y1,
op, IMAGE_HAS_ALPHA(im), blend);
if (drew && make_updates)
{
int mi, ma, dx, dy, w, h;
mi = MIN(cl_x0, cl_x1);
ma = MAX(cl_x0, cl_x1);
cl_x0 = mi;
cl_x1 = ma;
dx = cl_x1 - cl_x0;
mi = MIN(cl_y0, cl_y1);
ma = MAX(cl_y0, cl_y1);
cl_y0 = mi;
cl_y1 = ma;
dy = cl_y1 - cl_y0;
w = dx + 1;
h = dy + 1;
if (anti_alias)
{
if ( ((cl_x1 + 1) < (clx + clw)) && (dy > dx) ) w++;
if ( ((cl_y1 + 1) < (cly + clh)) && (dx > dy) ) h++;
}
CLIP_RECT_TO_RECT(cl_x0, cl_y0, w, h, clx, cly, clw, clh);
if ((w < 1) || (h < 1))
return NULL;
return __imlib_AddUpdate(NULL, cl_x0, cl_y0, w, h);
}
return NULL;
}

1631
src/polygon.c Normal file

File diff suppressed because it is too large Load Diff

192
src/rectangle.c Normal file
View File

@ -0,0 +1,192 @@
#include "common.h"
#include "colormod.h"
#include "image.h"
#include "blend.h"
#include "span.h"
#include "updates.h"
#include "rgbadraw.h"
static void
__imlib_Rectangle_DrawToData(int x, int y, int rw, int rh, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibPointDrawFunction pfunc;
ImlibSpanDrawFunction sfunc;
int x0, y0, x1, y1, len;
DATA32 *p, *pp;
if (A_VAL(&color) == 0xff) blend = 0;
sfunc = __imlib_GetSpanDrawFunction(op, dst_alpha, blend);
pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
if (!pfunc || !sfunc)
return;
dst += (dstw * cly) + clx;
x -= clx;
y -= cly;
x0 = x;
x1 = x + rw - 1;
if (x0 < 0) x0 = 0;
if (x1 >= clw) x1 = clw - 1;
if (y >= 0)
{
p = dst + (dstw * y) + x0;
len = x1 - x0 + 1;
sfunc(color, p, len);
}
if ((y + rh) <= clh)
{
p = dst + (dstw * (y + rh - 1)) + x0;
len = x1 - x0 + 1;
sfunc(color, p, len);
}
y0 = y + 1;
y1 = y + rh - 2;
if (y0 < 0) y0 = 0;
if (y1 >= clh) y1 = clh - 1;
len = y1 - y0 + 1;
if (len <= 0) return;
y1 = len;
if (x >= 0)
{
p = dst + (dstw * y0) + x;
while (len--)
{
pfunc(color, p);
p += dstw;
}
}
if ((x + rw) <= clw)
{
len = y1;
p = dst + (dstw * y0) + x + rw - 1;
while (len--)
{
pfunc(color, p);
p += dstw;
}
}
}
static void
__imlib_Rectangle_FillToData(int x, int y, int rw, int rh, DATA32 color,
DATA32 *dst, int dstw, int clx, int cly, int clw, int clh,
ImlibOp op, char dst_alpha, char blend)
{
ImlibSpanDrawFunction sfunc;
DATA32 *p;
if (A_VAL(&color) == 0xff)
blend = 0;
sfunc = __imlib_GetSpanDrawFunction(op, dst_alpha, blend);
if (!sfunc) return;
dst += (dstw * cly) + clx;
x -= clx;
y -= cly;
CLIP_RECT_TO_RECT(x, y, rw, rh, 0, 0, clw, clh);
if ((rw < 1) || (rh < 1))
return;
p = dst + (dstw * y) + x;
while (rh--)
{
sfunc(color, p, rw);
p += dstw;
}
}
void
__imlib_Rectangle_DrawToImage(int x, int y, int w, int h, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend)
{
if ((w < 1) || (h < 1) || (clw < 0))
return;
if ((w == 1) || (h == 1))
{
(void) __imlib_Line_DrawToImage(x, y, x + w - 1, y + h - 1, color,
im, clx, cly, clw, clh,
op, blend, 0, 0);
return;
}
if (blend && (!A_VAL(&color)))
return;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
if ((clw < 1) || (clh < 1))
return;
CLIP_RECT_TO_RECT(clx, cly, clw, clh, x, y, w, h);
if ((clw < 1) || (clh < 1))
return;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
__imlib_Rectangle_DrawToData(x, y, w, h, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
}
void
__imlib_Rectangle_FillToImage(int x, int y, int w, int h, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend)
{
if ((w < 1) || (h < 1) || (clw < 0))
return;
if ((w == 1) || (h == 1))
{
(void) __imlib_Line_DrawToImage(x, y, x + w - 1, y + h - 1, color,
im, clx, cly, clw, clh,
op, blend, 0, 0);
return;
}
if (blend && (!A_VAL(&color)))
return;
if (clw == 0)
{
clw = im->w;
clx = 0;
clh = im->h;
cly = 0;
}
CLIP_RECT_TO_RECT(clx, cly, clw, clh, 0, 0, im->w, im->h);
if ((clw < 1) || (clh < 1))
return;
CLIP_RECT_TO_RECT(clx, cly, clw, clh, x, y, w, h);
if ((clw < 1) || (clh < 1))
return;
if (blend && IMAGE_HAS_ALPHA(im))
__imlib_build_pow_lut();
__imlib_Rectangle_FillToData(x, y, w, h, color,
im->data, im->w, clx, cly, clw, clh,
op, IMAGE_HAS_ALPHA(im), blend);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,100 +1,38 @@
#ifndef __RGBADRAW
#define __RGBADRAW 1
#define IN_SEGMENT(x, sx, sw) \
((unsigned)((x) - (sx)) < (sw))
#define GROW_BOUNDS(px1, py1, px2, py2, x, y) { \
if (x < px1) \
px1 = x; \
\
if (x > px2) \
px2 = x; \
\
if (y < py1) \
py1 = y; \
\
if (y > py2) \
py2 = y; \
#define IN_RANGE(x, y, w, h) \
( ((unsigned)(x) < (w)) && ((unsigned)(y) < (h)) )
#define IN_RECT(x, y, rx, ry, rw, rh) \
( ((unsigned)((x) - (rx)) < (rw)) && ((unsigned)((y) - (ry)) < (rh)) )
#define CLIP_RECT_TO_RECT(x, y, w, h, rx, ry, rw, rh) \
{ \
int _t0, _t1; \
\
_t0 = MAX(x, (rx)); \
_t1 = MIN(x + w, (rx) + (rw)); \
x = _t0; \
w = _t1 - _t0; \
_t0 = MAX(y, (ry)); \
_t1 = MIN(y + h, (ry) + (rh)); \
y = _t0; \
h = _t1 - _t0; \
}
#define exchange(type, a, b) \
{ \
type _t_; \
_t_ = a; \
a = b; \
b = _t_; \
#define DIV_255(a, x, tmp) \
{ \
tmp = (x) + 0x80; \
a = (tmp + (tmp >> 8)) >> 8; \
}
/* Check if p lies on segment [ s1, s2 ] given that
it lies on the line defined by s1 and s2. */
#define __imlib_point_inside_segment(p_x, p_y, s1_x, s1_y, s2_x,s2_y) \
(s1_y != s2_y) ? (p_y <= MAX(s1_y, s2_y) && p_y >= MIN(s1_y, s2_y)) : (p_x <= MAX(s1_x, s2_x) && p_x >= MIN(s1_x, s2_x))
#define MULT(na, a0, a1, tmp) \
DIV_255(na, (a0) * (a1), tmp)
#define __imlib_point_on_segment(p_x, p_y, s1_x, s1_y, s2_x, s2_y) \
__imlib_segments_intersect(p_x, p_y, p_x, p_y, s1_x, s1_y, s2_x, s2_y)
#define XY_IN_RECT(x, y, rx, ry, rw, rh) \
(((x) >= (rx)) && ((y) >= (ry)) && ((x) <= ((rx) + (rw))) && ((y) <= ((ry) + (rh))))
#define __imlib_draw_set_point(im, x, y, r, g, b, a, op) \
{ \
DATA32 *p; int tmp; \
if (XY_IN_RECT((x), (y), 0, 0, im->w, im->h)) { \
p = &(im->data[(im->w * (y)) + (x)]); \
switch (op) { \
case OP_RESHADE: \
BLEND_RE(r, g, b, a, p); \
break; \
case OP_SUBTRACT: \
BLEND_SUB(r, g, b, a, p); \
break; \
case OP_ADD: \
BLEND_ADD(r, g, b, a, p); \
break; \
case OP_COPY: \
BLEND(r, g, b, a, p); \
break; \
default: \
break; \
} \
} \
}
#define __imlib_draw_set_point_clipped(im, x, y, clip_xmin, clip_xmax, clip_ymin, clip_ymax, r, g, b, a, op) \
{ DATA32 *p; int tmp; \
if (XY_IN_RECT((x), (y), 0, 0, im->w, im->h)) \
{ \
if (XY_IN_RECT \
((x), (y), clip_xmin, clip_ymin, clip_xmax - clip_xmin, \
clip_ymax - clip_ymin)) \
{ \
p = &(im->data[(im->w * (y)) + (x)]); \
switch (op) \
{ \
case OP_RESHADE: \
BLEND_RE(r, g, b, a, p); \
break; \
case OP_SUBTRACT: \
BLEND_SUB(r, g, b, a, p); \
break; \
case OP_ADD: \
BLEND_ADD(r, g, b, a, p); \
break; \
case OP_COPY: \
BLEND(r, g, b, a, p); \
break; \
default: \
break; \
} \
} \
} \
}
typedef struct _edgerec
{
double x;
}
edgeRec;
typedef struct _imlib_point ImlibPoint;
@ -110,7 +48,6 @@ struct _imlib_rectangle
int x, y, w, h;
};
typedef struct _imlib_polygon _ImlibPoly;
typedef _ImlibPoly *ImlibPoly;
@ -118,18 +55,11 @@ struct _imlib_polygon
{
ImlibPoint *points;
int pointcount;
int lx, rx;
int ty, by;
};
void __imlib_polygon_free(ImlibPoly poly);
void __imlib_polygon_add_point(ImlibPoly poly, int x, int y);
ImlibPoly __imlib_polygon_new(void);
typedef unsigned int ImlibOutCode;
enum
{ TOP = 0x1, BOTTOM = 0x2, RIGHT = 0x4, LEFT = 0x8 };
#define TRUE 1
#define FALSE 0
/* image related operations: in rgbadraw.c */
void __imlib_FlipImageHoriz(ImlibImage * im);
void __imlib_FlipImageVert(ImlibImage * im);
@ -139,67 +69,73 @@ void __imlib_BlurImage(ImlibImage * im, int rad);
void __imlib_SharpenImage(ImlibImage * im, int rad);
void __imlib_TileImageHoriz(ImlibImage * im);
void __imlib_TileImageVert(ImlibImage * im);
ImlibUpdate *__imlib_draw_line(ImlibImage * im, int x1, int y1, int x2,
int y2, DATA8 r, DATA8 g, DATA8 b, DATA8 a,
ImlibOp op, char make_updates);
void __imlib_draw_box(ImlibImage * im, int x, int y, int w, int h, DATA8 r,
DATA8 g, DATA8 b, DATA8 a, ImlibOp op);
void __imlib_draw_filled_box(ImlibImage * im, int x, int y, int w, int h,
DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op);
void __imlib_draw_filled_box_clipped(ImlibImage * im, int x, int y, int w,
int h,
int clip_xmin, int clip_xmax, int clip_ymin,
int clip_ymax, DATA8 r, DATA8 g, DATA8 b,
DATA8 a, ImlibOp op);
void __imlib_copy_image_data(ImlibImage * im, int x, int y, int w, int h,
int nx, int ny);
void __imlib_copy_alpha_data(ImlibImage * src, ImlibImage * dst, int x, int y,
int w, int h, int nx, int ny);
ImlibOutCode __imlib_comp_outcode(double x, double y, double xmin,
double xmax, double ymin, double ymax);
void __imlib_draw_polygon(ImlibImage * im, ImlibPoly poly,
unsigned char closed, DATA8 r, DATA8 g, DATA8 b,
DATA8 a, ImlibOp op);
ImlibUpdate *__imlib_draw_line_clipped(ImlibImage * im, int x1, int y1,
int x2, int y2, int clip_xmin,
int clip_xmax, int clip_ymin,
int clip_ymax, DATA8 r, DATA8 g,
DATA8 b, DATA8 a, ImlibOp op,
char make_updates);
void __imlib_draw_box_clipped(ImlibImage * im, int x, int y, int w, int h,
int clip_xmin, int clip_xmax, int clip_ymin,
int clip_ymax, DATA8 r, DATA8 g, DATA8 b,
DATA8 a, ImlibOp op);
void __imlib_draw_polygon_clipped(ImlibImage * im, ImlibPoly poly,
unsigned char closed, int clip_xmin,
int clip_xmax, int clip_ymin, int clip_ymax,
DATA8 r, DATA8 g, DATA8 b, DATA8 a,
void __imlib_copy_image_data(ImlibImage * im, int x, int y, int w, int h,
int nx, int ny);
ImlibOp op);
void __imlib_polygon_get_bounds(ImlibPoly poly, int *px1, int *py1, int *px2,
int *py2);
void __imlib_draw_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb,
DATA8 r, DATA8 g, DATA8 b, DATA8 a, ImlibOp op);
void __imlib_draw_ellipse_clipped(ImlibImage * im, int xc, int yc, int aa,
int bb, int clip_xmin, int clip_xmax,
int clip_ymin, int clip_ymax, DATA8 r,
DATA8 g, DATA8 b, DATA8 a, ImlibOp op);
void __imlib_draw_polygon_filled(ImlibImage * im, ImlibPoly poly,
int clip_xmin, int clip_xmax, int clip_ymin,
int clip_ymax, DATA8 r, DATA8 g, DATA8 b,
DATA8 a, ImlibOp op, unsigned char antialias);
void __imlib_fill_ellipse(ImlibImage * im, int xc, int yc, int aa, int bb,
int clip_xmin, int clip_xmax, int clip_ymin,
int clip_ymax, DATA8 r, DATA8 g, DATA8 b, DATA8 a,
ImlibOp op, unsigned char antialias);
/* point and line drawing: in line.c */
ImlibUpdate *
__imlib_Point_DrawToImage(int x, int y, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char make_updates);
ImlibUpdate *
__imlib_Line_DrawToImage(int x0, int y0, int x1, int y1, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias,
char make_updates);
/* rectangle drawing and filling: in rectangle.c */
void
__imlib_Rectangle_DrawToImage(int xc, int yc, int w, int h, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend);
void
__imlib_Rectangle_FillToImage(int xc, int yc, int w, int h, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend);
/* ellipse drawing and filling: in ellipse.c */
void
__imlib_Ellipse_DrawToImage(int xc, int yc, int a, int b, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias);
void
__imlib_Ellipse_FillToImage(int xc, int yc, int a, int b, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias);
/* polygon handling functions: in polygon.c */
ImlibPoly __imlib_polygon_new(void);
void __imlib_polygon_free(ImlibPoly poly);
void __imlib_polygon_add_point(ImlibPoly poly, int x, int y);
unsigned char __imlib_polygon_contains_point(ImlibPoly poly, int x, int y);
unsigned char __imlib_segments_intersect(int r1_x, int r1_y, int r2_x,
int r2_y, int s1_x, int s1_y,
int s2_x, int s2_y);
double __imlib_point_delta_from_line(int p_x, int p_y, int s1_x, int s1_y,
int s2_x, int s2_y);
void __spanlist_clip(edgeRec * table1, edgeRec * table2, int *sy, int *ey,
int xmin, int xmax, int ymin, int ymax);
void __imlib_polygon_get_bounds(ImlibPoly poly, int *px1, int *py1, int *px2, int *py2);
/* polygon drawing and filling: in polygon.c */
void
__imlib_Polygon_DrawToImage(ImlibPoly poly, char closed, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias);
void
__imlib_Polygon_FillToImage(ImlibPoly poly, DATA32 color,
ImlibImage *im, int clx, int cly, int clw, int clh,
ImlibOp op, char blend, char anti_alias);
#endif

1160
src/span.c Normal file

File diff suppressed because it is too large Load Diff

24
src/span.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __SPAN
#define __SPAN 1
typedef void (*ImlibPointDrawFunction)(DATA32, DATA32 *);
ImlibPointDrawFunction
__imlib_GetPointDrawFunction(ImlibOp op, char dst_alpha, char blend);
typedef void (*ImlibSpanDrawFunction)(DATA32, DATA32 *, int);
ImlibSpanDrawFunction
__imlib_GetSpanDrawFunction(ImlibOp op, char dst_alpha, char blend);
typedef void (*ImlibShapedSpanDrawFunction)(DATA8 *, DATA32, DATA32 *, int);
ImlibShapedSpanDrawFunction
__imlib_GetShapedSpanDrawFunction(ImlibOp op, char dst_alpha, char blend);
#endif