From: JunsuChoi Date: Wed, 8 May 2019 07:57:19 +0000 (+0900) Subject: ector_software_rasterizer: Support gradient mask blending X-Git-Tag: submit/tizen/20190509.054729~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F57%2F205657%2F1;p=platform%2Fupstream%2Fefl.git 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 Change-Id: I536b6f325734f4606ba5b736c750491dcf8cb61e --- diff --git a/src/lib/ector/software/ector_software_rasterizer.c b/src/lib/ector/software/ector_software_rasterizer.c index b2b5779..42a5e8e 100644 --- a/src/lib/ector/software/ector_software_rasterizer.c +++ b/src/lib/ector/software/ector_software_rasterizer.c @@ -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 spans must be sorted on y @@ -485,46 +599,49 @@ static void _adjust_span_fill_methods(Span_Data *spdata) { //Blending Function - switch(spdata->type) + if (spdata->mask) { - case None: - spdata->unclipped_blend = NULL; - break; - case Solid: + switch (spdata->mask_op) { - if (spdata->mask) - { - switch (spdata->mask_op) - { - default: - case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA: - spdata->unclipped_blend = &_blend_alpha; - break; - case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV: - spdata->unclipped_blend = &_blend_alpha_inv; - break; - case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD: - spdata->unclipped_blend = &_blend_mask_add; - break; - case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT: - spdata->unclipped_blend = &_blend_mask_sub; - break; - case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT: - spdata->unclipped_blend = &_blend_mask_ins; - break; - case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE: - spdata->unclipped_blend = &_blend_mask_diff; - break; - } - } - else - spdata->unclipped_blend = &_blend_argb; - } - break; - case LinearGradient: - case RadialGradient: + default: + case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA: + if (spdata->type == Solid) + 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; + case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV: + if (spdata->type == Solid) + 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; + case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD: + spdata->unclipped_blend = &_blend_mask_add; + break; + case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT: + spdata->unclipped_blend = &_blend_mask_sub; + break; + case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT: + spdata->unclipped_blend = &_blend_mask_ins; + break; + case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE: + spdata->unclipped_blend = &_blend_mask_diff; + break; + } + } + else + { + if (spdata->type == Solid) + spdata->unclipped_blend = &_blend_argb; + else if (spdata->type == LinearGradient || spdata->type == RadialGradient) spdata->unclipped_blend = &_blend_gradient; - break; + else //None + spdata->unclipped_blend = NULL; } //FIXME: Mask and mask case is not use clipping.