evas vg: Shape interpolation patch 80/258580/2
authorMichal Maciola <m.maciola@samsung.com>
Thu, 20 May 2021 10:12:42 +0000 (12:12 +0200)
committerHermet Park <chuneon.park@samsung.com>
Fri, 21 May 2021 05:36:34 +0000 (05:36 +0000)
This patch fixes the edgy case when the shape interpolation applies
only to a parameter such as fill color without path interpolation.
Previously, such a case was not performed.
Return case is EINA_FALSE on any error.

Change-Id: Ic8ce2c18ca10cb72c15785f0742a3f0db61beb39

src/lib/evas/canvas/efl_canvas_vg_shape.c

index 5b9ac8d..57bc148 100644 (file)
@@ -406,8 +406,6 @@ _shape_properties_interpolate(Evas_Vg_Shape *obj,
                               const Evas_Vg_Shape *to,
                               double pos_map)
 {
-   if (!obj || !from || !to) return EINA_FALSE;
-
    unsigned int i = 0;
    int a = 0, r = 0, g = 0, b = 0;
    int to_a = 0, to_r = 0, to_g = 0, to_b = 0;
@@ -434,39 +432,45 @@ _shape_properties_interpolate(Evas_Vg_Shape *obj,
 
    efl_gfx_color_get(from, &r, &g, &b, &a);
    efl_gfx_color_get(to, &to_r, &to_g, &to_b, &to_a);
-
-   a = _interpolate(a, to_a, pos_map);
-   r = _interpolate(r, to_r, pos_map);
-   g = _interpolate(g, to_g, pos_map);
-   b = _interpolate(b, to_b, pos_map);
+   if (a != to_a || r != to_r || g != to_g || b != to_b)
+      {
+         a = _interpolate(a, to_a, pos_map);
+         r = _interpolate(r, to_r, pos_map);
+         g = _interpolate(g, to_g, pos_map);
+         b = _interpolate(b, to_b, pos_map);
+      }
    efl_gfx_color_set((Eo*)obj, r, g, b, a);
 
    // Stroke - color
    tvg_shape_get_stroke_color(sd_from->shape, (uint8_t*)&r, (uint8_t*)&g, (uint8_t*)&b, (uint8_t*)&a);
    tvg_shape_get_stroke_color(sd_to->shape, (uint8_t*)&to_r, (uint8_t*)&to_g, (uint8_t*)&to_b, (uint8_t*)&to_a);
-   a = _interpolate(a, to_a, pos_map);
-   r = _interpolate(r, to_r, pos_map);
-   g = _interpolate(g, to_g, pos_map);
-   b = _interpolate(b, to_b, pos_map);
+   if (a != to_a || r != to_r || g != to_g || b != to_b)
+      {
+         a = _interpolate(a, to_a, pos_map);
+         r = _interpolate(r, to_r, pos_map);
+         g = _interpolate(g, to_g, pos_map);
+         b = _interpolate(b, to_b, pos_map);
+      }
    tvg_shape_set_stroke_color(sd->shape, r, g, b, a);
 
    // Stroke - width (scale)
    tvg_shape_get_stroke_width(sd_from->shape, &width);
    tvg_shape_get_stroke_width(sd_to->shape, &width_to);
-   sd->scale = _interpolate(sd_from->scale, sd_to->scale, pos_map);
-   width = _interpolate(width, width_to, pos_map) * sd->scale;
+   if (sd_from->scale != sd_to->scale || width != width_to)
+      {
+         sd->scale = _interpolate(sd_from->scale, sd_to->scale, pos_map);
+         width = _interpolate(width, width_to, pos_map) * sd->scale;
+      }
    tvg_shape_set_stroke_width(sd->shape, width);
 
    // Stroke - dash
    tvg_shape_get_stroke_dash(sd->shape, (const float**)&dash, &dash_cnt);
    tvg_shape_get_stroke_dash(sd_to->shape, (const float**)&dash_to, &dash_to_cnt);
-
    if (dash && dash_to && dash_cnt > 0 && dash_cnt == dash_to_cnt)
      {
         for (i = 0; i < dash_cnt; ++i)
           dash[i] = _interpolate(dash[i], dash_to[i], pos_map);
      }
-
    tvg_shape_set_stroke_dash(sd->shape, dash, dash_cnt);
 
    // Stroke - cap
@@ -501,13 +505,11 @@ _shape_properties_interpolate(Evas_Vg_Shape *obj,
 }
 
 static Eina_Bool
-_shape_interpolate(Evas_Vg_Shape *obj,
+_shape_path_interpolate(Evas_Vg_Shape *obj,
                    const Evas_Vg_Shape *from,
                    const Evas_Vg_Shape *to,
                    double pos_map)
 {
-   if (!obj || !from || !to) return EINA_FALSE;
-
    Tvg_Path_Command *path_commands_from = NULL;
    Tvg_Point *path_coords_from = NULL;
 
@@ -523,8 +525,6 @@ _shape_interpolate(Evas_Vg_Shape *obj,
    Tvg_Point *path_coords_dest = NULL;
    unsigned int i = 0;
 
-   evas_vg_shape_reset(obj);
-
    Tvg_Paint* tvg_dest = _get_tvg_shape(obj);
    Tvg_Paint* tvg_from = _get_tvg_shape((Evas_Vg_Shape*)from);
    Tvg_Paint* tvg_to = _get_tvg_shape((Evas_Vg_Shape*)to);
@@ -536,21 +536,42 @@ _shape_interpolate(Evas_Vg_Shape *obj,
    tvg_shape_get_path_commands(tvg_to, (const Tvg_Path_Command**)&path_commands_to, &cmds_count_to);
    tvg_shape_get_path_coords(tvg_to, (const Tvg_Point**)&path_coords_to, &pts_count_to);
 
-   path_coords_dest = (Tvg_Point*)malloc(sizeof(Tvg_Point) * pts_count_from);
-   if (!path_coords_dest) return EINA_FALSE;
+   if (cmds_count_from != cmds_count_to) return EINA_FALSE;
+   if (pts_count_from != pts_count_to) return EINA_FALSE;
 
-   for (i = 0; i < pts_count_from; ++i)
-     {
-        path_coords_dest[i].x = _interpolate(path_coords_from[i].x, path_coords_to[i].x, pos_map);
-        path_coords_dest[i].y = _interpolate(path_coords_from[i].y, path_coords_to[i].y, pos_map);
-     }
+   // interpolate only if coords differ
+   if (memcmp(path_coords_from, path_coords_to, sizeof(Tvg_Point) * pts_count_from))
+      {
+         path_coords_dest = (Tvg_Point*)malloc(sizeof(Tvg_Point) * pts_count_from);
+         if (!path_coords_dest) return EINA_FALSE;
 
-   _shape_properties_interpolate(obj, from, to, pos_map);
-   tvg_shape_append_path(tvg_dest, path_commands_from, cmds_count_from, path_coords_dest, pts_count_from);
-   free(path_coords_dest);
+         for (i = 0; i < pts_count_from; ++i)
+           {
+              path_coords_dest[i].x = _interpolate(path_coords_from[i].x, path_coords_to[i].x, pos_map);
+              path_coords_dest[i].y = _interpolate(path_coords_from[i].y, path_coords_to[i].y, pos_map);
+           }
+
+         evas_vg_shape_reset(obj);
+         tvg_shape_append_path(tvg_dest, path_commands_from, cmds_count_from, path_coords_dest, pts_count_from);
+         free(path_coords_dest);
+      }
 
    return EINA_TRUE;
 }
+
+static Eina_Bool
+_shape_interpolate(Evas_Vg_Shape *obj,
+                   const Evas_Vg_Shape *from,
+                   const Evas_Vg_Shape *to,
+                   double pos_map)
+{
+   Eina_Bool ret;
+   if (!obj || !from || !to) return EINA_FALSE;
+
+   ret = _shape_path_interpolate(obj, from, to, pos_map);
+   ret &= _shape_properties_interpolate(obj, from, to, pos_map);
+   return ret;
+}
 // FIXME: Use the renderer bounding box when it has been created instead of an estimation
 
 static void
@@ -1345,7 +1366,6 @@ evas_vg_shape_interpolate(Evas_Vg_Shape *obj, const Evas_Vg_Shape *from, const E
 {
    Eina_Bool ret = EINA_FALSE;
 
-   if (!evas_vg_shape_equal_commands((Evas_Vg_Shape*)from, (Evas_Vg_Shape*)to)) return EINA_FALSE;
    ret = _shape_interpolate(obj, from, to, pos_map);
 
    efl_canvas_vg_node_change(obj);