forked from enlightenment/efl
ector: refactored software drawing backend to use composition function.
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
parent
48b558a997
commit
2766ce57ce
|
@ -95,7 +95,8 @@ lib/ector/software/ector_software_rasterizer.c \
|
|||
lib/ector/software/ector_software_surface.c \
|
||||
lib/ector/software/sw_ft_math.c \
|
||||
lib/ector/software/sw_ft_raster.c \
|
||||
lib/ector/software/sw_ft_stroker.c
|
||||
lib/ector/software/sw_ft_stroker.c \
|
||||
lib/ector/software/ector_drawhelper.c
|
||||
|
||||
installed_ectorsoftwareheadersdir = $(includedir)/ector-@VMAJ@/software
|
||||
nodist_installed_ectorsoftwareheaders_DATA = $(ector_eolian_software_h)
|
||||
|
@ -147,7 +148,7 @@ endif
|
|||
EXTRA_DIST += \
|
||||
lib/ector/ector_private.h \
|
||||
lib/ector/cairo/ector_cairo_private.h \
|
||||
lib/ector/software/ector_blend_private.h \
|
||||
lib/ector/software/ector_drawhelper_private.h \
|
||||
lib/ector/software/ector_software_private.h \
|
||||
lib/ector/software/sw_ft_math.h \
|
||||
lib/ector/software/sw_ft_raster.h \
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <Ector.h>
|
||||
#include "ector_drawhelper_private.h"
|
||||
|
||||
/*
|
||||
s = source pixel
|
||||
d = destination pixel
|
||||
ca = const_alpha
|
||||
sia = source inverse alpha
|
||||
cia = const inverse alpha
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
result = s + d * sia
|
||||
dest = (s + d * sia) * ca + d * cia
|
||||
= s * ca + d * (sia * ca + cia)
|
||||
= s * ca + d * (1 - sa*ca)
|
||||
*/
|
||||
void
|
||||
comp_func_solid_source_over(uint *dest, int length, uint color, uint const_alpha)
|
||||
{
|
||||
int ialpha, i;
|
||||
if (const_alpha != 255)
|
||||
color = BYTE_MUL(color, const_alpha);
|
||||
ialpha = Alpha(~color);
|
||||
for (i = 0; i < length; ++i)
|
||||
dest[i] = color + BYTE_MUL(dest[i], ialpha);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
comp_func_source_over(uint *dest, const uint *src, int length, uint color, uint const_alpha)
|
||||
{
|
||||
int i;
|
||||
uint s, sc, sia;
|
||||
if (const_alpha != 255)
|
||||
color = BYTE_MUL(color, const_alpha);
|
||||
|
||||
if (color == 0xffffffff) // No color multiplier
|
||||
{
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
s = src[i];
|
||||
if (s >= 0xff000000)
|
||||
dest[i] = s;
|
||||
else if (s != 0)
|
||||
{
|
||||
sia = Alpha(~s);
|
||||
dest[i] = s + BYTE_MUL(dest[i], sia);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
s = src[i];
|
||||
sc = ECTOR_MUL4_SYM(color, s);
|
||||
sia = Alpha(~sc);
|
||||
dest[i] = sc + BYTE_MUL(dest[i], sia);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
result = s
|
||||
dest = s * ca + d * cia
|
||||
*/
|
||||
static void
|
||||
comp_func_solid_source(uint *dest, int length, uint color, uint const_alpha)
|
||||
{
|
||||
int ialpha, i;
|
||||
if (const_alpha == 255) _ector_memfill(dest, length, color);
|
||||
else
|
||||
{
|
||||
ialpha = 255 - const_alpha;
|
||||
color = BYTE_MUL(color, const_alpha);
|
||||
for (i = 0; i < length; ++i)
|
||||
dest[i] = color + BYTE_MUL(dest[i], ialpha);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
comp_func_source(uint *dest, const uint *src, int length, uint color, uint const_alpha)
|
||||
{
|
||||
int i, ialpha;
|
||||
uint src_color;
|
||||
if (color == 0xffffffff) // No color multiplier
|
||||
{
|
||||
if (const_alpha == 255)
|
||||
memcpy(dest, src, length * sizeof(uint));
|
||||
else
|
||||
{
|
||||
ialpha = 255 - const_alpha;
|
||||
for (i = 0; i < length; ++i)
|
||||
dest[i] = INTERPOLATE_PIXEL_256(src[i], const_alpha, dest[i], ialpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (const_alpha == 255)
|
||||
{
|
||||
for (i = 0; i < length; ++i)
|
||||
dest[i] = ECTOR_MUL4_SYM(src[i], color);
|
||||
}
|
||||
else
|
||||
{
|
||||
ialpha = 255 - const_alpha;
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
src_color = ECTOR_MUL4_SYM(src[i], color);
|
||||
dest[i] = INTERPOLATE_PIXEL_256(src_color, const_alpha, dest[i], ialpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RGBA_Comp_Func_Solid func_for_mode_solid[ECTOR_ROP_LAST] = {
|
||||
comp_func_solid_source_over,
|
||||
comp_func_solid_source
|
||||
};
|
||||
|
||||
RGBA_Comp_Func func_for_mode[ECTOR_ROP_LAST] = {
|
||||
comp_func_source_over,
|
||||
comp_func_source
|
||||
};
|
||||
|
||||
RGBA_Comp_Func_Solid
|
||||
ector_comp_func_solid_span_get(Ector_Rop op, uint color)
|
||||
{
|
||||
if ((color & 0xff000000) == 0xff000000)
|
||||
{
|
||||
if (op == ECTOR_ROP_BLEND) op = ECTOR_ROP_COPY;
|
||||
}
|
||||
|
||||
return func_for_mode_solid[op];
|
||||
}
|
||||
|
||||
RGBA_Comp_Func ector_comp_func_span_get(Ector_Rop op, uint color, Eina_Bool src_alpha)
|
||||
{
|
||||
if (((color & 0xff000000) == 0xff000000) && !src_alpha)
|
||||
{
|
||||
if (op == ECTOR_ROP_BLEND) op = ECTOR_ROP_COPY;
|
||||
}
|
||||
return func_for_mode[op];
|
||||
}
|
||||
|
||||
void init_draw_helper()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef ECTOR_DRAWHELPER_PRIVATE_H
|
||||
#define ECTOR_DRAWHELPER_PRIVATE_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX( a, b ) ( (a) > (b) ? (a) : (b) )
|
||||
#endif
|
||||
|
||||
#ifndef uint
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
|
||||
inline int Alpha(uint c)
|
||||
{
|
||||
return c>>24;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ECTOR_ARGB_JOIN(a,r,g,b) \
|
||||
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
|
||||
|
||||
#define ECTOR_MUL4_SYM(x, y) \
|
||||
( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
|
||||
((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
|
||||
((((((x) & 0xff00) * ((y) & 0xff00)) + 0xff0000) >> 16) & 0xff00) + \
|
||||
(((((x) & 0xff) * ((y) & 0xff)) + 0xff) >> 8) )
|
||||
|
||||
#define BYTE_MUL(c, a) \
|
||||
( (((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
|
||||
(((((c) & 0x00ff00ff) * (a)) >> 8) & 0x00ff00ff) )
|
||||
|
||||
#define LOOP_ALIGNED_U1_A4(DEST, LENGTH, UOP, A4OP) \
|
||||
{ \
|
||||
while((uintptr_t)DEST & 0xF && LENGTH) UOP \
|
||||
\
|
||||
while(LENGTH) { \
|
||||
switch(LENGTH) { \
|
||||
case 3: \
|
||||
case 2: \
|
||||
case 1: \
|
||||
UOP \
|
||||
break; \
|
||||
default: \
|
||||
A4OP \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
static inline void
|
||||
_ector_memfill(uint *dest, int length, uint value)
|
||||
{
|
||||
int n;
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
n = (length + 7) / 8;
|
||||
switch (length & 0x07)
|
||||
{
|
||||
case 0: do { *dest++ = value;
|
||||
case 7: *dest++ = value;
|
||||
case 6: *dest++ = value;
|
||||
case 5: *dest++ = value;
|
||||
case 4: *dest++ = value;
|
||||
case 3: *dest++ = value;
|
||||
case 2: *dest++ = value;
|
||||
case 1: *dest++ = value;
|
||||
} while (--n > 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint
|
||||
INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
|
||||
{
|
||||
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
|
||||
t >>= 8;
|
||||
t &= 0xff00ff;
|
||||
x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
|
||||
x &= 0xff00ff00;
|
||||
x |= t;
|
||||
return x;
|
||||
}
|
||||
|
||||
typedef void (*RGBA_Comp_Func)(uint *dest, const uint *src, int length, uint mul_col, uint const_alpha);
|
||||
typedef void (*RGBA_Comp_Func_Solid)(uint *dest, int length, uint color, uint const_alpha);
|
||||
extern RGBA_Comp_Func_Solid func_for_mode_solid[ECTOR_ROP_LAST];
|
||||
extern RGBA_Comp_Func func_for_mode[ECTOR_ROP_LAST];
|
||||
|
||||
void init_draw_helper();
|
||||
|
||||
RGBA_Comp_Func_Solid ector_comp_func_solid_span_get(Ector_Rop op, uint color);
|
||||
RGBA_Comp_Func ector_comp_func_span_get(Ector_Rop op, uint color, Eina_Bool src_alpha);
|
||||
|
||||
#endif
|
|
@ -8,49 +8,27 @@
|
|||
|
||||
#include "ector_private.h"
|
||||
#include "ector_software_private.h"
|
||||
#include "ector_blend_private.h"
|
||||
|
||||
#include "ector_drawhelper_private.h"
|
||||
|
||||
static void
|
||||
_blend_color_argb(int count, const SW_FT_Span *spans, void *user_data)
|
||||
{
|
||||
RGBA_Comp_Func_Solid comp_func;
|
||||
Span_Data *data = (Span_Data *)(user_data);
|
||||
uint color, *buffer, *target;
|
||||
|
||||
// multiply the color with mul_col if any
|
||||
uint color = ECTOR_MUL4_SYM(data->color, data->mul_col);
|
||||
Eina_Bool solid_source = ((color >> 24) == 255);
|
||||
color = ECTOR_MUL4_SYM(data->color, data->mul_col);
|
||||
comp_func = ector_comp_func_solid_span_get(data->op, color);
|
||||
|
||||
// move to the offset location
|
||||
uint *buffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
|
||||
|
||||
if (solid_source)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
|
||||
if (spans->coverage == 255)
|
||||
{
|
||||
_ector_memfill(target, color, spans->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint c = ECTOR_MUL_256(color, spans->coverage);
|
||||
int ialpha = 255 - spans->coverage;
|
||||
for (int i = 0; i < spans->len; ++i)
|
||||
target[i] = c + ECTOR_MUL_256(target[i], ialpha);
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
return;
|
||||
}
|
||||
buffer = data->raster_buffer.buffer + ((data->raster_buffer.width * data->offy) + data->offx);
|
||||
|
||||
while (count--)
|
||||
{
|
||||
uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
|
||||
uint c = ECTOR_MUL_256(color, spans->coverage);
|
||||
int ialpha = (~c) >> 24;
|
||||
|
||||
for (int i = 0; i < spans->len; ++i)
|
||||
target[i] = c + ECTOR_MUL_256(target[i], ialpha);
|
||||
target = buffer + ((data->raster_buffer.width * spans->y) + spans->x);
|
||||
comp_func(target, spans->len, color, spans->coverage);
|
||||
++spans;
|
||||
}
|
||||
}
|
||||
|
@ -62,37 +40,35 @@ typedef void (*src_fetch) (unsigned int *buffer, Span_Data *data, int y, int x,
|
|||
static void
|
||||
_blend_gradient(int count, const SW_FT_Span *spans, void *user_data)
|
||||
{
|
||||
Span_Data *data = (Span_Data *)(user_data);
|
||||
src_fetch fetchfunc = NULL;
|
||||
RGBA_Comp_Func comp_func;
|
||||
Span_Data *data = (Span_Data *)(user_data);
|
||||
src_fetch fetchfunc = NULL;
|
||||
unsigned int buffer[BLEND_GRADIENT_BUFFER_SIZE], *target, *destbuffer;
|
||||
int length, l;
|
||||
|
||||
if(data->type == LinearGradient) fetchfunc = &fetch_linear_gradient;
|
||||
if(data->type == RadialGradient) fetchfunc = &fetch_radial_gradient;
|
||||
//@TODO, Get the proper composition function using ,color, ECTOR_OP etc.
|
||||
if (data->type == LinearGradient) fetchfunc = &fetch_linear_gradient;
|
||||
if (data->type == RadialGradient) fetchfunc = &fetch_radial_gradient;
|
||||
|
||||
unsigned int buffer[BLEND_GRADIENT_BUFFER_SIZE];
|
||||
comp_func = ector_comp_func_span_get(data->op, data->mul_col, data->gradient->alpha);
|
||||
|
||||
// move to the offset location
|
||||
unsigned int *destbuffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
|
||||
// move to the offset location
|
||||
destbuffer = data->raster_buffer.buffer + ((data->raster_buffer.width * data->offy) + data->offx);
|
||||
|
||||
while (count--)
|
||||
{
|
||||
unsigned int *target = destbuffer + (data->raster_buffer.width * spans->y + spans->x);
|
||||
int length = spans->len;
|
||||
while (length)
|
||||
{
|
||||
int l = MIN(length, BLEND_GRADIENT_BUFFER_SIZE);
|
||||
if (fetchfunc)
|
||||
fetchfunc(buffer, data, spans->y, spans->x, l);
|
||||
else
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (data->mul_col == 0xffffffff)
|
||||
_ector_comp_func_source_over(target, buffer, l, spans->coverage); // TODO use proper composition func
|
||||
else
|
||||
_ector_comp_func_source_over_mul_c(target, buffer, data->mul_col, l, spans->coverage);
|
||||
target += l;
|
||||
length -= l;
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
while (count--)
|
||||
{
|
||||
target = destbuffer + ((data->raster_buffer.width * spans->y) + spans->x);
|
||||
length = spans->len;
|
||||
while (length)
|
||||
{
|
||||
l = MIN(length, BLEND_GRADIENT_BUFFER_SIZE);
|
||||
fetchfunc(buffer, data, spans->y, spans->x, l);
|
||||
comp_func(target, buffer, l, data->mul_col, spans->coverage);
|
||||
target += l;
|
||||
length -= l;
|
||||
}
|
||||
++spans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,14 +77,18 @@ _blend_gradient(int count, const SW_FT_Span *spans, void *user_data)
|
|||
spans must be sorted on y
|
||||
*/
|
||||
static const
|
||||
SW_FT_Span *_intersect_spans_rect(const Eina_Rectangle *clip, const SW_FT_Span *spans, const SW_FT_Span *end,
|
||||
SW_FT_Span **out_spans, int available)
|
||||
SW_FT_Span *_intersect_spans_rect(const Eina_Rectangle *clip,
|
||||
const SW_FT_Span *spans,
|
||||
const SW_FT_Span *end,
|
||||
SW_FT_Span **out_spans,
|
||||
int available)
|
||||
{
|
||||
SW_FT_Span *out = *out_spans;
|
||||
const short minx = clip->x;
|
||||
const short miny = clip->y;
|
||||
const short maxx = minx + clip->w - 1;
|
||||
const short maxy = miny + clip->h - 1;
|
||||
short minx, miny, maxx, maxy;
|
||||
minx = clip->x;
|
||||
miny = clip->y;
|
||||
maxx = minx + clip->w - 1;
|
||||
maxy = miny + clip->h - 1;
|
||||
|
||||
while (available && spans < end )
|
||||
{
|
||||
|
@ -140,129 +120,144 @@ SW_FT_Span *_intersect_spans_rect(const Eina_Rectangle *clip, const SW_FT_Span *
|
|||
out->coverage = spans->coverage;
|
||||
++out;
|
||||
}
|
||||
|
||||
++spans;
|
||||
--available;
|
||||
}
|
||||
}
|
||||
|
||||
*out_spans = out;
|
||||
|
||||
return spans;
|
||||
*out_spans = out;
|
||||
return spans;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
|
||||
|
||||
static const
|
||||
SW_FT_Span *_intersect_spans_region(const Shape_Rle_Data *clip, int *currentClip,
|
||||
const SW_FT_Span *spans, const SW_FT_Span *end,
|
||||
SW_FT_Span **out_spans, int available)
|
||||
SW_FT_Span *_intersect_spans_region(const Shape_Rle_Data *clip,
|
||||
int *currentClip,
|
||||
const SW_FT_Span *spans,
|
||||
const SW_FT_Span *end,
|
||||
SW_FT_Span **out_spans,
|
||||
int available)
|
||||
{
|
||||
SW_FT_Span *out = *out_spans;
|
||||
SW_FT_Span *out = *out_spans;
|
||||
int sx1, sx2, cx1, cx2, x, len;
|
||||
|
||||
const SW_FT_Span *clipSpans = clip->spans + *currentClip;
|
||||
const SW_FT_Span *clipEnd = clip->spans + clip->size;
|
||||
const SW_FT_Span *clipSpans = clip->spans + *currentClip;
|
||||
const SW_FT_Span *clipEnd = clip->spans + clip->size;
|
||||
|
||||
while (available && spans < end ) {
|
||||
if (clipSpans >= clipEnd) {
|
||||
spans = end;
|
||||
break;
|
||||
}
|
||||
if (clipSpans->y > spans->y) {
|
||||
++spans;
|
||||
continue;
|
||||
}
|
||||
if (spans->y != clipSpans->y) {
|
||||
++clipSpans;
|
||||
continue;
|
||||
}
|
||||
while (available && spans < end )
|
||||
{
|
||||
if (clipSpans >= clipEnd)
|
||||
{
|
||||
spans = end;
|
||||
break;
|
||||
}
|
||||
if (clipSpans->y > spans->y)
|
||||
{
|
||||
++spans;
|
||||
continue;
|
||||
}
|
||||
if (spans->y != clipSpans->y)
|
||||
{
|
||||
++clipSpans;
|
||||
continue;
|
||||
}
|
||||
//assert(spans->y == clipSpans->y);
|
||||
sx1 = spans->x;
|
||||
sx2 = sx1 + spans->len;
|
||||
cx1 = clipSpans->x;
|
||||
cx2 = cx1 + clipSpans->len;
|
||||
|
||||
int sx1 = spans->x;
|
||||
int sx2 = sx1 + spans->len;
|
||||
int cx1 = clipSpans->x;
|
||||
int cx2 = cx1 + clipSpans->len;
|
||||
if (cx1 < sx1 && cx2 < sx1)
|
||||
{
|
||||
++clipSpans;
|
||||
continue;
|
||||
}
|
||||
else if (sx1 < cx1 && sx2 < cx1)
|
||||
{
|
||||
++spans;
|
||||
continue;
|
||||
}
|
||||
x = MAX(sx1, cx1);
|
||||
len = MIN(sx2, cx2) - x;
|
||||
if (len)
|
||||
{
|
||||
out->x = MAX(sx1, cx1);
|
||||
out->len = MIN(sx2, cx2) - out->x;
|
||||
out->y = spans->y;
|
||||
out->coverage = _div_255(spans->coverage * clipSpans->coverage);
|
||||
++out;
|
||||
--available;
|
||||
}
|
||||
if (sx2 < cx2)
|
||||
{
|
||||
++spans;
|
||||
}
|
||||
else
|
||||
{
|
||||
++clipSpans;
|
||||
}
|
||||
}
|
||||
|
||||
if (cx1 < sx1 && cx2 < sx1) {
|
||||
++clipSpans;
|
||||
continue;
|
||||
} else if (sx1 < cx1 && sx2 < cx1) {
|
||||
++spans;
|
||||
continue;
|
||||
}
|
||||
int x = MAX(sx1, cx1);
|
||||
int len = MIN(sx2, cx2) - x;
|
||||
if (len) {
|
||||
out->x = MAX(sx1, cx1);
|
||||
out->len = MIN(sx2, cx2) - out->x;
|
||||
out->y = spans->y;
|
||||
out->coverage = _div_255(spans->coverage * clipSpans->coverage);
|
||||
++out;
|
||||
--available;
|
||||
}
|
||||
if (sx2 < cx2) {
|
||||
++spans;
|
||||
} else {
|
||||
++clipSpans;
|
||||
}
|
||||
}
|
||||
|
||||
*out_spans = out;
|
||||
*currentClip = clipSpans - clip->spans;
|
||||
return spans;
|
||||
*out_spans = out;
|
||||
*currentClip = clipSpans - clip->spans;
|
||||
return spans;
|
||||
}
|
||||
|
||||
static void
|
||||
_span_fill_clipRect(int span_count, const SW_FT_Span *spans, void *user_data)
|
||||
{
|
||||
const int NSPANS = 256;
|
||||
int clip_count, i;
|
||||
SW_FT_Span cspans[NSPANS];
|
||||
Span_Data *fill_data = (Span_Data *) user_data;
|
||||
Clip_Data clip = fill_data->clip;
|
||||
const int NSPANS = 256;
|
||||
int clip_count, i;
|
||||
SW_FT_Span cspans[NSPANS];
|
||||
Span_Data *fill_data = (Span_Data *) user_data;
|
||||
Clip_Data clip = fill_data->clip;
|
||||
SW_FT_Span *clipped;
|
||||
Eina_Rectangle *rect;
|
||||
Eina_Rectangle tmp_rect;
|
||||
|
||||
clip_count = eina_array_count(clip.clips);
|
||||
for (i = 0; i < clip_count ; i ++)
|
||||
{
|
||||
Eina_Rectangle *rect = (Eina_Rectangle *)eina_array_data_get(clip.clips, i);
|
||||
Eina_Rectangle tmpRect;
|
||||
|
||||
clip_count = eina_array_count(clip.clips);
|
||||
for (i = 0; i < clip_count; i++)
|
||||
{
|
||||
rect = (Eina_Rectangle *)eina_array_data_get(clip.clips, i);
|
||||
|
||||
// invert transform the offset
|
||||
tmpRect.x = rect->x - fill_data->offx;
|
||||
tmpRect.y = rect->y - fill_data->offy;
|
||||
tmpRect.w = rect->w;
|
||||
tmpRect.h = rect->h;
|
||||
tmp_rect.x = rect->x - fill_data->offx;
|
||||
tmp_rect.y = rect->y - fill_data->offy;
|
||||
tmp_rect.w = rect->w;
|
||||
tmp_rect.h = rect->h;
|
||||
const SW_FT_Span *end = spans + span_count;
|
||||
|
||||
while (spans < end)
|
||||
{
|
||||
SW_FT_Span *clipped = cspans;
|
||||
spans = _intersect_spans_rect(&tmpRect,spans, end, &clipped, NSPANS);
|
||||
clipped = cspans;
|
||||
spans = _intersect_spans_rect(&tmp_rect, spans, end, &clipped, NSPANS);
|
||||
if (clipped - cspans)
|
||||
fill_data->unclipped_blend(clipped - cspans, cspans, fill_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_span_fill_clipPath(int span_count, const SW_FT_Span *spans, void *user_data)
|
||||
{
|
||||
const int NSPANS = 256;
|
||||
int current_clip = 0;
|
||||
SW_FT_Span cspans[NSPANS];
|
||||
Span_Data *fill_data = (Span_Data *) user_data;
|
||||
Clip_Data clip = fill_data->clip;
|
||||
const int NSPANS = 256;
|
||||
int current_clip = 0;
|
||||
SW_FT_Span cspans[NSPANS];
|
||||
Span_Data *fill_data = (Span_Data *) user_data;
|
||||
Clip_Data clip = fill_data->clip;
|
||||
SW_FT_Span *clipped;
|
||||
|
||||
//TODO take clip path offset into account.
|
||||
|
||||
const SW_FT_Span *end = spans + span_count;
|
||||
while (spans < end)
|
||||
{
|
||||
SW_FT_Span *clipped = cspans;
|
||||
spans = _intersect_spans_region(clip.path, ¤t_clip, spans, end, &clipped, NSPANS);
|
||||
if (clipped - cspans)
|
||||
fill_data->unclipped_blend(clipped - cspans, cspans, fill_data);
|
||||
}
|
||||
//TODO take clip path offset into account.
|
||||
const SW_FT_Span *end = spans + span_count;
|
||||
while (spans < end)
|
||||
{
|
||||
clipped = cspans;
|
||||
spans = _intersect_spans_region(clip.path, ¤t_clip, spans, end, &clipped, NSPANS);
|
||||
if (clipped - cspans)
|
||||
fill_data->unclipped_blend(clipped - cspans, cspans, fill_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -270,19 +265,19 @@ _adjust_span_fill_methods(Span_Data *spdata)
|
|||
{
|
||||
switch(spdata->type)
|
||||
{
|
||||
case None:
|
||||
spdata->unclipped_blend = 0;
|
||||
break;
|
||||
case Solid:
|
||||
spdata->unclipped_blend = &_blend_color_argb;
|
||||
break;
|
||||
case LinearGradient:
|
||||
case RadialGradient:
|
||||
spdata->unclipped_blend = &_blend_gradient;
|
||||
break;
|
||||
case Image:
|
||||
spdata->unclipped_blend = 0;//&_blend_image;
|
||||
break;
|
||||
case None:
|
||||
spdata->unclipped_blend = 0;
|
||||
break;
|
||||
case Solid:
|
||||
spdata->unclipped_blend = &_blend_color_argb;
|
||||
break;
|
||||
case LinearGradient:
|
||||
case RadialGradient:
|
||||
spdata->unclipped_blend = &_blend_gradient;
|
||||
break;
|
||||
case Image:
|
||||
spdata->unclipped_blend = 0;//&_blend_image;
|
||||
break;
|
||||
}
|
||||
|
||||
// setup clipping
|
||||
|
@ -317,6 +312,7 @@ void ector_software_rasterizer_init(Software_Rasterizer *rasterizer)
|
|||
rasterizer->fill_data.clip.enabled = EINA_FALSE;
|
||||
rasterizer->fill_data.unclipped_blend = 0;
|
||||
rasterizer->fill_data.blend = 0;
|
||||
init_draw_helper();
|
||||
}
|
||||
|
||||
void ector_software_rasterizer_done(Software_Rasterizer *rasterizer)
|
||||
|
@ -325,40 +321,38 @@ void ector_software_rasterizer_done(Software_Rasterizer *rasterizer)
|
|||
SW_FT_Stroker_Done(rasterizer->stroker);
|
||||
}
|
||||
|
||||
|
||||
void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width,
|
||||
Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style)
|
||||
{
|
||||
SW_FT_Stroker_LineCap cap;
|
||||
SW_FT_Stroker_LineJoin join;
|
||||
int stroke_width = (int)(width * 64);
|
||||
|
||||
switch (cap_style)
|
||||
{
|
||||
case EFL_GFX_CAP_SQUARE:
|
||||
cap = SW_FT_STROKER_LINECAP_SQUARE;
|
||||
break;
|
||||
case EFL_GFX_CAP_ROUND:
|
||||
cap = SW_FT_STROKER_LINECAP_ROUND;
|
||||
break;
|
||||
default:
|
||||
cap = SW_FT_STROKER_LINECAP_BUTT;
|
||||
break;
|
||||
case EFL_GFX_CAP_SQUARE:
|
||||
cap = SW_FT_STROKER_LINECAP_SQUARE;
|
||||
break;
|
||||
case EFL_GFX_CAP_ROUND:
|
||||
cap = SW_FT_STROKER_LINECAP_ROUND;
|
||||
break;
|
||||
default:
|
||||
cap = SW_FT_STROKER_LINECAP_BUTT;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (join_style)
|
||||
{
|
||||
case EFL_GFX_JOIN_BEVEL:
|
||||
join = SW_FT_STROKER_LINEJOIN_BEVEL;
|
||||
break;
|
||||
case EFL_GFX_JOIN_ROUND:
|
||||
join = SW_FT_STROKER_LINEJOIN_ROUND;
|
||||
break;
|
||||
default:
|
||||
join = SW_FT_STROKER_LINEJOIN_MITER;
|
||||
break;
|
||||
case EFL_GFX_JOIN_BEVEL:
|
||||
join = SW_FT_STROKER_LINEJOIN_BEVEL;
|
||||
break;
|
||||
case EFL_GFX_JOIN_ROUND:
|
||||
join = SW_FT_STROKER_LINEJOIN_ROUND;
|
||||
break;
|
||||
default:
|
||||
join = SW_FT_STROKER_LINEJOIN_MITER;
|
||||
break;
|
||||
}
|
||||
|
||||
int stroke_width = (int)(width * 64);
|
||||
SW_FT_Stroker_Set(rasterizer->stroker, stroke_width, cap, join, 0);
|
||||
}
|
||||
|
||||
|
@ -371,7 +365,7 @@ _rle_generation_cb( int count, const SW_FT_Span* spans,void *user)
|
|||
// allocate enough memory for new spans
|
||||
// alloc is required to prevent free and reallocation
|
||||
// when the rle needs to be regenerated because of attribute change.
|
||||
if(rle->alloc < newsize)
|
||||
if (rle->alloc < newsize)
|
||||
{
|
||||
rle->spans = (SW_FT_Span *) realloc(rle->spans, newsize * sizeof(SW_FT_Span));
|
||||
rle->alloc = newsize;
|
||||
|
@ -425,18 +419,19 @@ Shape_Rle_Data *
|
|||
ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath)
|
||||
{
|
||||
uint points,contors;
|
||||
Shape_Rle_Data *rle_data;
|
||||
SW_FT_Outline strokeOutline = { 0, 0, NULL, NULL, NULL, 0 };
|
||||
|
||||
SW_FT_Stroker_ParseOutline(rasterizer->stroker, outline, !closePath);
|
||||
SW_FT_Stroker_GetCounts(rasterizer->stroker,&points, &contors);
|
||||
|
||||
SW_FT_Outline strokeOutline = { 0, 0, NULL, NULL, NULL, 0 };
|
||||
strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
|
||||
strokeOutline.tags = (char *) calloc(points, sizeof(char));
|
||||
strokeOutline.contours = (short *) calloc(contors, sizeof(short));
|
||||
|
||||
SW_FT_Stroker_Export(rasterizer->stroker, &strokeOutline);
|
||||
|
||||
Shape_Rle_Data *rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline);
|
||||
rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline);
|
||||
|
||||
// cleanup the outline data.
|
||||
free(strokeOutline.points);
|
||||
|
@ -503,20 +498,24 @@ void ector_software_rasterizer_color_set(Software_Rasterizer *rasterizer, int r,
|
|||
rasterizer->fill_data.color = ECTOR_ARGB_JOIN(a, r, g, b);
|
||||
rasterizer->fill_data.type = Solid;
|
||||
}
|
||||
void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *linear)
|
||||
|
||||
void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer,
|
||||
Ector_Renderer_Software_Gradient_Data *linear)
|
||||
{
|
||||
rasterizer->fill_data.gradient = linear;
|
||||
rasterizer->fill_data.type = LinearGradient;
|
||||
}
|
||||
void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *radial)
|
||||
|
||||
void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer,
|
||||
Ector_Renderer_Software_Gradient_Data *radial)
|
||||
{
|
||||
rasterizer->fill_data.gradient = radial;
|
||||
rasterizer->fill_data.type = RadialGradient;
|
||||
}
|
||||
|
||||
|
||||
void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer,
|
||||
int x, int y, uint mul_col, Ector_Rop op, Shape_Rle_Data* rle)
|
||||
int x, int y, uint mul_col,
|
||||
Ector_Rop op, Shape_Rle_Data* rle)
|
||||
{
|
||||
// check for NULL rle data
|
||||
if (!rle) return;
|
||||
|
@ -529,6 +528,6 @@ void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer,
|
|||
_setup_span_fill_matrix(rasterizer);
|
||||
_adjust_span_fill_methods(&rasterizer->fill_data);
|
||||
|
||||
if(rasterizer->fill_data.blend)
|
||||
if (rasterizer->fill_data.blend)
|
||||
rasterizer->fill_data.blend(rle->size, rle->spans, &rasterizer->fill_data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue