diff --git a/src/lib/ector/ector_surface.eo b/src/lib/ector/ector_surface.eo index 0dcfff28ac..67a4813368 100644 --- a/src/lib/ector/ector_surface.eo +++ b/src/lib/ector/ector_surface.eo @@ -21,5 +21,15 @@ mixin @beta Ector.Surface extends Ector.Buffer @in type: const(Efl.Class); [[Efl class]] /* FIXME: Should probably be a more restricted type */ } } + draw_image @pure_virtual { + [[ Draw image's buffer to surface buffer. ]] + params { + @in image: Ector.Buffer; [[Image buffer]] + @in x: int; [[Buffer position x]] + @in y: int; [[Buffer position y]] + @in alpha: int; [[Buffer alpha value]] + } + return: bool; [[True if drawing was successful]] + } } } diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h index 34ea0038b7..62d1c3f8fd 100644 --- a/src/lib/ector/software/ector_software_private.h +++ b/src/lib/ector/software/ector_software_private.h @@ -5,6 +5,7 @@ #include "sw_ft_raster.h" #include "sw_ft_stroker.h" #include "../ector_private.h" +#include "draw.h" typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data; typedef struct _Ector_Software_Thread Ector_Software_Thread; diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c index 10cf9962fd..08a2786f16 100644 --- a/src/lib/ector/software/ector_software_surface.c +++ b/src/lib/ector/software/ector_software_surface.c @@ -245,5 +245,31 @@ _ector_software_surface_ector_surface_reference_point_set(Eo *obj EINA_UNUSED, pd->y = y; } +static Eina_Bool +_ector_software_surface_ector_surface_draw_image(Eo *obj EINA_UNUSED, + Ector_Software_Surface_Data *pd, + Ector_Buffer *buffer, int x, int y, int alpha) +{ + if (!buffer || !pd->rasterizer || !pd->rasterizer->fill_data.raster_buffer->pixels.u32) + return EINA_FALSE; + + Ector_Software_Buffer_Base_Data *bd = efl_data_scope_get(buffer, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN); + const int pix_stride = pd->rasterizer->fill_data.raster_buffer->stride / 4; + + uint32_t *src = bd->pixels.u32; + for (unsigned int local_y = 0; local_y < bd->generic->h; local_y++) + { + uint32_t *dst = pd->rasterizer->fill_data.raster_buffer->pixels.u32 + (x + ((local_y + y) * pix_stride)); + for (unsigned int local_x = 0; local_x < bd->generic->w; local_x++) + { + *src = draw_mul_256(alpha, *src); + int inv_alpha = 255 - ((*src) >> 24); + *dst = *src + draw_mul_256(inv_alpha, *dst); + dst++; + src++; + } + } + return EINA_TRUE; +} #include "ector_software_surface.eo.c" #include "ector_renderer_software.eo.c" diff --git a/src/lib/ector/software/ector_software_surface.eo b/src/lib/ector/software/ector_software_surface.eo index 77d6db28a3..62126401b8 100644 --- a/src/lib/ector/software/ector_software_surface.eo +++ b/src/lib/ector/software/ector_software_surface.eo @@ -6,6 +6,7 @@ class @beta Ector.Software.Surface extends Ector.Software.Buffer implements Ecto implements { Ector.Surface.renderer_factory_new; Ector.Surface.reference_point { set; } + Ector.Surface.draw_image; Efl.Object.destructor; Efl.Object.constructor; } diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c index 9598168956..2c55071a4d 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.c +++ b/src/lib/evas/canvas/efl_canvas_vg_container.c @@ -236,6 +236,9 @@ static void _efl_canvas_vg_container_efl_object_destructor(Eo *obj, Efl_Canvas_Vg_Container_Data *pd) { + if (pd->blend_pixels) free(pd->blend_pixels); + if (pd->blend_buffer) efl_unref(pd->blend_buffer); + //Destroy mask surface if (pd->mask.buffer) efl_unref(pd->mask.buffer); if (pd->mask.pixels) free(pd->mask.pixels); diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index c4e7c2b861..026640a80a 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -386,22 +386,66 @@ _efl_canvas_vg_object_efl_object_finalize(Eo *obj, Efl_Canvas_Vg_Object_Data *pd static void _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, void *engine, void *output, void *context, Efl_VG *node, - Eina_Array *clips, Eina_Bool do_async) + Eina_Array *clips, int w, int h, Ector_Surface *ector, Eina_Bool do_async) { if (!efl_gfx_entity_visible_get(node)) return; if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS)) { - Efl_Canvas_Vg_Container_Data *cd = - efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS); + Efl_VG *child; + Eina_List *l; + Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS); if (cd->mask.target) return; //Don't draw mask itself. - Efl_VG *child; - Eina_List *l; + int alpha = 255; + efl_gfx_color_get(node, NULL, NULL, NULL, &alpha); - EINA_LIST_FOREACH(cd->children, l, child) - _evas_vg_render(obj, pd, engine, output, context, child, clips, do_async); + if (alpha < 255) + { + // Reuse buffer + if (!cd->blend_pixels) + cd->blend_pixels = calloc(w * h, sizeof(uint32_t*)); + else + memset(cd->blend_pixels, 0, sizeof(uint32_t) * (w * h)); + + if (!cd->blend_buffer) + { + cd->blend_buffer = ENFN->ector_buffer_new(ENC, obj->layer->evas->evas, + w, h, + EFL_GFX_COLORSPACE_ARGB8888, + ECTOR_BUFFER_FLAG_DRAWABLE | + ECTOR_BUFFER_FLAG_CPU_READABLE | + ECTOR_BUFFER_FLAG_CPU_WRITABLE); + ector_buffer_pixels_set(cd->blend_buffer, cd->blend_pixels, + w, h, 0, + EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); + } + + // Buffer change + ector_buffer_pixels_set(ector, cd->blend_pixels, + w, h, 0, + EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); + ector_surface_reference_point_set(ector, 0,0); + + // Draw child node to changed buffer + EINA_LIST_FOREACH(cd->children, l, child) + _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async); + + // Re-set original surface + ENFN->ector_begin(engine, output, context, ector, 0, 0, EINA_FALSE, do_async); + + // Draw buffer to original surface.(Ector_Surface) + ector_surface_draw_image(ector, cd->blend_buffer, 0, 0, alpha); + + } + else + { + if (cd->blend_pixels) free(cd->blend_pixels); + if (cd->blend_buffer) efl_unref(cd->blend_buffer); + EINA_LIST_FOREACH(cd->children, l, child) + _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async); + } } else { @@ -451,6 +495,7 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd engine, buffer, context, root, NULL, + w, h, ector, do_async); ENFN->image_dirty_region(engine, buffer, 0, 0, w, h); diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index f4c47de4bb..73ff63e7d8 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -94,6 +94,10 @@ struct _Efl_Canvas_Vg_Container_Data //Masking feature. Efl_Canvas_Vg_Node *mask_src; //Mask Source Vg_Mask mask; //Mask source data + + //Layer transparency feature. This buffer is only valid when the layer has transparency. + Ector_Buffer *blend_buffer; + void *blend_pixels; }; struct _Efl_Canvas_Vg_Gradient_Data