Ector.Renderer : Implement Ector.Renderer.(Software).Image class
authorJunsuChoi <jsuya.choi@samsung.com>
Mon, 22 Jul 2019 04:29:02 +0000 (13:29 +0900)
committerSangHyeon Jade Lee <sh10233.lee@samsung.com>
Tue, 23 Jul 2019 05:04:43 +0000 (14:04 +0900)
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
src/lib/ector/ector_renderer.h
src/lib/ector/ector_renderer_image.c [new file with mode: 0644]
src/lib/ector/ector_renderer_image.eo [new file with mode: 0644]
src/lib/ector/meson.build
src/lib/ector/software/Ector_Software.h
src/lib/ector/software/ector_renderer_software_image.c [new file with mode: 0644]
src/lib/ector/software/ector_renderer_software_image.eo [new file with mode: 0644]
src/lib/ector/software/ector_software_surface.c
src/lib/ector/software/meson.build

index 8604768..8e12820 100644 (file)
@@ -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;
index c8d20d2..482f6cb 100644 (file)
@@ -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 (file)
index 0000000..3e34254
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Ector.h>
+
+#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 (file)
index 0000000..9c2e7b3
--- /dev/null
@@ -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]]
+         }
+       }
+   }
+}
index 069e98d..5bedb7e 100644 (file)
@@ -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'
index 2f9192f..85529e6 100644 (file)
@@ -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 (file)
index 0000000..cb8d93a
--- /dev/null
@@ -0,0 +1,194 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <float.h>
+
+#include <Eina.h>
+#include <Ector.h>
+#include <software/Ector_Software.h>
+
+#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 (file)
index 0000000..8a3f9c5
--- /dev/null
@@ -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;
+   }
+}
index 08a2786..1008fe5 100644 (file)
@@ -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)
index 2dff5be..7374252 100644 (file)
@@ -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',
 ]