forked from enlightenment/efl
446 lines
8.8 KiB
C
446 lines
8.8 KiB
C
#include "evas_common_soft16.h"
|
|
#include "evas_soft16_scanline_fill.c"
|
|
|
|
/*
|
|
* All functions except by evas_common_soft16_line_draw() expect x0 <= x1.
|
|
*/
|
|
|
|
static inline int
|
|
_in_range(int value, int min, int max)
|
|
{
|
|
return min <= value && value <= max;
|
|
}
|
|
|
|
static inline int
|
|
_is_xy_inside_clip(int x, int y, const struct RGBA_Draw_Context_clip clip)
|
|
{
|
|
if (!clip.use)
|
|
return 1;
|
|
|
|
if (!_in_range(x, clip.x, clip.x + clip.w - 1))
|
|
return 0;
|
|
|
|
if (!_in_range(y, clip.y, clip.y + clip.h - 1))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int
|
|
_is_x_inside_clip(int x, const struct RGBA_Draw_Context_clip clip)
|
|
{
|
|
if (!clip.use)
|
|
return 1;
|
|
|
|
return _in_range(x, clip.x, clip.x + clip.w - 1);
|
|
}
|
|
|
|
static inline int
|
|
_is_y_inside_clip(int y, const struct RGBA_Draw_Context_clip clip)
|
|
{
|
|
if (!clip.use)
|
|
return 1;
|
|
|
|
return _in_range(y, clip.y, clip.y + clip.h - 1);
|
|
}
|
|
|
|
static inline int
|
|
_is_xy_inside_rect(int x, int y, int w, int h)
|
|
{
|
|
return _in_range(x, 0, w - 1) && _in_range(y, 0, h - 1);
|
|
}
|
|
|
|
static inline int
|
|
_is_empty_clip(const struct RGBA_Draw_Context_clip clip)
|
|
{
|
|
return clip.w < 1 || clip.h < 1;
|
|
}
|
|
|
|
static void
|
|
_soft16_line_point(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y)
|
|
{
|
|
DATA16 rgb565, *dst_itr;
|
|
DATA8 alpha;
|
|
|
|
if (!_is_xy_inside_rect(x, y, dst->cache_entry.w, dst->cache_entry.h))
|
|
return;
|
|
|
|
if (!_is_xy_inside_clip(x, y, dc->clip))
|
|
return;
|
|
|
|
dst_itr = dst->pixels + (dst->stride * y) + x;
|
|
alpha = A_VAL(&dc->col.col) >> 3;
|
|
rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
|
|
G_VAL(&dc->col.col),
|
|
B_VAL(&dc->col.col));
|
|
|
|
if (alpha == 31)
|
|
_soft16_pt_fill_solid_solid(dst_itr, rgb565);
|
|
else if (alpha > 0)
|
|
{
|
|
DATA32 rgb565_unpack;
|
|
|
|
rgb565_unpack = RGB_565_UNPACK(rgb565);
|
|
alpha++;
|
|
_soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_soft16_line_horiz(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int x1, int y)
|
|
{
|
|
DATA16 rgb565, *dst_itr;
|
|
DATA8 alpha;
|
|
int w;
|
|
|
|
if (!_is_y_inside_clip(y, dc->clip))
|
|
return;
|
|
|
|
if (x0 < dc->clip.x)
|
|
x0 = dc->clip.x;
|
|
|
|
if (x1 >= dc->clip.x + dc->clip.w)
|
|
x1 = dc->clip.x + dc->clip.w - 1;
|
|
|
|
w = x1 - x0;
|
|
if (w < 1)
|
|
return;
|
|
|
|
dst_itr = dst->pixels + (dst->stride * y) + x0;
|
|
alpha = A_VAL(&dc->col.col) >> 3;
|
|
rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
|
|
G_VAL(&dc->col.col),
|
|
B_VAL(&dc->col.col));
|
|
|
|
if (alpha == 31)
|
|
_soft16_scanline_fill_solid_solid(dst_itr, w, rgb565);
|
|
else if (alpha > 0)
|
|
{
|
|
DATA32 rgb565_unpack;
|
|
|
|
rgb565_unpack = RGB_565_UNPACK(rgb565);
|
|
alpha++;
|
|
_soft16_scanline_fill_transp_solid(dst_itr, w, rgb565_unpack, alpha);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_soft16_line_vert(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y0, int y1)
|
|
{
|
|
DATA16 rgb565, *dst_itr;
|
|
DATA8 alpha;
|
|
int h;
|
|
|
|
if (!_is_x_inside_clip(x, dc->clip))
|
|
return;
|
|
|
|
if (y1 < y0)
|
|
{
|
|
int t;
|
|
t = y0;
|
|
y0 = y1;
|
|
y1 = t;
|
|
}
|
|
|
|
if (y0 < dc->clip.y)
|
|
y0 = dc->clip.y;
|
|
|
|
if (y1 >= dc->clip.y + dc->clip.h)
|
|
y1 = dc->clip.y + dc->clip.h - 1;
|
|
|
|
h = y1 - y0;
|
|
if (h < 1)
|
|
return;
|
|
|
|
dst_itr = dst->pixels + (dst->stride * y0) + x;
|
|
alpha = A_VAL(&dc->col.col) >> 3;
|
|
rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
|
|
G_VAL(&dc->col.col),
|
|
B_VAL(&dc->col.col));
|
|
|
|
if (alpha == 31)
|
|
{
|
|
for (; h > 0; h--, dst_itr += dst->stride)
|
|
_soft16_pt_fill_solid_solid(dst_itr, rgb565);
|
|
}
|
|
else if (alpha > 0)
|
|
{
|
|
DATA32 rgb565_unpack;
|
|
|
|
rgb565_unpack = RGB_565_UNPACK(rgb565);
|
|
alpha++;
|
|
|
|
for (; h > 0; h--, dst_itr += dst->stride)
|
|
_soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
_soft16_line_45deg_adjust_boundaries(const struct RGBA_Draw_Context_clip clip, int *p_x0, int *p_y0, int *p_x1, int *p_y1)
|
|
{
|
|
int diff, dy, x0, y0, x1, y1;
|
|
|
|
x0 = *p_x0;
|
|
y0 = *p_y0;
|
|
x1 = *p_x1;
|
|
y1 = *p_y1;
|
|
|
|
dy = y1 - y0;
|
|
|
|
diff = clip.x - x0;
|
|
if (diff > 0)
|
|
{
|
|
x0 = clip.x;
|
|
y0 += (dy > 0) ? diff : -diff;
|
|
}
|
|
|
|
diff = x1 - (clip.x + clip.w);
|
|
if (diff > 0)
|
|
{
|
|
x1 = clip.x + clip.w;
|
|
y1 += (dy > 0) ? -diff : diff;
|
|
}
|
|
|
|
if (dy > 0)
|
|
{
|
|
diff = clip.y - y0;
|
|
if (diff > 0)
|
|
{
|
|
y0 = clip.y;
|
|
x0 += diff;
|
|
}
|
|
|
|
diff = y1 - (clip.y + clip.h);
|
|
if (diff > 0)
|
|
{
|
|
y1 = clip.y + clip.h;
|
|
x1 -= diff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
diff = clip.y - y1;
|
|
if (diff > 0)
|
|
{
|
|
y1 = clip.y;
|
|
x1 -= diff;
|
|
}
|
|
|
|
diff = y0 - (clip.y + clip.h - 1);
|
|
if (diff > 0)
|
|
{
|
|
y0 = clip.y + clip.h - 1;
|
|
x0 += diff;
|
|
}
|
|
}
|
|
|
|
*p_x0 = x0;
|
|
*p_y0 = y0;
|
|
*p_x1 = x1;
|
|
*p_y1 = y1;
|
|
}
|
|
|
|
static void
|
|
_soft16_line_45deg(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
|
|
{
|
|
int dy, step_dst_itr, len;
|
|
DATA8 alpha;
|
|
DATA16 *dst_itr, rgb565;
|
|
|
|
alpha = A_VAL(&dc->col.col) >> 3;
|
|
if (alpha < 1)
|
|
return;
|
|
|
|
rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
|
|
G_VAL(&dc->col.col),
|
|
B_VAL(&dc->col.col));
|
|
|
|
dy = y1 - y0;
|
|
step_dst_itr = 1 + ((dy > 0) ? dst->stride : -dst->stride);
|
|
|
|
_soft16_line_45deg_adjust_boundaries(dc->clip, &x0, &y0, &x1, &y1);
|
|
|
|
len = (dy > 0) ? (y1 - y0) : (y0 - y1);
|
|
if (len < 1)
|
|
return;
|
|
|
|
dst_itr = dst->pixels + dst->stride * y0 + x0;
|
|
if (alpha == 31)
|
|
{
|
|
for (; len > 0; len--, dst_itr += step_dst_itr)
|
|
_soft16_pt_fill_solid_solid(dst_itr, rgb565);
|
|
}
|
|
else
|
|
{
|
|
DATA32 rgb565_unpack;
|
|
|
|
rgb565_unpack = RGB_565_UNPACK(rgb565);
|
|
alpha++;
|
|
for (; len > 0; len--, dst_itr += step_dst_itr)
|
|
_soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
|
|
}
|
|
}
|
|
|
|
static always_inline void
|
|
_soft16_line_aliased_pt(DATA16 *dst_itr, DATA16 rgb565, DATA32 rgb565_unpack, DATA8 alpha)
|
|
{
|
|
if (alpha == 32)
|
|
_soft16_pt_fill_solid_solid(dst_itr, rgb565);
|
|
else
|
|
_soft16_pt_fill_transp_solid(dst_itr, rgb565_unpack, alpha);
|
|
}
|
|
|
|
static void
|
|
_soft16_line_aliased(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
|
|
{
|
|
int dx, dy, step_y, step_dst_itr;
|
|
DATA32 rgb565_unpack;
|
|
DATA16 rgb565;
|
|
DATA8 alpha;
|
|
|
|
alpha = A_VAL(&dc->col.col) >> 3;
|
|
if (alpha == 0)
|
|
return;
|
|
alpha++;
|
|
|
|
rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col),
|
|
G_VAL(&dc->col.col),
|
|
B_VAL(&dc->col.col));
|
|
rgb565_unpack = RGB_565_UNPACK(rgb565);
|
|
|
|
dx = x1 - x0;
|
|
dy = y1 - y0;
|
|
|
|
if (dy >= 0)
|
|
{
|
|
step_y = 1;
|
|
step_dst_itr = dst->stride;
|
|
}
|
|
else
|
|
{
|
|
dy = -dy;
|
|
step_y = -1;
|
|
step_dst_itr = -dst->stride;
|
|
}
|
|
|
|
if (dx > dy)
|
|
{
|
|
DATA16 *dst_itr;
|
|
int e, x, y;
|
|
|
|
e = - (dx / 2);
|
|
y = y0;
|
|
dst_itr = dst->pixels + dst->stride * y0 + x0;
|
|
for (x=x0; x <= x1; x++, dst_itr++)
|
|
{
|
|
if (_is_xy_inside_clip(x, y, dc->clip))
|
|
_soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
|
|
|
|
e += dy;
|
|
if (e >= 0)
|
|
{
|
|
dst_itr += step_dst_itr;
|
|
y += step_y;
|
|
e -= dx;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DATA16 *dst_itr;
|
|
int e, x, y;
|
|
|
|
e = - (dy / 2);
|
|
x = x0;
|
|
dst_itr = dst->pixels + dst->stride * y0 + x0;
|
|
for (y=y0; y != y1; y += step_y, dst_itr += step_dst_itr)
|
|
{
|
|
if (_is_xy_inside_clip(x, y, dc->clip))
|
|
_soft16_line_aliased_pt(dst_itr, rgb565, rgb565_unpack, alpha);
|
|
|
|
e += dx;
|
|
if (e >= 0)
|
|
{
|
|
dst_itr++;
|
|
x++;
|
|
e -= dy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
evas_common_soft16_line_draw(Soft16_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1)
|
|
{
|
|
struct RGBA_Draw_Context_clip c_bkp, c_tmp;
|
|
int dx, dy;
|
|
int x, y, w, h;
|
|
|
|
c_tmp.mask = NULL;
|
|
c_tmp.use = 1;
|
|
c_tmp.x = 0;
|
|
c_tmp.y = 0;
|
|
c_tmp.w = dst->cache_entry.w;
|
|
c_tmp.h = dst->cache_entry.h;
|
|
|
|
/* save out clip info */
|
|
c_bkp = dc->clip;
|
|
if (c_bkp.use)
|
|
{
|
|
RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h,
|
|
c_bkp.x, c_bkp.y, c_bkp.w, c_bkp.h);
|
|
if (_is_empty_clip(c_tmp))
|
|
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(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h, x, y, w, h);
|
|
if (_is_empty_clip(c_tmp))
|
|
return;
|
|
|
|
/* Check if the line doesn't cross the clip area */
|
|
if (x0 < c_tmp.x && x1 < c_tmp.x)
|
|
return;
|
|
if (x0 >= c_tmp.x + c_tmp.w && x1 >= c_tmp.x + c_tmp.w)
|
|
return;
|
|
if (y0 < c_tmp.y && y1 < c_tmp.y)
|
|
return;
|
|
if (y0 >= c_tmp.y + c_tmp.h && y1 >= c_tmp.y + c_tmp.h)
|
|
return;
|
|
|
|
dc->clip = c_tmp;
|
|
dx = x1 - x0;
|
|
dy = y1 - y0;
|
|
|
|
if (dx < 0)
|
|
{
|
|
int t;
|
|
|
|
t = x0;
|
|
x0 = x1;
|
|
x1 = t;
|
|
|
|
t = y0;
|
|
y0 = y1;
|
|
y1 = t;
|
|
}
|
|
|
|
if (dx == 0 && dy == 0)
|
|
_soft16_line_point(dst, dc, x0, y0);
|
|
else if (dx == 0)
|
|
_soft16_line_vert(dst, dc, x0, y0, y1);
|
|
else if (dy == 0)
|
|
_soft16_line_horiz(dst, dc, x0, x1, y0);
|
|
else if (dy == dx || dy == -dx)
|
|
_soft16_line_45deg(dst, dc, x0, y0, x1, y1);
|
|
else
|
|
_soft16_line_aliased(dst, dc, x0, y0, x1, y1);
|
|
|
|
/* restore clip info */
|
|
dc->clip = c_bkp;
|
|
}
|