edje_calc: fix interpolate calculation of map colors
authorVitalii Vorobiov <vi.vorobiov@samsung.com>
Mon, 13 Jun 2016 12:31:48 +0000 (15:31 +0300)
committerWonki Kim <wonki_.kim@samsung.com>
Mon, 2 Jan 2017 07:27:07 +0000 (16:27 +0900)
There were a problem when while swithcing between states
(because of program running in transition),
there is SIGSEV appearing when first state has
only one point color, and next state more than one.

Basically it looks like this:
....
part {
   name: "rectangle";
   type: RECT;
   description { state: "default" 0.0;
      map {
         on: 1;
         color: 3 255 90 0 255;
      }
   }
   description { state: "moved" 0.0;
      map {
         on: 1;
         color: 0 0 0 255 255;
         color: 1 255 0 0 255;
         color: 2 255 90 0 255;
         color: 3 41 68 59 255;
      }
   }
}
<and program that change 'rectangle' state with transition>
....

@fix

Change-Id: I078f692cf1e8f959fed68dbf79b38357f6882764
Signed-off-by: Vitalii Vorobiov <vi.vorobiov@samsung.com>
src/lib/edje/edje_calc.c

index cc5677d..d9eb09d 100644 (file)
@@ -3860,9 +3860,11 @@ static Eina_Bool
 _map_colors_interp(Edje_Calc_Params *p1, Edje_Calc_Params *p2,
                    Edje_Calc_Params_Map *pmap, FLOAT_T pos)
 {
-   Edje_Map_Color *col, *col2, *col3;
-   int i, j, idx = 0;
-   Eina_Bool matched = EINA_FALSE;
+   Edje_Map_Color *col = NULL, *col2 = NULL, *col3;
+   int i, j;
+
+   unsigned char col1_r = 255, col1_g = 255, col1_b = 255, col1_a = 255;
+   unsigned char col2_r = 255, col2_g = 255, col2_b = 255, col2_a = 255;
 
    if ((p1->map->colors_count > 0) || (p2->map->colors_count > 0))
      {
@@ -3870,59 +3872,50 @@ _map_colors_interp(Edje_Calc_Params *p1, Edje_Calc_Params *p2,
 
         pmap->colors = (Edje_Map_Color **)malloc(sizeof(Edje_Map_Color *) * (int)pmap->colors_count);
 
-        for (i = 0; i < (int)p1->map->colors_count; i++)
+        /* create all Map Color structs at first
+           to make sure we won't get SIGSEV later on cleanup. */
+        for (i = 0; i < (int)pmap->colors_count; i++)
           {
-             col = p1->map->colors[i];
              col3 = malloc(sizeof(Edje_Map_Color));
-             col3->idx = col->idx;
-
-             for (j = 0; j < (int)p2->map->colors_count; j++)
-               {
-                  col2 = p2->map->colors[j];
-                  if (col->idx != col2->idx) continue;
-                  col3->r = INTP(col->r, col2->r, pos);
-                  col3->g = INTP(col->g, col2->g, pos);
-                  col3->b = INTP(col->b, col2->b, pos);
-                  col3->a = INTP(col->a, col2->a, pos);
-                  pmap->colors[idx] = col3;
-                  matched = EINA_TRUE;
-                  break;
-               }
-             if (!matched)
-               {
-                  col3->r = INTP(col->r, 255, pos);
-                  col3->g = INTP(col->g, 255, pos);
-                  col3->b = INTP(col->b, 255, pos);
-                  col3->a = INTP(col->a, 255, pos);
-                  pmap->colors[idx] = col3;
-               }
-             idx++;
-             matched = EINA_FALSE;
-          }
-        for (i = 0; i < (int)p2->map->colors_count; i++)
-          {
-             col = p2->map->colors[i];
+             col3->idx = i; /* we don't care about index position anyway */
 
+             /* find color with idx from first */
              for (j = 0; j < (int)p1->map->colors_count; j++)
                {
-                  col2 = p1->map->colors[j];
-                  if (col->idx != col2->idx) continue;
-                  matched = EINA_TRUE;
-                  break;
+                  col = p1->map->colors[j];
+                  if (col3->idx == col->idx)
+                    {
+                       col1_r = col->r;
+                       col1_g = col->g;
+                       col1_b = col->b;
+                       col1_a = col->a;
+                       break;
+                    }
                }
-             if (!matched)
+             /* find color from idx from second */
+             for (j = 0; j < (int)p2->map->colors_count; j++)
                {
-                  col3 = malloc(sizeof(Edje_Map_Color));
-                  col3->idx = col->idx;
-                  col3->r = INTP(255, col->r, pos);
-                  col3->g = INTP(255, col->g, pos);
-                  col3->b = INTP(255, col->b, pos);
-                  col3->a = INTP(255, col->a, pos);
-                  pmap->colors[idx] = col3;
+                  col2 = p2->map->colors[j];
+                  if (col3->idx == col2->idx)
+                    {
+                       col2_r = col2->r;
+                       col2_g = col2->g;
+                       col2_b = col2->b;
+                       col2_a = col2->a;
+                       break;
+                    }
                }
-             idx++;
-             matched = EINA_FALSE;
+
+             /* interpolate!
+                if color didn't existed, then there are default 255 values */
+             col3->r = INTP(col1_r, col2_r, pos);
+             col3->g = INTP(col1_g, col2_g, pos);
+             col3->b = INTP(col1_b, col2_b, pos);
+             col3->a = INTP(col1_a, col2_a, pos);
+
+             pmap->colors[i] = col3;
           }
+
         return EINA_TRUE;
      }