efl/src/lib/evas/common/evas_line_main.c

1586 lines
44 KiB
C

#include "evas_common_private.h"
#include "evas_blend_private.h"
#define IN_RANGE(x, y, w, h) \
( x > 0 && y > 0 &&((unsigned)(x) < (unsigned)(w)) && ((unsigned)(y) < (unsigned)(h)) )
#define IN_RECT(x, y, rx, ry, rw, rh) \
( ((unsigned)((x) - (rx)) < (unsigned)(rw)) && \
((unsigned)((y) - (ry)) < (unsigned)(rh)) )
#define EXCHANGE_POINTS(x0, y0, x1, y1) \
{ \
int _tmp = y0; \
\
y0 = y1; \
y1 = _tmp; \
\
_tmp = x0; \
x0 = x1; \
x1 = _tmp; \
}
EAPI void
evas_common_line_init(void)
{
}
static void
_evas_draw_point(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y)
{
RGBA_Gfx_Pt_Func pfunc;
DATA8 *mask = NULL;
if (!dst->image.data) return;
if (!IN_RANGE(x, y, dst->cache_entry.w, dst->cache_entry.h))
return;
if ((dc->clip.use) && (!IN_RECT(x, y, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h)))
return;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_op_t op = PIXMAN_OP_SRC;
if (dc->render_op == _EVAS_RENDER_BLEND)
op = PIXMAN_OP_OVER;
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image, NULL,
dst->pixman.im, x, y, 0, 0, x, y, 1, 1);
else
# endif
#endif
{
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask = im->image.data8
+ (y - dc->clip.mask_y) * im->cache_entry.w
+ (x - dc->clip.mask_x);
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(dc->col.col, dst->cache_entry.flags.alpha, dc->render_op);
if (pfunc)
pfunc(0, *mask, dc->col.col, dst->image.data + (dst->cache_entry.w * y) + x);
}
else
{
pfunc = evas_common_gfx_func_composite_color_pt_get(dc->col.col, dst->cache_entry.flags.alpha, dc->render_op);
if (pfunc)
pfunc(0, 255, dc->col.col, dst->image.data + (dst->cache_entry.w * y) + x);
}
}
}
EAPI void
evas_common_line_point_draw(RGBA_Image *dst, int clip_x, int clip_y, int clip_w, int clip_h, DATA32 color, int render_op, int x, int y, RGBA_Image *mask_ie, int mask_x, int mask_y)
{
Eina_Bool no_cuse;
RGBA_Gfx_Pt_Func pfunc;
DATA8 *mask = NULL;
if (!dst->image.data) return;
no_cuse = ((clip_x == 0) && (clip_y == 0) &&
((clip_w == (int)dst->cache_entry.w) &&
(clip_h == (int)dst->cache_entry.h)));
if (!IN_RANGE(x, y, dst->cache_entry.w, dst->cache_entry.h)) return;
if ((!no_cuse) && (!IN_RECT(x, y, clip_x, clip_y, clip_w, clip_h)))
return;
if (mask_ie)
{
mask = mask_ie->image.data8
+ (y - mask_y) * mask_ie->cache_entry.w
+ (x - mask_x);
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
if (pfunc)
pfunc(0, *mask, color, dst->image.data + (dst->cache_entry.w * y) + x);
}
else
{
pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
if (pfunc)
pfunc(0, 255, color, dst->image.data + (dst->cache_entry.w * y) + x);
}
}
/*
these functions use the dc->clip data as bounding
data. they assume that such data has already been cut
back to lie in the dst image rect and the object's
(line) bounding rect.
*/
static void
_evas_draw_simple_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
{
int dx, dy, len, lx, ty, rx, by;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p, color;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
RGBA_Gfx_Func sfunc;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY
if (dc->render_op == _EVAS_RENDER_BLEND)
op = PIXMAN_OP_OVER;
# endif
#endif
dstw = dst->cache_entry.w;
color = dc->col.col;
if (y0 > y1)
EXCHANGE_POINTS(x0, y0, x1, y1)
if (x0 > x1)
EXCHANGE_POINTS(x0, y0, x1, y1)
dx = x1 - x0;
dy = y1 - y0;
clx = dc->clip.x;
cly = dc->clip.y;
clw = dc->clip.w;
clh = dc->clip.h;
lx = clx;
rx = clx + clw - 1;
ty = cly;
by = cly + clh - 1;
if (dy == 0)
{
if ((y0 >= ty) && (y0 <= by))
{
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->image.data + (dstw * y0) + x0;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
NULL, dst->pixman.im,
x0, y0, 0, 0, x0, y0, len, 1);
else
# endif
#endif
{
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask = im->image.data8
+ ((y0 - dc->clip.mask_y) * im->cache_entry.w)
+ (x0 - dc->clip.mask_x);
sfunc = evas_common_gfx_func_composite_mask_color_span_get(color, dst->cache_entry.flags.alpha, len, dc->render_op);
if (sfunc) sfunc(NULL, mask, color, p, len);
}
else
{
sfunc = evas_common_gfx_func_composite_color_span_get(color, dst->cache_entry.flags.alpha, len, dc->render_op);
if (sfunc)
sfunc(NULL, NULL, color, p, len);
}
}
}
return;
}
if (dc->clip.mask)
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, dc->render_op);
else
pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst->cache_entry.flags.alpha, dc->render_op);
if (!pfunc) return;
if (dx == 0)
{
if ((x0 >= lx) && (x0 <= rx))
{
if (y0 < ty) y0 = ty;
if (y1 > by) y1 = by;
len = y1 - y0 + 1;
p = dst->image.data + (dstw * y0) + x0;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
NULL, dst->pixman.im,
x0, y0, 0, 0, x0, y0, 1, len);
else
# endif
#endif
{
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask_w = im->cache_entry.w;
mask = im->image.data8
+ ((y0 - dc->clip.mask_y) * mask_w)
+ (x0 - dc->clip.mask_x);
while (len--)
{
pfunc(0, *mask, color, p);
p += dstw;
mask += mask_w;
}
}
else
{
while (len--)
{
pfunc(0, 255, color, p);
p += dstw;
}
}
}
}
return;
}
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 (dy > 0)
{
if (!p0_in)
{
x0 = x0 + (ty - y0);
y0 = ty;
if (x0 > rx) return;
if (x0 < lx)
{
y0 = y0 + (lx - x0);
x0 = lx;
if ((y0 < ty) || (y0 > by)) return;
}
}
if (!p1_in)
{
x1 = x0 + (by - y0);
y1 = by;
if (x1 < lx) return;
if (x1 > rx)
{
y1 = y0 + (rx - x0);
x1 = rx;
if ((y1 < ty) || (y1 > by)) return;
}
}
}
else
{
if (!p0_in)
{
x0 = x0 - (by - y0);
y0 = by;
if (x0 > rx) return;
if (x0 < lx)
{
y0 = y0 - (lx - x0);
x0 = lx;
if ((y0 < ty) || (y0 > by)) return;
}
}
if (!p1_in)
{
x1 = x0 - (ty - y0);
y1 = ty;
if (x1 < lx) return;
if (x1 > rx)
{
y1 = y0 - (rx - x0);
x1 = rx;
if ((y1 < ty) || (y1 > by)) return;
}
}
}
if (y1 > y0)
{
p = dst->image.data + (dstw * y0) + x0;
len = y1 - y0 + 1;
if (dx > 0) dstw++;
else dstw--;
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask_w = im->cache_entry.w;
mask = im->image.data8
+ ((y0 - dc->clip.mask_y) * mask_w)
+ (x0 - dc->clip.mask_x);
if (dx > 0) mask_w++;
else mask_w--;
}
}
else
{
len = y0 - y1 + 1;
p = dst->image.data + (dstw * y1) + x1;
if (dx > 0) dstw--;
else dstw++;
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask_w = im->cache_entry.w;
mask = im->image.data8
+ ((y1 - dc->clip.mask_y) * mask_w)
+ (x1 - dc->clip.mask_x);
if (dx > 0) mask_w--;
else mask_w++;
}
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
int pixman_x_position = x0;
int pixman_y_position = y0;
int x_unit = dstw - dst->cache_entry.w;
# endif
#endif
while (len--)
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
NULL, dst->pixman.im,
pixman_x_position,
pixman_y_position,
0, 0, pixman_x_position,
pixman_y_position, 1, 1);
else
# endif
#endif
{
if (mask)
{
pfunc(0, *mask, color, p);
mask += mask_w;
}
else
pfunc(0, 255, color, p);
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_x_position += x_unit;
pixman_y_position += 1;
# endif
#endif
p += dstw;
}
}
}
#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; \
else if ((dely < 0) && (py < -1)) \
return; \
} \
\
y = 0; \
if ((dely > 0) && (py < 0)) \
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; \
\
yy = x * dyy; \
y = yy >> 16; \
if (!a_a) \
y += (yy - (y << 16)) >> 15; \
py += y; \
if ((dely > 0) && (py >= clh)) \
return; \
else if ((dely < 0) && (py < -1)) \
return; \
} \
\
p = data + (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; \
else if ((delx < 0) && (px < -1)) \
return; \
} \
\
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; \
\
xx = y * dxx; \
x = xx >> 16; \
if (!a_a) \
x += (xx - (x << 16)) >> 15; \
px += x; \
if ((delx > 0) && (px >= clw)) \
return; \
else if ((delx < 0) && (px < -1)) \
return; \
} \
\
p = data + (dstw * py) + px; \
\
y = py - y0; \
xx = y * dxx; \
prev_x = (xx >> 16); \
\
by = MIN(y1 + 1, clh); \
rx = clw - 1;
static void
_draw_render_thread_simple_line(RGBA_Image *dst, int clip_x, int clip_y, int clip_w, int clip_h, DATA32 color, int render_op, int x0, int y0, int x1, int y1, RGBA_Image *mask_ie, int mask_x, int mask_y)
{
int dx, dy, len, lx, ty, rx, by;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
RGBA_Gfx_Func sfunc;
dstw = dst->cache_entry.w;
if (y0 > y1)
EXCHANGE_POINTS(x0, y0, x1, y1)
if (x0 > x1)
EXCHANGE_POINTS(x0, y0, x1, y1)
dx = x1 - x0;
dy = y1 - y0;
clx = clip_x;
cly = clip_y;
clw = clip_w;
clh = clip_h;
lx = clx;
rx = clx + clw - 1;
ty = cly;
by = cly + clh - 1;
if (dy == 0)
{
if ((y0 >= ty) && (y0 <= by))
{
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->image.data + (dstw * y0) + x0;
if (mask_ie)
{
mask = mask_ie->image.data8
+ ((y0 - mask_y) * mask_ie->cache_entry.w)
+ (x0 - mask_x);
sfunc = evas_common_gfx_func_composite_mask_color_span_get(color, dst->cache_entry.flags.alpha, len, render_op);
if (sfunc) sfunc(NULL, mask, color, p, len);
}
else
{
sfunc = evas_common_gfx_func_composite_color_span_get(color, dst->cache_entry.flags.alpha, len, render_op);
if (sfunc) sfunc(NULL, NULL, color, p, len);
}
}
return;
}
if (mask_ie)
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
else
pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
if (!pfunc) return;
if (dx == 0)
{
if ((x0 >= lx) && (x0 <= rx))
{
if (y0 < ty) y0 = ty;
if (y1 > by) y1 = by;
len = y1 - y0 + 1;
p = dst->image.data + (dstw * y0) + x0;
if (mask_ie)
{
mask_w = mask_ie->cache_entry.w;
mask = mask_ie->image.data8
+ ((y0 - mask_y) * mask_w)
+ (x0 - mask_x);
while (len--)
{
pfunc(0, *mask, color, p);
p += dstw;
mask += mask_w;
}
}
else
{
while (len--)
{
pfunc(0, 255, color, p);
p += dstw;
}
}
}
return;
}
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 (dy > 0)
{
if (!p0_in)
{
x0 = x0 + (ty - y0);
y0 = ty;
if (x0 > rx) return;
if (x0 < lx)
{
y0 = y0 + (lx - x0);
x0 = lx;
if ((y0 < ty) || (y0 > by)) return;
}
}
if (!p1_in)
{
x1 = x0 + (by - y0);
y1 = by;
if (x1 < lx) return;
if (x1 > rx)
{
y1 = y0 + (rx - x0);
x1 = rx;
if ((y1 < ty) || (y1 > by)) return;
}
}
}
else
{
if (!p0_in)
{
x0 = x0 - (by - y0);
y0 = by;
if (x0 > rx) return;
if (x0 < lx)
{
y0 = y0 - (lx - x0);
x0 = lx;
if ((y0 < ty) || (y0 > by)) return;
}
}
if (!p1_in)
{
x1 = x0 - (ty - y0);
y1 = ty;
if (x1 < lx) return;
if (x1 > rx)
{
y1 = y0 - (rx - x0);
x1 = rx;
if ((y1 < ty) || (y1 > by)) return;
}
}
}
if (y1 > y0)
{
p = dst->image.data + (dstw * y0) + x0;
len = y1 - y0 + 1;
if (dx > 0) dstw++;
else dstw--;
if (mask_ie)
{
mask_w = mask_ie->cache_entry.w;
mask = mask_ie->image.data8
+ ((y0 - mask_y) * mask_w)
+ (x0 - mask_x);
if (dx > 0) mask_w++;
else mask_w--;
}
}
else
{
len = y0 - y1 + 1;
p = dst->image.data + (dstw * y1) + x1;
if (dx > 0) dstw--;
else dstw++;
if (mask_ie)
{
mask_w = mask_ie->cache_entry.w;
mask = mask_ie->image.data8
+ ((y1 - mask_y) * mask_w)
+ (x1 - mask_x);
if (dx > 0) mask_w--;
else mask_w++;
}
}
if (mask)
{
while (len--)
{
pfunc(0, *mask, color, p);
p += dstw;
mask += mask_w;
}
}
else
{
while (len--)
{
pfunc(0, 255, color, p);
p += dstw;
}
}
}
}
EAPI void
evas_common_line_draw_line(RGBA_Image *dst, int clip_x, int clip_y, int clip_w, int clip_h, DATA32 color, int render_op, int x0, int y0, int x1, int y1, RGBA_Image *mask_ie, int mask_x, int mask_y)
{
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;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p, *data;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
dx = x1 - x0;
dy = y1 - y0;
if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
{
_draw_render_thread_simple_line
(dst, clip_x, clip_y, clip_w, clip_h,
color, render_op,
x0, y0, x1, y1,
mask_ie, mask_x, mask_y);
return;
}
if (mask_ie)
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
else
pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
if (!pfunc) return;
clx = clip_x;
cly = clip_y;
clw = clip_w;
clh = clip_h;
data = dst->image.data;
dstw = dst->cache_entry.w;
data += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
if (mask_ie)
{
mask_w = mask_ie->cache_entry.w;
mask = mask_ie->image.data8
+ ((cly - mask_y) * mask_w) + (clx - mask_x);
}
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW;
if (mask) mask += (py * mask_w) + px;
while (px < rx)
{
y = (yy >> 16);
y += ((yy - (y << 16)) >> 15);
if (prev_y != y)
{
prev_y = y;
p += dh;
if (mask) mask += mask_w;
py += dely;
}
if (!p1_in)
{
if ((py < 0) && (dely < 0)) return;
if ((py > by) && (dely > 0)) return;
}
if (!p0_in)
{
if (py < 0) goto next_x;
}
if (IN_RANGE(px, py, clw, clh))
{
if (mask) pfunc(0, *mask, color, p);
else pfunc(0, 255, color, p);
}
next_x:
yy += dyy;
px++;
p++;
if (mask) mask++;
}
return;
}
/* steep: y-parametric */
SETUP_LINE_STEEP;
if (mask) mask += (py * mask_w) + px;
while (py < by)
{
x = (xx >> 16);
x += ((xx - (x << 16)) >> 15);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
if (mask) mask += delx;
}
if (!p1_in)
{
if ((px < 0) && (delx < 0)) return;
if ((px > rx) && (delx > 0)) return;
}
if (!p0_in)
{
if (px < 0) goto next_y;
}
if (IN_RANGE(px, py, clw, clh))
{
if (mask) pfunc(0, *mask, color, p);
else pfunc(0, 255, color, p);
}
next_y:
xx += dxx;
py++;
p += dstw;
if (mask) mask += mask_w;
}
}
static void
_evas_draw_line(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
{
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;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p, *data, color;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
dx = x1 - x0;
dy = y1 - y0;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
int pix_x;
int pix_y;
int pix_x_unit;
int pix_y_unit;
pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY
if (dc->render_op == _EVAS_RENDER_BLEND)
op = PIXMAN_OP_OVER;
pix_x = x0;
pix_y = y0;
if (dx < 0)
pix_x_unit = -1;
else
pix_x_unit = 1;
if (dy < 0)
pix_y_unit = -1;
else
pix_y_unit = 1;
# endif
#endif
if ( (dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy) )
{
_evas_draw_simple_line(dst, dc, x0, y0, x1, y1);
return;
}
color = dc->col.col;
if (dc->clip.mask)
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, dc->render_op);
else
pfunc = evas_common_gfx_func_composite_color_pt_get(color, dst->cache_entry.flags.alpha, dc->render_op);
if (!pfunc) return;
clx = dc->clip.x;
cly = dc->clip.y;
clw = dc->clip.w;
clh = dc->clip.h;
data = dst->image.data;
dstw = dst->cache_entry.w;
data += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask_w = im->cache_entry.w;
mask = im->image.data8
+ ((cly - dc->clip.mask_y) * mask_w) + (clx - dc->clip.mask_x);
}
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW;
if (mask) mask += (py * mask_w) + px;
while (px < rx)
{
y = (yy >> 16);
y += ((yy - (y << 16)) >> 15);
if (prev_y != y)
{
prev_y = y;
p += dh;
if (mask) mask += mask_w;
py += dely;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_y += pix_y_unit;
# endif
#endif
}
if (!p1_in)
{
if ((py < 0) && (dely < 0)) return;
if ((py > by) && (dely > 0)) return;
}
if (!p0_in)
{
if (py < 0) goto next_x;
}
if (IN_RANGE(px, py, clw, clh))
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
NULL, dst->pixman.im,
pix_x, pix_y, 0, 0,
pix_x, pix_y, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, *mask, color, p);
else pfunc(0, 255, color, p);
}
}
next_x:
yy += dyy;
px++;
p++;
if (mask) mask++;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_x += pix_x_unit;
# endif
#endif
}
return;
}
/* steep: y-parametric */
SETUP_LINE_STEEP;
if (mask) mask += (py * mask_w) + px;
while (py < by)
{
x = (xx >> 16);
x += ((xx - (x << 16)) >> 15);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
if (mask) mask += delx;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_x += pix_x_unit;
# endif
#endif
}
if (!p1_in)
{
if ((px < 0) && (delx < 0)) return;
if ((px > rx) && (delx > 0)) return;
}
if (!p0_in)
{
if (px < 0) goto next_y;
}
if (IN_RANGE(px, py, clw, clh))
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
NULL, dst->pixman.im,
pix_x, pix_y, 0, 0,
pix_x, pix_y, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, *mask, color, p);
else pfunc(0, 255, color, p);
}
}
next_y:
xx += dxx;
py++;
p += dstw;
if (mask) mask += mask_w;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_y += pix_y_unit;
# endif
#endif
}
}
EAPI void
evas_common_line_draw_line_aa(RGBA_Image *dst, int clip_x, int clip_y, int clip_w, int clip_h, DATA32 color, int render_op, int x0, int y0, int x1, int y1, RGBA_Image *mask_ie, int mask_x, int mask_y)
{
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;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p, *data;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
dx = x1 - x0;
dy = y1 - y0;
if (y0 > y1)
EXCHANGE_POINTS(x0, y0, x1, y1);
dx = x1 - x0;
dy = y1 - y0;
if ((dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy))
{
_draw_render_thread_simple_line
(dst, clip_x, clip_y, clip_w, clip_h,
color, render_op,
x0, y0, x1, y1,
mask_ie, mask_x, mask_y);
return;
}
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, render_op);
if (!pfunc) return;
clx = clip_x;
cly = clip_y;
clw = clip_w;
clh = clip_h;
data = evas_cache_image_pixels(&dst->cache_entry);
dstw = dst->cache_entry.w;
data += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
if (mask_ie)
{
mask_w = mask_ie->cache_entry.w;
mask = mask_ie->image.data8
+ (cly - mask_y) * mask_w + (clx - mask_x);
}
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW;
if (mask) mask += (py * mask_w) + px;
while (px < rx)
{
DATA8 aa;
y = (yy >> 16);
if (prev_y != y)
{
prev_y = y;
p += dh;
if (mask) mask += mask_w;
py += dely;
}
if (!p1_in)
{
if ((py < 0) && (dely < 0)) return;
if ((py > by) && (dely > 0)) return;
}
if (!p0_in)
{
if (py < 0) goto next_x;
}
if (px < clw)
{
aa = ((yy - (y << 16)) >> 8);
if (mask)
{
if ((py) < clh) pfunc(0, (255 - aa) * (*mask) / 255, color, p);
if ((py + 1) < clh) pfunc(0, aa * (*(mask + mask_w)) / 255, color, p + dstw);
}
else
{
if ((py) < clh) pfunc(0, 255 - aa, color, p);
if ((py + 1) < clh) pfunc(0, aa, color, p + dstw);
}
}
next_x:
yy += dyy;
px++;
p++;
if (mask) mask++;
}
return;
}
/* steep: y-parametric */
SETUP_LINE_STEEP;
if (mask) mask += (py * mask_w) + px;
while (py < by)
{
DATA8 aa;
x = (xx >> 16);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
if (mask) mask += delx;
}
if (!p1_in)
{
if ((px < 0) && (delx < 0)) return;
if ((px > rx) && (delx > 0)) return;
}
if (!p0_in)
{
if (px < 0) goto next_y;
}
if (py < clh)
{
aa = ((xx - (x << 16)) >> 8);
if (mask)
{
if ((px) < clw) pfunc(0, (255 - aa) * (*mask) / 255, color, p);
if ((px + 1) < clw) pfunc(0, aa * (*(mask + 1)) / 255, color, p + 1);
}
else
{
if ((px) < clw) pfunc(0, 255 - aa, color, p);
if ((px + 1) < clw) pfunc(0, aa, color, p + 1);
}
}
next_y:
xx += dxx;
py++;
p += dstw;
if (mask) mask += mask_w;
}
}
static void
_evas_draw_line_aa(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
{
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;
int clx, cly, clw, clh;
int dstw, mask_w = 0;
DATA32 *p, *data, color;
DATA8 *mask = NULL;
RGBA_Gfx_Pt_Func pfunc;
dx = x1 - x0;
dy = y1 - y0;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
int pix_x;
int pix_y;
int pix_x_unit;
int pix_y_unit;
pixman_image_t *aa_mask_image;
int alpha_data_buffer;
pixman_op_t op = PIXMAN_OP_SRC; // _EVAS_RENDER_COPY
if (dc->render_op == _EVAS_RENDER_BLEND)
op = PIXMAN_OP_OVER;
pix_x = x0;
pix_y = y0;
if (dx < 0)
pix_x_unit = -1;
else
pix_x_unit = 1;
if (dy < 0)
pix_y_unit = -1;
else
pix_y_unit = 1;
# endif
#endif
if (y0 > y1)
EXCHANGE_POINTS(x0, y0, x1, y1);
dx = x1 - x0;
dy = y1 - y0;
if ((dx == 0) || (dy == 0) || (dx == dy) || (dx == -dy))
{
_evas_draw_simple_line(dst, dc, x0, y0, x1, y1);
return;
}
color = dc->col.col;
pfunc = evas_common_gfx_func_composite_mask_color_pt_get(color, dst->cache_entry.flags.alpha, dc->render_op);
if (!pfunc) return;
clx = dc->clip.x;
cly = dc->clip.y;
clw = dc->clip.w;
clh = dc->clip.h;
data = evas_cache_image_pixels(&dst->cache_entry);
dstw = dst->cache_entry.w;
data += (dstw * cly) + clx;
x0 -= clx;
y0 -= cly;
x1 -= clx;
y1 -= cly;
if (dc->clip.mask)
{
RGBA_Image *im = dc->clip.mask;
mask_w = im->cache_entry.w;
mask = im->image.data8
+ ((cly - dc->clip.mask_y) * mask_w) + (clx - dc->clip.mask_x);
}
/* shallow: x-parametric */
if ((dy < dx) || (dy < -dx))
{
SETUP_LINE_SHALLOW;
if (mask) mask += (py * mask_w) + px;
while (px < rx)
{
DATA8 aa;
y = (yy >> 16);
if (prev_y != y)
{
prev_y = y;
p += dh;
if (mask) mask += mask_w;
py += dely;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_y += pix_y_unit;
# endif
#endif
}
if (!p1_in)
{
if ((py < 0) && (dely < 0)) return;
if ((py > by) && (dely > 0)) return;
}
if (!p0_in)
{
if (py < 0) goto next_x;
}
if (px < clw)
{
aa = ((yy - (y << 16)) >> 8);
if ((py) < clh)
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
alpha_data_buffer = 255 - aa;
aa_mask_image = pixman_image_create_bits(PIXMAN_a8, 1, 1,
(uint32_t *)&alpha_data_buffer, 4);
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
aa_mask_image, dst->pixman.im,
pix_x, pix_y, 0, 0,
pix_x, pix_y, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, (255 - aa) * (*mask) / 255, color, p);
else pfunc(0, 255 - aa, color, p);
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_image_unref(aa_mask_image);
# endif
#endif
}
if ((py + 1) < clh)
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
alpha_data_buffer = aa;
aa_mask_image = pixman_image_create_bits(PIXMAN_a8, 1, 1,
(uint32_t *)&alpha_data_buffer, 4);
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
aa_mask_image, dst->pixman.im,
pix_x, pix_y + 1, 0, 0,
pix_x, pix_y + 1, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, aa * (*(mask + mask_w)) / 255, color, p + dstw);
else pfunc(0, aa, color, p + dstw);
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_image_unref(aa_mask_image);
# endif
#endif
}
}
next_x:
yy += dyy;
px++;
p++;
if (mask) mask++;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_x += pix_x_unit;
# endif
#endif
}
return;
}
/* steep: y-parametric */
SETUP_LINE_STEEP;
if (mask) mask += (py * mask_w) + px;
while (py < by)
{
DATA8 aa;
x = (xx >> 16);
if (prev_x != x)
{
prev_x = x;
px += delx;
p += delx;
if (mask) mask += delx;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_x += pix_x_unit;
# endif
#endif
}
if (!p1_in)
{
if ((px < 0) && (delx < 0)) return;
if ((px > rx) && (delx > 0)) return;
}
if (!p0_in)
{
if (px < 0) goto next_y;
}
if (py < clh)
{
aa = ((xx - (x << 16)) >> 8);
if ((px) < clw)
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
alpha_data_buffer = 255 - aa;
aa_mask_image = pixman_image_create_bits(PIXMAN_a8, 1, 1, (uint32_t *)&alpha_data_buffer, 4);
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
aa_mask_image, dst->pixman.im,
pix_x, pix_y, 0, 0,
pix_x, pix_y, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, (255 - aa) * (*mask) / 255, color, p);
else pfunc(0, 255 - aa, color, p);
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_image_unref(aa_mask_image);
# endif
#endif
}
if ((px + 1) < clw)
{
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
alpha_data_buffer = aa;
aa_mask_image = pixman_image_create_bits(PIXMAN_a8, 1, 1,
(uint32_t *)&alpha_data_buffer, 4);
if ((dst->pixman.im) && (dc->col.pixman_color_image))
pixman_image_composite(op, dc->col.pixman_color_image,
aa_mask_image, dst->pixman.im,
pix_x + 1, pix_y, 0, 0,
pix_x + 1, pix_y, 1, 1);
else
# endif
#endif
{
if (mask) pfunc(0, aa * (*(mask + 1)) / 255, color, p + 1);
else pfunc(0, aa, color, p + 1);
}
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pixman_image_unref(aa_mask_image);
# endif
#endif
}
}
next_y:
xx += dxx;
py++;
p += dstw;
if (mask) mask += mask_w;
#ifdef HAVE_PIXMAN
# ifdef PIXMAN_LINE
pix_y += pix_y_unit;
# endif
#endif
}
}
EAPI void
evas_common_line_draw_cb(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1, Evas_Common_Line_Draw_Cb cb)
{
int x, y, w, h;
int clx, cly, clw, clh;
int cuse, cx, cy, cw, ch;
/* No cutout ? FIXME ? */
if ((x0 == x1) && (y0 == y1))
{
_evas_draw_point(dst, dc, x0, y0);
return;
}
clx = cly = 0;
clw = dst->cache_entry.w;
clh = dst->cache_entry.h;
/* save out clip info */
cuse = dc->clip.use;
cx = dc->clip.x;
cy = dc->clip.y;
cw = dc->clip.w;
ch = dc->clip.h;
if (cuse)
{
RECTS_CLIP_TO_RECT(clx, cly, clw, clh, cx, cy, cw, ch);
if ((clw < 1) || (clh < 1))
return;
}
x = MIN(x0, x1);
y = MIN(y0, y1);
w = MAX(x0, x1) - x + 1;
h = MAX(y0, y1) - y + 1;
RECTS_CLIP_TO_RECT(clx, cly, clw, clh, x, y, w, h);
if ((clw < 1) || (clh < 1))
return;
dc->clip.use = 1;
dc->clip.x = clx;
dc->clip.y = cly;
dc->clip.w = clw;
dc->clip.h = clh;
cb(dst, dc, x0, y0, x1, y1);
/* restore clip info */
dc->clip.use = cuse;
dc->clip.x = cx;
dc->clip.y = cy;
dc->clip.w = cw;
dc->clip.h = ch;
}
EAPI void
evas_common_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
{
Evas_Common_Line_Draw_Cb cb;
if (dc->anti_alias) cb = _evas_draw_line_aa;
else cb = _evas_draw_line;
evas_common_line_draw_cb(dst, dc, x0, y0, x1, y1, cb);
}