/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- __imlib_Point_DrawToImage
- __imlib_SimpleLine_DrawToData
- __imlib_Line_DrawToData
- __imlib_Line_DrawToData_AA
- __imlib_Line_DrawToImage
#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) \
do { \
int _tmp = y0; \
\
y0 = y1; \
y1 = _tmp; \
\
_tmp = x0; \
x0 = x1; \
x1 = _tmp; \
} while (0)
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() \
do { \
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; \
} while (0)
#define SETUP_LINE_STEEP() \
do { \
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; \
} while (0)
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 (abs(dy) < abs(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 (abs(dy) < abs(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;
}