From 18c92fc2c6502e63afef03914b4666cb728bc125 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 22 Jul 2019 13:29:02 +0900 Subject: [PATCH] Ector.Renderer : Implement Ector.Renderer.(Software).Image class Summary: Implement a class and drawer that outputs image data from the Ector. Image data is output with a vector object and supports transform. Test Plan: N/A Reviewers: Hermet, smohanty, kimcinoo Reviewed By: Hermet Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9218 --- src/lib/ector/ector_private.h | 6 + src/lib/ector/ector_renderer.h | 1 + src/lib/ector/ector_renderer_image.c | 22 +++ src/lib/ector/ector_renderer_image.eo | 16 ++ src/lib/ector/meson.build | 2 + src/lib/ector/software/Ector_Software.h | 1 + .../ector/software/ector_renderer_software_image.c | 194 +++++++++++++++++++++ .../software/ector_renderer_software_image.eo | 13 ++ src/lib/ector/software/ector_software_surface.c | 2 + src/lib/ector/software/meson.build | 2 + 10 files changed, 259 insertions(+) create mode 100644 src/lib/ector/ector_renderer_image.c create mode 100644 src/lib/ector/ector_renderer_image.eo create mode 100644 src/lib/ector/software/ector_renderer_software_image.c create mode 100644 src/lib/ector/software/ector_renderer_software_image.eo diff --git a/src/lib/ector/ector_private.h b/src/lib/ector/ector_private.h index 8604768..8e12820 100644 --- a/src/lib/ector/ector_private.h +++ b/src/lib/ector/ector_private.h @@ -47,6 +47,7 @@ typedef struct _Ector_Renderer_Gradient_Data Ector_Renderer_Gradient_Data; typedef struct _Ector_Renderer_Gradient_Linear_Data Ector_Renderer_Gradient_Linear_Data; typedef struct _Ector_Renderer_Gradient_Radial_Data Ector_Renderer_Gradient_Radial_Data; typedef struct _Ector_Renderer_Shape_Data Ector_Renderer_Shape_Data; +typedef struct _Ector_Renderer_Image_Data Ector_Renderer_Image_Data; typedef struct _Ector_Renderer_Buffer_Data Ector_Renderer_Buffer_Data; struct _Ector_Renderer_Data @@ -99,6 +100,11 @@ struct _Ector_Renderer_Shape_Data } stroke; }; +struct _Ector_Renderer_Image_Data +{ + Ector_Buffer *buffer; +}; + struct _Ector_Renderer_Buffer_Data { Ector_Buffer *eo_buffer; diff --git a/src/lib/ector/ector_renderer.h b/src/lib/ector/ector_renderer.h index c8d20d2..482f6cb 100644 --- a/src/lib/ector/ector_renderer.h +++ b/src/lib/ector/ector_renderer.h @@ -3,6 +3,7 @@ #include "ector_renderer.eo.h" #include "ector_renderer_shape.eo.h" +#include "ector_renderer_image.eo.h" #include "ector_renderer_gradient.eo.h" #include "ector_renderer_gradient_linear.eo.h" #include "ector_renderer_gradient_radial.eo.h" diff --git a/src/lib/ector/ector_renderer_image.c b/src/lib/ector/ector_renderer_image.c new file mode 100644 index 0000000..3e34254 --- /dev/null +++ b/src/lib/ector/ector_renderer_image.c @@ -0,0 +1,22 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "ector_private.h" + +#define MY_CLASS ECTOR_RENDERER_IMAGE_MIXIN + + +static void +_ector_renderer_image_buffer_set(Eo *obj EINA_UNUSED, + Ector_Renderer_Image_Data *pd, + Ector_Buffer *buffer) +{ + pd->buffer = buffer; +} + + +#include "ector_renderer_image.eo.c" diff --git a/src/lib/ector/ector_renderer_image.eo b/src/lib/ector/ector_renderer_image.eo new file mode 100644 index 0000000..9c2e7b3 --- /dev/null +++ b/src/lib/ector/ector_renderer_image.eo @@ -0,0 +1,16 @@ +import ector_renderer; + +mixin @beta Ector.Renderer.Image +{ + [[Ector image renderer mixin]] + c_prefix: ector_renderer_image; + methods { + @property buffer { + set { + } + values { + buffer : Ector.Buffer; [[Image buffer]] + } + } + } +} diff --git a/src/lib/ector/meson.build b/src/lib/ector/meson.build index 069e98d..5bedb7e 100644 --- a/src/lib/ector/meson.build +++ b/src/lib/ector/meson.build @@ -14,6 +14,7 @@ ector_src = [ 'ector_gl_internal.h', 'ector_buffer.c', 'ector_renderer_shape.c', + 'ector_renderer_image.c', 'ector_renderer.c', 'ector_renderer_gradient.c', 'ector_renderer_gradient_radial.c', @@ -25,6 +26,7 @@ pub_eo_files = [ 'ector_buffer.eo', 'ector_renderer.eo', 'ector_renderer_shape.eo', + 'ector_renderer_image.eo', 'ector_renderer_gradient.eo', 'ector_renderer_gradient_radial.eo', 'ector_renderer_gradient_linear.eo' diff --git a/src/lib/ector/software/Ector_Software.h b/src/lib/ector/software/Ector_Software.h index 2f9192f..85529e6 100644 --- a/src/lib/ector/software/Ector_Software.h +++ b/src/lib/ector/software/Ector_Software.h @@ -36,6 +36,7 @@ #include "software/ector_software_buffer_base.eo.h" #include "software/ector_renderer_software.eo.h" #include "software/ector_renderer_software_shape.eo.h" +#include "software/ector_renderer_software_image.eo.h" #include "software/ector_renderer_software_gradient_linear.eo.h" #include "software/ector_renderer_software_gradient_radial.eo.h" diff --git a/src/lib/ector/software/ector_renderer_software_image.c b/src/lib/ector/software/ector_renderer_software_image.c new file mode 100644 index 0000000..cb8d93a --- /dev/null +++ b/src/lib/ector/software/ector_renderer_software_image.c @@ -0,0 +1,194 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#include "ector_private.h" +#include "ector_software_private.h" + +#define MY_CLASS ECTOR_RENDERER_SOFTWARE_IMAGE_CLASS + +typedef struct _Ector_Renderer_Software_Image_Data Ector_Renderer_Software_Image_Data; + +struct _Ector_Renderer_Software_Image_Data +{ + Ector_Software_Surface_Data *surface; + Ector_Renderer_Image_Data *image; + Ector_Renderer_Data *base; + Ector_Buffer *mask; + int mask_op; + int opacity; + Eina_Matrix3 inv_m; + struct { + int x1, y1, x2, y2; + } boundary; +}; + +static Eina_Bool +_ector_renderer_software_image_ector_renderer_prepare(Eo *obj, + Ector_Renderer_Software_Image_Data *pd) +{ + if (!pd->surface) + pd->surface = efl_data_xref(pd->base->surface, ECTOR_SOFTWARE_SURFACE_CLASS, obj); + + if (!pd->image->buffer || !pd->surface->rasterizer->fill_data.raster_buffer) + return EINA_FALSE; + + Eina_Matrix3 m; + double m11, m12, m21, m22, m31, m32; + int x = pd->surface->x + (int)pd->base->origin.x; + int y = pd->surface->y + (int)pd->base->origin.y; + int image_w, image_h; + ector_buffer_size_get(pd->image->buffer, &image_w, &image_h); + + double px[4] = {x, x + image_w, x, x + image_w}; + double py[4] = {y, y, y + image_h, y + image_h}; + + //Only use alpha color + pd->opacity = pd->base->color.a; + /*ector_software_rasterizer_color_set(pd->surface->rasterizer, + pd->base->color.r, + pd->base->color.g, + pd->base->color.b, + pd->base->color.a);*/ + + if (!pd->base->m) + { + eina_matrix3_identity(&m); + eina_matrix3_scale(&m, (double)pd->surface->rasterizer->fill_data.raster_buffer->generic->w / (double)image_w, + (double)pd->surface->rasterizer->fill_data.raster_buffer->generic->h / (double)image_h); + } + else + eina_matrix3_copy(&m, pd->base->m); + eina_matrix3_values_get(&m, &m11, &m12, NULL, + &m21, &m22, NULL, + &m31, &m32, NULL); + //Calc draw boundbox + pd->boundary.x1 = MAX(pd->surface->rasterizer->fill_data.raster_buffer->generic->w , (unsigned int)image_w); + pd->boundary.y1 = MAX(pd->surface->rasterizer->fill_data.raster_buffer->generic->h , (unsigned int)image_h); + pd->boundary.x2 = 0; pd->boundary.y2 = 0; + for (int i = 0; i < 4; i++) + { + pd->boundary.x1 = MIN(pd->boundary.x1, (int)(((px[i] * m11) + (py[i] * m21) + m31) + 0.5)); + pd->boundary.y1 = MIN(pd->boundary.y1, (int)(((px[i] * m12) + (py[i] * m22) + m32) + 0.5)); + + pd->boundary.x2 = MAX(pd->boundary.x2, (int)(((px[i] * m11) + (py[i] * m21) + m31) + 0.5)); + pd->boundary.y2 = MAX(pd->boundary.y2, (int)(((px[i] * m12) + (py[i] * m22) + m32) + 0.5)); + } + + eina_matrix3_inverse(&m, &pd->inv_m); + + return EINA_TRUE; +} + +//FIXME: We need to implement that apply op, clips and mul_col. +static Eina_Bool +_ector_renderer_software_image_ector_renderer_draw(Eo *obj EINA_UNUSED, + Ector_Renderer_Software_Image_Data *pd, + Efl_Gfx_Render_Op op EINA_UNUSED, Eina_Array *clips EINA_UNUSED, + unsigned int mul_col EINA_UNUSED) +{ + if (!pd->image->buffer || !pd->surface->rasterizer->fill_data.raster_buffer->pixels.u32) + return EINA_FALSE; + + if (pd->opacity == 0) + return EINA_TRUE; + + const int pix_stride = pd->surface->rasterizer->fill_data.raster_buffer->stride / 4; + Ector_Software_Buffer_Base_Data *mask = pd->mask ? efl_data_scope_get(pd->mask, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN) : NULL; + Ector_Software_Buffer_Base_Data *bpd = efl_data_scope_get(pd->image->buffer, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN); + double im11, im12, im21, im22, im31, im32; + uint32_t *dst_buf, *src_buf; + int image_w, image_h; + ector_buffer_size_get(pd->image->buffer, &image_w, &image_h); + + dst_buf = pd->surface->rasterizer->fill_data.raster_buffer->pixels.u32; + src_buf = bpd->pixels.u32; + + eina_matrix3_values_get(&pd->inv_m, &im11, &im12, NULL, + &im21, &im22, NULL, + &im31, &im32, NULL); + + //Draw + for (int local_y = pd->boundary.y1; local_y < pd->boundary.y2; local_y++) + { + for (int local_x = pd->boundary.x1; local_x < pd->boundary.x2; local_x++) + { + uint32_t *dst = dst_buf + ((int)local_x + ((int)local_y * pix_stride)); + int rx, ry; + rx = (int)(((double)local_x * im11) + ((double)local_y * im21) + im31 + 0.5); + ry = (int)(((double)local_x * im12) + ((double)local_y * im22) + im32 + 0.5); + if (rx < 0 || rx >= image_w || ry < 0 || ry >= image_h) + continue; + uint32_t *src = src_buf + (rx + (ry * image_w)); //FIXME: use to stride + uint32_t temp = 0x0; + if (mask) + { + uint32_t *m = mask->pixels.u32 + ((int)local_x + ((int)local_y * mask->generic->w)); + //FIXME : This masking can work only matte case. + // We need consider to inverse matte case. + temp = draw_mul_256((((*m)>>24) * pd->opacity)>>8, *src); + } + else + { + temp = draw_mul_256(pd->opacity, *src); + } + int inv_alpha = 255 - ((temp) >> 24); + *dst = temp + draw_mul_256(inv_alpha, *dst); + } + } + + return EINA_TRUE; +} + +static Eo * +_ector_renderer_software_image_efl_object_constructor(Eo *obj, Ector_Renderer_Software_Image_Data *pd) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + if (!obj) return NULL; + + pd->image = efl_data_xref(obj, ECTOR_RENDERER_IMAGE_MIXIN, obj); + pd->base = efl_data_xref(obj, ECTOR_RENDERER_CLASS, obj); + + return obj; +} + +static void +_ector_renderer_software_image_efl_object_destructor(Eo *obj, Ector_Renderer_Software_Image_Data *pd) +{ + efl_data_xunref(pd->base->surface, pd->surface, obj); + efl_data_xunref(obj, pd->base, obj); + efl_data_xunref(obj, pd->image, obj); + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +unsigned int +_ector_renderer_software_image_ector_renderer_crc_get(const Eo *obj, + Ector_Renderer_Software_Image_Data *pd) +{ + unsigned int crc; + + crc = ector_renderer_crc_get(efl_super(obj, MY_CLASS)); + + crc = eina_crc((void*) pd->image, sizeof (Ector_Renderer_Image_Data), crc, EINA_FALSE); + return crc; +} + +static void +_ector_renderer_software_image_ector_renderer_mask_set(Eo *obj EINA_UNUSED, + Ector_Renderer_Software_Image_Data *pd, + Ector_Buffer *mask, + int op) +{ + pd->mask = mask; + pd->mask_op = op; +} + +#include "ector_renderer_software_image.eo.c" diff --git a/src/lib/ector/software/ector_renderer_software_image.eo b/src/lib/ector/software/ector_renderer_software_image.eo new file mode 100644 index 0000000..8a3f9c5 --- /dev/null +++ b/src/lib/ector/software/ector_renderer_software_image.eo @@ -0,0 +1,13 @@ +class @beta Ector.Renderer.Software.Image extends Ector.Renderer.Software implements Ector.Renderer.Image +{ + [[Ector software renderer image class]] + c_prefix: ector_renderer_software_image; + implements { + Ector.Renderer.prepare; + Ector.Renderer.draw; + Ector.Renderer.mask { set; } + Ector.Renderer.crc { get; } + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c index 08a2786..1008fe5 100644 --- a/src/lib/ector/software/ector_software_surface.c +++ b/src/lib/ector/software/ector_software_surface.c @@ -204,6 +204,8 @@ _ector_software_surface_ector_surface_renderer_factory_new(Eo *obj, { if (type == ECTOR_RENDERER_SHAPE_MIXIN) return efl_add_ref(ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); + else if (type == ECTOR_RENDERER_IMAGE_MIXIN) + return efl_add_ref(ECTOR_RENDERER_SOFTWARE_IMAGE_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); else if (type == ECTOR_RENDERER_GRADIENT_LINEAR_MIXIN) return efl_add_ref(ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); else if (type == ECTOR_RENDERER_GRADIENT_RADIAL_MIXIN) diff --git a/src/lib/ector/software/meson.build b/src/lib/ector/software/meson.build index 2dff5be..7374252 100644 --- a/src/lib/ector/software/meson.build +++ b/src/lib/ector/software/meson.build @@ -3,6 +3,7 @@ ector_src += files([ 'ector_renderer_software_gradient_linear.c', 'ector_renderer_software_gradient_radial.c', 'ector_renderer_software_shape.c', + 'ector_renderer_software_image.c', 'ector_software_gradient.c', 'ector_software_rasterizer.c', 'ector_software_surface.c', @@ -16,6 +17,7 @@ pub_eo_files = [ 'ector_software_buffer_base.eo', 'ector_renderer_software.eo', 'ector_renderer_software_shape.eo', + 'ector_renderer_software_image.eo', 'ector_renderer_software_gradient_radial.eo', 'ector_renderer_software_gradient_linear.eo', ] -- 2.7.4