forked from enlightenment/efl
ector_software_rasterizer: Support gradient mask blending
Summary: This patch supports mask blending of gradient shapes. Test Plan: N/A Reviewers: Hermet, kimcinoo Reviewed By: Hermet Subscribers: cedric, #reviewers, smohanty, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8855
This commit is contained in:
parent
3a570c38c9
commit
4473062dd4
|
@ -293,6 +293,120 @@ _blend_gradient(int count, const SW_FT_Span *spans, void *user_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_blend_gradient_alpha(int count, const SW_FT_Span *spans, void *user_data)
|
||||||
|
{
|
||||||
|
RGBA_Comp_Func comp_func;
|
||||||
|
Span_Data *data = (Span_Data *)(user_data);
|
||||||
|
src_fetch fetchfunc = NULL;
|
||||||
|
uint32_t *buffer;
|
||||||
|
const int pix_stride = data->raster_buffer->stride / 4;
|
||||||
|
uint32_t gradientbuffer[BLEND_GRADIENT_BUFFER_SIZE];
|
||||||
|
|
||||||
|
// FIXME: 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;
|
||||||
|
|
||||||
|
if (!fetchfunc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Ector_Software_Buffer_Base_Data *mask = data->mask;
|
||||||
|
uint32_t *mbuffer = mask->pixels.u32;
|
||||||
|
|
||||||
|
//Temp buffer for intermediate processing
|
||||||
|
uint32_t *tbuffer = malloc(sizeof(uint32_t) * data->raster_buffer->generic->w);
|
||||||
|
|
||||||
|
comp_func = efl_draw_func_span_get(data->op, data->mul_col, data->gradient->alpha);
|
||||||
|
|
||||||
|
// move to the offset location
|
||||||
|
buffer = data->raster_buffer->pixels.u32 + ((pix_stride * data->offy) + data->offx);
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
uint32_t *target = buffer + ((data->raster_buffer->generic->w * spans->y) + spans->x);
|
||||||
|
uint32_t *mtarget = mbuffer + ((mask->generic->w * spans->y) + spans->x);
|
||||||
|
uint32_t *temp = tbuffer;
|
||||||
|
int length = spans->len;
|
||||||
|
memset(temp, 0x00, sizeof(uint32_t) * spans->len);
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
int l = MIN(length, BLEND_GRADIENT_BUFFER_SIZE);
|
||||||
|
fetchfunc(gradientbuffer, data, spans->y, spans->x, l);
|
||||||
|
comp_func(temp, gradientbuffer, l, data->mul_col, spans->coverage);
|
||||||
|
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
*temp = draw_mul_256(((*mtarget)>>24), *temp);
|
||||||
|
int alpha = 255 - ((*temp) >> 24);
|
||||||
|
*target = *temp + draw_mul_256(alpha, *target);
|
||||||
|
++temp;
|
||||||
|
++mtarget;
|
||||||
|
++target;
|
||||||
|
}
|
||||||
|
length -= l;
|
||||||
|
}
|
||||||
|
++spans;
|
||||||
|
}
|
||||||
|
free(tbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_blend_gradient_alpha_inv(int count, const SW_FT_Span *spans, void *user_data)
|
||||||
|
{
|
||||||
|
RGBA_Comp_Func comp_func;
|
||||||
|
Span_Data *data = (Span_Data *)(user_data);
|
||||||
|
src_fetch fetchfunc = NULL;
|
||||||
|
uint32_t *buffer;
|
||||||
|
const int pix_stride = data->raster_buffer->stride / 4;
|
||||||
|
uint32_t gradientbuffer[BLEND_GRADIENT_BUFFER_SIZE];
|
||||||
|
|
||||||
|
// FIXME: 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;
|
||||||
|
|
||||||
|
if (!fetchfunc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Ector_Software_Buffer_Base_Data *mask = data->mask;
|
||||||
|
uint32_t *mbuffer = mask->pixels.u32;
|
||||||
|
|
||||||
|
//Temp buffer for intermediate processing
|
||||||
|
uint32_t *tbuffer = malloc(sizeof(uint32_t) * data->raster_buffer->generic->w);
|
||||||
|
|
||||||
|
comp_func = efl_draw_func_span_get(data->op, data->mul_col, data->gradient->alpha);
|
||||||
|
|
||||||
|
// move to the offset location
|
||||||
|
buffer = data->raster_buffer->pixels.u32 + ((pix_stride * data->offy) + data->offx);
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
uint32_t *target = buffer + ((data->raster_buffer->generic->w * spans->y) + spans->x);
|
||||||
|
uint32_t *mtarget = mbuffer + ((mask->generic->w * spans->y) + spans->x);
|
||||||
|
uint32_t *temp = tbuffer;
|
||||||
|
int length = spans->len;
|
||||||
|
memset(temp, 0x00, sizeof(uint32_t) * spans->len);
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
int l = MIN(length, BLEND_GRADIENT_BUFFER_SIZE);
|
||||||
|
fetchfunc(gradientbuffer, data, spans->y, spans->x, l);
|
||||||
|
comp_func(temp, gradientbuffer, l, data->mul_col, spans->coverage);
|
||||||
|
|
||||||
|
for (int i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
if (*mtarget)
|
||||||
|
*temp = draw_mul_256((255 - ((*mtarget)>>24)), *temp);
|
||||||
|
int alpha = 255 - ((*temp) >> 24);
|
||||||
|
*target = *temp + draw_mul_256(alpha, *target);
|
||||||
|
++temp;
|
||||||
|
++mtarget;
|
||||||
|
++target;
|
||||||
|
}
|
||||||
|
length -= l;
|
||||||
|
}
|
||||||
|
++spans;
|
||||||
|
}
|
||||||
|
free(tbuffer);
|
||||||
|
}
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
spans must be sorted on y
|
spans must be sorted on y
|
||||||
|
@ -485,23 +599,26 @@ static void
|
||||||
_adjust_span_fill_methods(Span_Data *spdata)
|
_adjust_span_fill_methods(Span_Data *spdata)
|
||||||
{
|
{
|
||||||
//Blending Function
|
//Blending Function
|
||||||
switch(spdata->type)
|
|
||||||
{
|
|
||||||
case None:
|
|
||||||
spdata->unclipped_blend = NULL;
|
|
||||||
break;
|
|
||||||
case Solid:
|
|
||||||
{
|
|
||||||
if (spdata->mask)
|
if (spdata->mask)
|
||||||
{
|
{
|
||||||
switch (spdata->mask_op)
|
switch (spdata->mask_op)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA:
|
case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA:
|
||||||
|
if (spdata->type == Solid)
|
||||||
spdata->unclipped_blend = &_blend_alpha;
|
spdata->unclipped_blend = &_blend_alpha;
|
||||||
|
else if (spdata->type == LinearGradient || spdata->type == RadialGradient)
|
||||||
|
spdata->unclipped_blend = &_blend_gradient_alpha;
|
||||||
|
else //None
|
||||||
|
spdata->unclipped_blend = NULL;
|
||||||
break;
|
break;
|
||||||
case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV:
|
case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV:
|
||||||
|
if (spdata->type == Solid)
|
||||||
spdata->unclipped_blend = &_blend_alpha_inv;
|
spdata->unclipped_blend = &_blend_alpha_inv;
|
||||||
|
else if (spdata->type == LinearGradient || spdata->type == RadialGradient)
|
||||||
|
spdata->unclipped_blend = &_blend_gradient_alpha_inv;
|
||||||
|
else //None
|
||||||
|
spdata->unclipped_blend = NULL;
|
||||||
break;
|
break;
|
||||||
case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD:
|
case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD:
|
||||||
spdata->unclipped_blend = &_blend_mask_add;
|
spdata->unclipped_blend = &_blend_mask_add;
|
||||||
|
@ -518,13 +635,13 @@ _adjust_span_fill_methods(Span_Data *spdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (spdata->type == Solid)
|
||||||
spdata->unclipped_blend = &_blend_argb;
|
spdata->unclipped_blend = &_blend_argb;
|
||||||
}
|
else if (spdata->type == LinearGradient || spdata->type == RadialGradient)
|
||||||
break;
|
|
||||||
case LinearGradient:
|
|
||||||
case RadialGradient:
|
|
||||||
spdata->unclipped_blend = &_blend_gradient;
|
spdata->unclipped_blend = &_blend_gradient;
|
||||||
break;
|
else //None
|
||||||
|
spdata->unclipped_blend = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: Mask and mask case is not use clipping.
|
//FIXME: Mask and mask case is not use clipping.
|
||||||
|
|
Loading…
Reference in New Issue