1 #define EFL_GFX_HINT_PROTECTED
2 
3 #include "edje_private.h"
4 
5 #include "../evas/canvas/evas_table_eo.h"
6 
7 static void                          _edje_part_make_rtl(Edje_Part_Description_Common *desc);
8 static Edje_Part_Description_Common *_edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type);
9 
10 static void                          _edje_part_recalc_single(Edje *ed, Edje_Real_Part *ep,
11                                                               Edje_Part_Description_Common *desc,
12                                                               Edje_Part_Description_Common *chosen_desc,
13                                                               Edje_Real_Part *center,
14                                                               Edje_Real_Part *zoom_center,
15                                                               Edje_Real_Part *light, Edje_Real_Part *persp,
16                                                               Edje_Real_Part *rel1_to_x, Edje_Real_Part *rel1_to_y,
17                                                               Edje_Real_Part *rel2_to_x, Edje_Real_Part *rel2_to_y,
18                                                               Edje_Real_Part *clip_to,
19                                                               Edje_Real_Part *confine_to, Edje_Real_Part *threshold,
20                                                               Edje_Calc_Params *params,
21                                                               Evas_Coord mmw, Evas_Coord mmh,
22                                                               FLOAT_T pos);
23 
24 #define EINA_COW_CALC_PHYSICS_BEGIN(Calc, Write) \
25    _edje_calc_params_need_ext(Calc); \
26    EINA_COW_WRITE_BEGIN(_edje_calc_params_physics_cow, Calc->ext->physics, Edje_Calc_Params_Physics, Write)
27 
28 #define EINA_COW_CALC_PHYSICS_END(Calc, Write) \
29    EINA_COW_WRITE_END(_edje_calc_params_physics_cow, Calc->ext->physics, Write)
30 
31 #define EINA_COW_CALC_MAP_BEGIN(Calc, Write) \
32    _edje_calc_params_need_ext(Calc); \
33    EINA_COW_WRITE_BEGIN(_edje_calc_params_map_cow, Calc->ext->map, Edje_Calc_Params_Map, Write)
34 
35 #define EINA_COW_CALC_MAP_END(Calc, Write) \
36    EINA_COW_WRITE_END(_edje_calc_params_map_cow, Calc->ext->map, Write)
37 
38 #ifdef BUILD_EDJE_FP
39 
40 #define TYPE_EPSILON FLT_EPSILON
41 
42 #else
43 
44 #define TYPE_EPSILON DBL_EPSILON
45 
46 #endif
47 
48 void
_edje_calc_params_clear(Edje_Calc_Params * p)49 _edje_calc_params_clear(Edje_Calc_Params *p)
50 {
51    // this happens to cover type.common, type.text and type.node
52    if (p->type.common) free(p->type.common);
53    p->type.common = NULL;
54 
55    // handle cow stuff in one place
56    if (p->ext)
57      {
58 #ifdef EDJE_CALC_CACHE
59         eina_cow_free(_edje_calc_params_map_cow, (const Eina_Cow_Data **)&(p->ext->map));
60         p->ext->map = NULL;
61 # ifdef HAVE_EPHYSICS
62         eina_cow_free(_edje_calc_params_physics_cow, (const Eina_Cow_Data **)&(p->ext->physics));
63         p->ext->physics = NULL;
64 # endif
65 #endif
66         free(p->ext);
67         p->ext = NULL;
68      }
69 }
70 
71 static inline Eo *
_edje_calc_get_part_object(const Edje_Real_Part * ep)72 _edje_calc_get_part_object(const Edje_Real_Part *ep)
73 {
74    if ((ep->type == EDJE_RP_TYPE_SWALLOW) && ep->typedata.swallow &&
75        ep->typedata.swallow->swallowed_object)
76      return ep->typedata.swallow->swallowed_object;
77    return ep->object;
78 }
79 
80 static inline void
_edje_calc_handle_state_clip(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * pf)81 _edje_calc_handle_state_clip(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *pf)
82 {
83    Edje_Real_Part *clip_part = NULL;
84    Eo *clip_obj = ed->base.clipper;
85 
86    if ((pf->ext) && (pf->ext->clip_to) && (pf->ext->clip_to->object))
87      clip_part = pf->ext->clip_to;
88    else if (ep->part->clip_to_id >= 0)
89      clip_part = ed->table_parts[ep->part->clip_to_id % ed->table_parts_size];
90 
91    if (clip_part)
92      clip_obj = _edje_calc_get_part_object(clip_part);
93    evas_object_clip_set(_edje_calc_get_part_object(ep), clip_obj);
94 }
95 
96 void
_edje_part_pos_set(Edje * ed,Edje_Real_Part * ep,int mode,FLOAT_T pos,FLOAT_T v1,FLOAT_T v2,FLOAT_T v3,FLOAT_T v4)97 _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, FLOAT_T pos, FLOAT_T v1, FLOAT_T v2, FLOAT_T v3, FLOAT_T v4)
98 {
99    FLOAT_T fp_pos;
100    FLOAT_T npos;
101    double v[4];
102 
103    pos = CLAMP(pos, ZERO, FROM_INT(1));
104 
105    fp_pos = pos;
106 
107 #if 0 // old code - easy to enable for comparing float vs fixed point
108       /* take linear pos along timescale and use interpolation method */
109    switch (mode)
110      {
111       case EDJE_TWEEN_MODE_SINUSOIDAL:
112         /* npos = (1.0 - cos(pos * PI)) / 2.0; */
113         npos = DIV2(SUB(FROM_INT(1),
114                         COS(MUL(fp_pos,
115                                 PI))));
116         break;
117 
118       case EDJE_TWEEN_MODE_ACCELERATE:
119         /* npos = 1.0 - sin((PI / 2.0) + (pos * PI / 2.0)); */
120         npos = SUB(FROM_INT(1),
121                    SIN(ADD(DIV2(PI),
122                            MUL(fp_pos,
123                                DIV2(PI)))));
124         break;
125 
126       case EDJE_TWEEN_MODE_DECELERATE:
127         /* npos = sin(pos * PI / 2.0); */
128         npos = SIN(MUL(fp_pos,
129                        DIV2(PI)));
130         break;
131 
132       case EDJE_TWEEN_MODE_LINEAR:
133         npos = fp_pos;
134         break;
135 
136       default:
137         npos = fp_pos;
138         break;
139      }
140 #else
141    switch (mode & EDJE_TWEEN_MODE_MASK)
142      {
143       case EDJE_TWEEN_MODE_SINUSOIDAL:
144         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
145                                                   ECORE_POS_MAP_SINUSOIDAL,
146                                                   0.0, 0.0));
147         break;
148 
149       case EDJE_TWEEN_MODE_ACCELERATE:
150         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
151                                                   ECORE_POS_MAP_ACCELERATE,
152                                                   0.0, 0.0));
153         break;
154 
155       case EDJE_TWEEN_MODE_DECELERATE:
156         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
157                                                   ECORE_POS_MAP_DECELERATE,
158                                                   0.0, 0.0));
159         break;
160 
161       case EDJE_TWEEN_MODE_LINEAR:
162         npos = fp_pos;
163 /*        npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
164                                                   ECORE_POS_MAP_LINEAR,
165                                                   0.0, 0.0));
166  */
167         break;
168 
169       case EDJE_TWEEN_MODE_ACCELERATE_FACTOR:
170         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
171                                                   ECORE_POS_MAP_ACCELERATE_FACTOR,
172                                                   TO_DOUBLE(v1), 0.0));
173         break;
174 
175       case EDJE_TWEEN_MODE_DECELERATE_FACTOR:
176         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
177                                                   ECORE_POS_MAP_DECELERATE_FACTOR,
178                                                   TO_DOUBLE(v1), 0.0));
179         break;
180 
181       case EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR:
182         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
183                                                   ECORE_POS_MAP_SINUSOIDAL_FACTOR,
184                                                   TO_DOUBLE(v1), 0.0));
185         break;
186 
187       case EDJE_TWEEN_MODE_DIVISOR_INTERP:
188         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
189                                                   ECORE_POS_MAP_DIVISOR_INTERP,
190                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
191         break;
192 
193       case EDJE_TWEEN_MODE_BOUNCE:
194         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
195                                                   ECORE_POS_MAP_BOUNCE,
196                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
197         break;
198 
199       case EDJE_TWEEN_MODE_SPRING:
200         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
201                                                   ECORE_POS_MAP_SPRING,
202                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
203         break;
204 
205       case EDJE_TWEEN_MODE_CUBIC_BEZIER:
206         v[0] = TO_DOUBLE(v1);
207         v[1] = TO_DOUBLE(v2);
208         v[2] = TO_DOUBLE(v3);
209         v[3] = TO_DOUBLE(v4);
210 
211         npos = FROM_DOUBLE(ecore_animator_pos_map_n(TO_DOUBLE(pos),
212                                                     ECORE_POS_MAP_CUBIC_BEZIER,
213                                                     4, v));
214         break;
215 
216       default:
217         npos = fp_pos;
218         break;
219      }
220 #endif
221    if (EQ(npos, ep->description_pos)) return;
222 
223    ep->description_pos = npos;
224 
225    ed->dirty = EINA_TRUE;
226    ed->recalc_call = EINA_TRUE;
227 #ifdef EDJE_CALC_CACHE
228    ep->invalidate = EINA_TRUE;
229 #endif
230 }
231 
232 /**
233  * Returns part description
234  *
235  * @internal
236  *
237  * Converts part description to RTL-desc.
238  *
239  * @param desc Pointer to desc buffer.
240  *
241  **/
242 static void
_edje_part_make_rtl(Edje_Part_Description_Common * desc)243 _edje_part_make_rtl(Edje_Part_Description_Common *desc)
244 {
245    double t;
246    int i;
247 
248    if (!desc)
249      return;
250 
251    /* This makes alignment right-oriented */
252    desc->align.x = 1.0 - desc->align.x;
253 
254    /* same as above for relative components */
255    t = desc->rel1.relative_x;
256    desc->rel1.relative_x = 1.0 - desc->rel2.relative_x;
257    desc->rel2.relative_x = 1.0 - t;
258 
259    /* +1 and +1 are because how edje works with right
260     * side borders - nothing is printed beyond that limit
261     *
262     * rel2 is now to the left of rel1, and Edje assumes
263     * the opposite so we switch corners on x-axis to define
264     * offset from right to left */
265    i = desc->rel1.offset_x;
266    desc->rel1.offset_x = -(desc->rel2.offset_x + 1);
267    desc->rel2.offset_x = -(i + 1);
268 
269    i = desc->rel1.id_x;
270    desc->rel1.id_x = desc->rel2.id_x;
271    desc->rel2.id_x = i;
272 }
273 
274 static Edje_Part_Description_Common *
_edje_get_custom_description_by_orientation(Edje * ed,Edje_Part_Description_Common * src,Edje_Part_Description_Common ** dst,unsigned char type)275 _edje_get_custom_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type)
276 {
277    Edje_Part_Description_Common *ret;
278    size_t memsize = 0;
279 
280    /* RTL flag is not set, return original description */
281    if (!edje_object_mirrored_get(ed->obj))
282      return src;
283 
284    if (!(*dst))
285      {
286         ret = _edje_get_description_by_orientation(ed, src, dst, type);
287         return ret;
288      }
289 
290 #define POPULATE_MEMSIZE_RTL(Short, Type)                        \
291 case EDJE_PART_TYPE_##Short:                                          \
292 {                                                                     \
293    memsize = sizeof(Edje_Part_Description_##Type);                    \
294    break;                                                             \
295 }
296 
297    switch (type)
298      {
299         POPULATE_MEMSIZE_RTL(RECTANGLE, Common);
300         POPULATE_MEMSIZE_RTL(SNAPSHOT, Snapshot);
301         POPULATE_MEMSIZE_RTL(SWALLOW, Common);
302         POPULATE_MEMSIZE_RTL(GROUP, Common);
303         POPULATE_MEMSIZE_RTL(SPACER, Common);
304         POPULATE_MEMSIZE_RTL(TEXT, Text);
305         POPULATE_MEMSIZE_RTL(TEXTBLOCK, Text);
306         POPULATE_MEMSIZE_RTL(IMAGE, Image);
307         POPULATE_MEMSIZE_RTL(PROXY, Proxy);
308         POPULATE_MEMSIZE_RTL(BOX, Box);
309         POPULATE_MEMSIZE_RTL(TABLE, Table);
310         POPULATE_MEMSIZE_RTL(EXTERNAL, External);
311         POPULATE_MEMSIZE_RTL(VECTOR, Vector);
312      }
313 #undef POPULATE_MEMSIZE_RTL
314 
315    ret = *dst;
316    memcpy(ret, src, memsize);
317    _edje_part_make_rtl(ret);
318 
319    return ret;
320 }
321 
322 /**
323  * Returns part description
324  *
325  * @internal
326  *
327  * Returns part description according to object orientation.
328  * When object is in RTL-orientation (RTL flag is set)
329  * this returns the RTL-desc of it.
330  * RTL-desc would be allocated if was not created by a previous call.
331  * The dst pointer is updated in case of an allocation.
332  *
333  * @param ed Edje object.
334  * @param src The Left To Right (LTR), original desc.
335  * @param dst Pointer to Right To Left (RTL) desc-list.
336  * @param type name of dec type. Example: "default".
337  *
338  * @return Edje part description.
339  *
340  **/
341 static Edje_Part_Description_Common *
_edje_get_description_by_orientation(Edje * ed,Edje_Part_Description_Common * src,Edje_Part_Description_Common ** dst,unsigned char type)342 _edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type)
343 {
344    Edje_Part_Description_Common *desc_rtl = NULL;
345    Edje_Part_Collection_Directory_Entry *ce;
346    size_t memsize = 0;
347 
348    /* RTL flag is not set, return original description */
349    if (!edje_object_mirrored_get(ed->obj))
350      return src;
351 
352    if (*dst)
353      return *dst;  /* Was allocated before and we should use it */
354 
355 #define EDIT_ALLOC_POOL_RTL(Short, Type, Name)                        \
356 case EDJE_PART_TYPE_##Short:                                          \
357 {                                                                     \
358    Edje_Part_Description_##Type * Name;                               \
359    Name = eina_mempool_malloc(ce->mp->mp_rtl.Short,                   \
360                               sizeof (Edje_Part_Description_##Type)); \
361    desc_rtl = &Name->common;                                          \
362    memsize = sizeof(Edje_Part_Description_##Type);                    \
363    break;                                                             \
364 }
365 
366    ce = eina_hash_find(ed->file->collection, ed->group);
367 
368    switch (type)
369      {
370       case EDJE_PART_TYPE_RECTANGLE:
371         desc_rtl = eina_mempool_malloc(ce->mp->mp_rtl.RECTANGLE,
372                                        sizeof (Edje_Part_Description_Common));
373         ce->count.RECTANGLE++;
374         memsize = sizeof(Edje_Part_Description_Common);
375         break;
376 
377       case EDJE_PART_TYPE_SNAPSHOT:
378         desc_rtl = eina_mempool_malloc(ce->mp->mp_rtl.SNAPSHOT,
379                                        sizeof (Edje_Part_Description_Snapshot));
380         ce->count.SNAPSHOT++;
381         memsize = sizeof(Edje_Part_Description_Snapshot);
382         break;
383 
384       case EDJE_PART_TYPE_SWALLOW:
385         desc_rtl = eina_mempool_malloc(ce->mp->mp_rtl.SWALLOW,
386                                        sizeof (Edje_Part_Description_Common));
387         ce->count.SWALLOW++;
388         memsize = sizeof(Edje_Part_Description_Common);
389         break;
390 
391       case EDJE_PART_TYPE_GROUP:
392         desc_rtl = eina_mempool_malloc(ce->mp->mp_rtl.GROUP,
393                                        sizeof (Edje_Part_Description_Common));
394         ce->count.GROUP++;
395         memsize = sizeof(Edje_Part_Description_Common);
396         break;
397 
398       case EDJE_PART_TYPE_SPACER:
399         desc_rtl = eina_mempool_malloc(ce->mp->mp_rtl.SPACER,
400                                        sizeof (Edje_Part_Description_Common));
401         ce->count.SPACER++;
402         memsize = sizeof(Edje_Part_Description_Common);
403         break;
404         EDIT_ALLOC_POOL_RTL(TEXT, Text, text);
405         EDIT_ALLOC_POOL_RTL(TEXTBLOCK, Text, text);
406         EDIT_ALLOC_POOL_RTL(IMAGE, Image, image);
407         EDIT_ALLOC_POOL_RTL(PROXY, Proxy, proxy);
408         EDIT_ALLOC_POOL_RTL(BOX, Box, box);
409         EDIT_ALLOC_POOL_RTL(TABLE, Table, table);
410         EDIT_ALLOC_POOL_RTL(EXTERNAL, External, external_params);
411         EDIT_ALLOC_POOL_RTL(VECTOR, Vector, vector);
412      }
413 
414    if (desc_rtl)
415      memcpy(desc_rtl, src, memsize);
416 
417    _edje_part_make_rtl(desc_rtl);
418 
419    *dst = desc_rtl;
420    return desc_rtl;
421 }
422 
423 Edje_Part_Description_Common *
_edje_part_description_find(Edje * ed,Edje_Real_Part * rp,const char * state_name,double state_val,Eina_Bool approximate)424 _edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *state_name,
425                             double state_val, Eina_Bool approximate)
426 {
427    Edje_Part *ep = rp->part;
428    Edje_Part_Description_Common *ret = NULL;
429    Edje_Part_Description_Common *d;
430 
431    double min_dst = 99999.0;
432    unsigned int i;
433 
434    /* RTL flag is set, return RTL description */
435    if (edje_object_mirrored_get(ed->obj) && !ep->other.desc_rtl)
436      {
437         ep->other.desc_rtl = (Edje_Part_Description_Common **)
438            calloc(ep->other.desc_count,
439                   sizeof (Edje_Part_Description_Common *));
440      }
441 
442    if (!strcmp(state_name, "default") && EQ(state_val, ZERO))
443      return _edje_get_description_by_orientation(ed,
444                                                  ep->default_desc, &ep->default_desc_rtl, ep->type);
445 
446    if (!strcmp(state_name, "custom"))
447      return rp->custom ?
448             _edje_get_custom_description_by_orientation(ed, rp->custom->description,
449                                                        &rp->custom->description_rtl, ep->type) : NULL;
450 
451    if (!strcmp(state_name, "default") && approximate)
452      {
453         ret = _edje_get_description_by_orientation(ed, ep->default_desc,
454                                                    &ep->default_desc_rtl,
455                                                    ep->type);
456 
457         min_dst = ABS(ep->default_desc->state.value - state_val);
458      }
459 
460    for (i = 0; i < ep->other.desc_count; ++i)
461      {
462         d = ep->other.desc[i];
463 
464         if (d->state.name && (d->state.name == state_name ||
465                               !strcmp(d->state.name, state_name)))
466           {
467              if (!approximate)
468                {
469                   if (EQ(d->state.value, state_val))
470                     return _edje_get_description_by_orientation(ed, d,
471                                                                 &ep->other.desc_rtl[i], ep->type);
472                   else
473                     continue;
474                }
475              else
476                {
477                   double dst;
478 
479                   dst = ABS(d->state.value - state_val);
480                   if (dst < min_dst)
481                     {
482                        ret = _edje_get_description_by_orientation(ed, d,
483                                                                   &ep->other.desc_rtl[i], ep->type);
484                        min_dst = dst;
485                     }
486                }
487           }
488      }
489 
490    return ret;
491 }
492 
493 static int
_edje_image_set_fill(Edje_Real_Part_Set ** eps,Edje_Image_Directory_Set_Entry * entry,Edje_Image_Directory_Set * set,int id)494 _edje_image_set_fill(Edje_Real_Part_Set **eps,
495                      Edje_Image_Directory_Set_Entry *entry,
496                      Edje_Image_Directory_Set *set,
497                      int id)
498 {
499    if (eps)
500      {
501         if (!*eps) *eps = calloc(1, sizeof(Edje_Real_Part_Set));
502         if (*eps)
503           {
504              (*eps)->entry = entry;
505              (*eps)->set = set;
506              (*eps)->id = id;
507           }
508      }
509    return entry->id;
510 }
511 
512 static int
_edje_image_find(Evas_Object * obj,Edje * ed,Edje_Real_Part_Set ** eps,Edje_Part_Description_Image * st,Edje_Part_Image_Id * imid)513 _edje_image_find(Evas_Object *obj, Edje *ed, Edje_Real_Part_Set **eps,
514                  Edje_Part_Description_Image *st, Edje_Part_Image_Id *imid)
515 {
516    Edje_Image_Directory_Set_Entry *entry;
517    Edje_Image_Directory_Set *set = NULL;
518    Eina_List *l;
519    int w = 0, h = 0, id, maxw = 0, maxh = 0;
520 
521    if (!st && !imid) return -1;
522    if (st && !st->image.set) return st->image.id;
523    if (imid && !imid->set) return imid->id;
524 
525    if (imid) id = imid->id;
526    else id = st->image.id;
527 
528    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
529    if (eps && *eps)
530      {
531         if ((*eps)->id == id) set = (*eps)->set;
532         if (set)
533           {
534              if (((*eps)->entry->size.min.w <= w) &&
535                  (w <= (*eps)->entry->size.max.w))
536                {
537                   if (((*eps)->entry->size.min.h <= h) &&
538                       (h <= (*eps)->entry->size.max.h))
539                     return (*eps)->entry->id;
540                }
541           }
542      }
543 
544    if (!set) set = ed->file->image_dir->sets + id;
545 
546    if (set->entries)
547      evas_image_max_size_get(evas_object_evas_get(obj), &maxw, &maxh);
548    EINA_LIST_FOREACH(set->entries, l, entry)
549      {
550         // skip images b
551         if ((entry->size.w > 0) && (entry->size.h > 0) &&
552             ((w > entry->size.w) || (h > entry->size.h)))
553           continue;
554         // skip images that exceed max size
555         if ((maxw > 0) && (maxh > 0) &&
556             ((entry->size.w > maxw) || (entry->size.h > maxh)))
557           continue;
558         if ((entry->size.min.w <= w) && (w <= entry->size.max.w))
559           {
560              if ((entry->size.min.h <= h) && (h <= entry->size.max.h))
561                return _edje_image_set_fill(eps, entry, set, id);
562           }
563      }
564    // nothing found so pick first - which shouldbe smallest
565    entry = eina_list_data_get(set->entries);
566    if (entry)
567      return _edje_image_set_fill(eps, entry, set, id);
568 
569    return -1;
570 }
571 
572 static void
_edje_real_part_image_error_check(Edje_Real_Part * ep)573 _edje_real_part_image_error_check(Edje_Real_Part *ep)
574 {
575    switch (evas_object_image_load_error_get(ep->object))
576      {
577       case EVAS_LOAD_ERROR_GENERIC:
578         ERR("Error type: EVAS_LOAD_ERROR_GENERIC");
579         break;
580 
581       case EVAS_LOAD_ERROR_DOES_NOT_EXIST:
582         ERR("Error type: EVAS_LOAD_ERROR_DOES_NOT_EXIST");
583         break;
584 
585       case EVAS_LOAD_ERROR_PERMISSION_DENIED:
586         ERR("Error type: EVAS_LOAD_ERROR_PERMISSION_DENIED");
587         break;
588 
589       case EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED:
590         ERR("Error type: EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
591         break;
592 
593       case EVAS_LOAD_ERROR_CORRUPT_FILE:
594         ERR("Error type: EVAS_LOAD_ERROR_CORRUPT_FILE");
595         break;
596 
597       case EVAS_LOAD_ERROR_UNKNOWN_FORMAT:
598         ERR("Error type: EVAS_LOAD_ERROR_UNKNOWN_FORMAT");
599         break;
600 
601       default:
602         ERR("Error type: ???");
603         break;
604      }
605 }
606 
607 static Eina_Bool
_edje_real_part_image_internal_set(Edje_File * edf,Edje_Real_Part * ep,int image_id)608 _edje_real_part_image_internal_set(Edje_File *edf, Edje_Real_Part *ep, int image_id)
609 {
610    char buf[1024] = "edje/images/";
611 
612    /* Replace snprint("edje/images/%i") == memcpy + itoa */
613    eina_convert_itoa(image_id, buf + 12); /* No need to check length as 2³² need only 10 characteres. */
614 
615    evas_object_image_mmap_set(ep->object, edf->f, buf);
616    if (evas_object_image_load_error_get(ep->object) != EVAS_LOAD_ERROR_NONE)
617      {
618         ERR("Error loading image collection \"%s\" from "
619             "file \"%s\". Missing EET Evas loader module?",
620             buf, edf->path);
621         _edje_real_part_image_error_check(ep);
622         return EINA_FALSE;
623      }
624    return EINA_TRUE;
625 }
626 
627 static Eina_Bool
_edje_real_part_image_external_set(Edje_File * edf,Edje_Real_Part * ep,int image_id)628 _edje_real_part_image_external_set(Edje_File *edf, Edje_Real_Part *ep, int image_id)
629 {
630    Edje_Image_Directory_Entry *ie;
631 
632    if (!edf->image_dir) return EINA_FALSE;
633    ie = edf->image_dir->entries + (-image_id) - 1;
634    if ((ie) &&
635        (ie->source_type == EDJE_IMAGE_SOURCE_TYPE_USER) &&
636        (ie->entry))
637      {
638         evas_object_image_file_set(ep->object, ie->entry, NULL);
639         _edje_real_part_image_error_check(ep);
640         return EINA_TRUE;
641      }
642    else if ((ie) &&
643        (ie->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
644        (ie->entry))
645      {
646         Edje_File *edff;
647         Eina_List *l, *ll;
648 
649         l = eina_hash_find(_edje_id_hash, ie->external_id);
650         EINA_LIST_FOREACH(l, ll, edff)
651           {
652              Edje_Image_Hash *eih = eina_hash_find(edff->image_id_hash, ie->entry);
653 
654              if (!eih) continue;
655              if (eih->id < 0)
656                return _edje_real_part_image_external_set(edff, ep, eih->id);
657              else
658                _edje_real_part_image_internal_set(edff, ep, eih->id);
659              return EINA_TRUE;
660           }
661         return EINA_FALSE;
662      }
663    return EINA_FALSE;
664 }
665 
666 static void
_edje_real_part_image_set(Edje * ed,Edje_Real_Part * ep,Edje_Real_Part_Set ** set,FLOAT_T pos)667 _edje_real_part_image_set(Edje *ed, Edje_Real_Part *ep, Edje_Real_Part_Set **set, FLOAT_T pos)
668 {
669    int image_id;
670    int image_count, image_num;
671 
672    image_id = _edje_image_find(ep->object, ed,
673                                &ep->param1.set,
674                                (Edje_Part_Description_Image *)ep->param1.description,
675                                NULL);
676    if (set) *set = ep->param1.set;
677    if (image_id < 0)
678      {
679         _edje_real_part_image_external_set(ed->file, ep, image_id);
680      }
681    else
682      {
683         image_count = 2;
684         if (ep->param2)
685           image_count += ((Edje_Part_Description_Image *)ep->param2->description)->image.tweens_count;
686         image_num = TO_INT(MUL(pos, SUB(FROM_INT(image_count),
687                                         FROM_DOUBLE(0.5))));
688         if (image_num > (image_count - 1))
689           image_num = image_count - 1;
690         if (image_num <= 0)
691           {
692              image_id = _edje_image_find(ep->object, ed,
693                                          &ep->param1.set,
694                                          (Edje_Part_Description_Image *)ep->param1.description,
695                                          NULL);
696              if (set) *set = ep->param1.set;
697           }
698         else
699         if (ep->param2)
700           {
701              if (image_num == (image_count - 1))
702                {
703                   image_id = _edje_image_find(ep->object, ed,
704                                               &ep->param2->set,
705                                               (Edje_Part_Description_Image *)ep->param2->description,
706                                               NULL);
707                   if (set) *set = ep->param2->set;
708                }
709              else
710                {
711                   Edje_Part_Image_Id *imid;
712 
713                   imid = ((Edje_Part_Description_Image *)ep->param2->description)->image.tweens[image_num - 1];
714                   image_id = _edje_image_find(ep->object, ed, NULL, NULL, imid);
715                   if (set) *set = NULL;
716                }
717           }
718         if (image_id < 0)
719           {
720              if (!_edje_real_part_image_external_set(ed->file, ep, image_id))
721                ERR("Part \"%s\" description, "
722                    "\"%s\" %3.3f with image %i index has a missing image id in a set of %i !!!",
723                    ep->part->name,
724                    ep->param1.description->state.name,
725                    ep->param1.description->state.value,
726                    image_num,
727                    image_count);
728           }
729         else
730           {
731              _edje_real_part_image_internal_set(ed->file, ep, image_id);
732           }
733      }
734 }
735 
736 static void
_edje_real_part_rel_to_apply(Edje * ed EINA_UNUSED,Edje_Real_Part * ep,Edje_Real_Part_State * state)737 _edje_real_part_rel_to_apply(Edje *ed EINA_UNUSED,
738                              Edje_Real_Part *ep,
739                              Edje_Real_Part_State *state)
740 {
741    if (state->description)
742      {
743         if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
744           {
745              Edje_Part_Description_External *external;
746 
747              if ((ep->type != EDJE_RP_TYPE_SWALLOW) ||
748                  (!ep->typedata.swallow)) return;
749 
750              external = (Edje_Part_Description_External *)state->description;
751 
752              if (state->external_params)
753                _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object, state->external_params);
754              state->external_params = _edje_external_params_parse(ep->typedata.swallow->swallowed_object, external->external_params);
755           }
756      }
757 }
758 
759 void
_edje_part_description_apply(Edje * ed,Edje_Real_Part * ep,const char * d1,double v1,const char * d2,double v2)760 _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, double v1, const char *d2, double v2)
761 {
762    Edje_Part_Description_Common *epd1;
763    Edje_Part_Description_Common *epd2 = NULL;
764    Edje_Part_Description_Common *last_desc;
765    Eina_Bool change_w, change_h;
766    Edje_Part_Description_Image *epdi;
767 
768    if (!d1) d1 = "default";
769 
770    epd1 = _edje_part_description_find(ed, ep, d1, v1, EINA_TRUE);
771    if (!epd1)
772      {
773         ERR("Cannot find description \"%s\" in part \"%s\" from group \"%s\". Fallback to default description.",
774             d1, ep->part->name, ed->group);
775         epd1 = _edje_get_description_by_orientation(ed, ep->part->default_desc,
776                                                     &ep->part->default_desc_rtl,
777                                                     ep->type); /* never NULL */
778      }
779 
780    if (d2)
781      epd2 = _edje_part_description_find(ed, ep, d2, v2, EINA_TRUE);
782 
783    epdi = (Edje_Part_Description_Image *)epd2;
784    /* There is an animation if both description are different or if description is an image with tweens */
785    if (epd2 && (epd1 != epd2 || (ep->part->type == EDJE_PART_TYPE_IMAGE && epdi->image.tweens_count)))
786      {
787         if (!ep->param2)
788           {
789              ep->param2 = eina_mempool_malloc(_edje_real_part_state_mp,
790                                               sizeof(Edje_Real_Part_State));
791              if (ep->param2)
792                memset(ep->param2, 0, sizeof(Edje_Real_Part_State));
793           }
794         else if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
795           {
796              if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
797                  (ep->typedata.swallow))
798                _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object,
799                                                  ep->param2->external_params);
800           }
801         if (ep->param2)
802           ep->param2->external_params = NULL;
803      }
804    else
805    if (ep->param2)
806      {
807         if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
808           {
809              if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
810                  (ep->typedata.swallow))
811                _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object,
812                                                  ep->param2->external_params);
813           }
814         if (ep->param2)
815           {
816              free(ep->param2->set);
817 #ifdef EDJE_CALC_CACHE
818              _edje_calc_params_clear(&(ep->param2->p));
819 #endif
820           }
821         eina_mempool_free(_edje_real_part_state_mp, ep->param2);
822         ep->param2 = NULL;
823      }
824 
825    last_desc = ep->chosen_description;
826    ep->param1.description = epd1;
827    ep->chosen_description = epd1;
828    if (last_desc)
829      {
830         change_w = ep->chosen_description->fixed.w != last_desc->fixed.w;
831         change_h = ep->chosen_description->fixed.h != last_desc->fixed.h;
832      }
833    _edje_real_part_rel_to_apply(ed, ep, &ep->param1);
834 
835    if (ep->param2)
836      {
837         ep->param2->description = epd2;
838 
839         _edje_real_part_rel_to_apply(ed, ep, ep->param2);
840 
841         if (ep->description_pos > FROM_DOUBLE(0.0))
842           ep->chosen_description = epd2;
843      }
844 
845    if (last_desc != ep->chosen_description)
846      {
847         if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
848           _edje_external_recalc_apply(ed, ep, NULL, last_desc);
849         else if ((last_desc) && (ep->part->type == EDJE_PART_TYPE_GROUP))
850           {
851              Edje_Size *min, *max, *pmin, *pmax;
852 
853              min = &ep->chosen_description->min;
854              max = &ep->chosen_description->max;
855              pmin = &last_desc->min;
856              pmax = &last_desc->max;
857              if (change_w || change_h ||
858                  (((pmin->w == pmax->w) && (pmin->h == pmax->h) && (pmin->w > 0) && (pmin->h > 0)) &&
859                   (((min->w != max->w) || (min->h != max->h) || (min->w <= 0) || (min->h <= 0)))))
860                {
861                   Edje *ted = _edje_fetch(ep->typedata.swallow->swallowed_object);
862                   if (ted)
863                     {
864                        ted->recalc_call = ted->dirty = ted->recalc_hints = EINA_TRUE;
865                        _edje_recalc(ted);
866                     }
867                }
868 
869              edje_object_mirrored_set(ep->typedata.swallow->swallowed_object,
870                    edje_object_mirrored_get(ed->obj));
871           }
872      }
873 
874    ed->recalc_hints = EINA_TRUE;
875    ed->dirty = EINA_TRUE;
876    ed->recalc_call = EINA_TRUE;
877 #ifdef EDJE_CALC_CACHE
878    ep->invalidate = EINA_TRUE;
879 #endif
880 }
881 
882 void
_edje_recalc(Edje * ed)883 _edje_recalc(Edje *ed)
884 {
885    if ((ed->freeze > 0) || (_edje_util_freeze_val > 0))
886      {
887         ed->recalc = EINA_TRUE;
888         if (!ed->calc_only)
889           {
890              if (_edje_util_freeze_val > 0)
891                {
892                   if (!ed->freeze_calc)
893                     {
894                        _edje_util_freeze_calc_count++;
895                        _edje_util_freeze_calc_list = eina_list_append(_edje_util_freeze_calc_list, ed);
896                        ed->freeze_calc = EINA_TRUE;
897                     }
898                }
899              return;
900           }
901      }
902 
903    evas_object_smart_changed(ed->obj);
904 }
905 
906 static
907 #ifdef EDJE_CALC_CACHE
908 Eina_Bool
909 #else
910 void
911 #endif
_edje_recalc_table_parts(Edje * ed,Eina_Bool need_reinit_state)912 _edje_recalc_table_parts(Edje *ed
913 #ifdef EDJE_CALC_CACHE
914                          , Eina_Bool need_reinit_state
915 #endif
916                         )
917 {
918    unsigned short i;
919    Edje_Real_Part *ep;
920 
921    for (i = 0; i < ed->table_parts_size; i++)
922      {
923         ep = ed->table_parts[i];
924         ep->calculated = FLAG_NONE; // FIXME: this is dubious (see below)
925         ep->calculating = FLAG_NONE;
926 #ifdef EDJE_CALC_CACHE
927         if (need_reinit_state)
928           {
929              ep->state = 0;
930              ep->param1.state = 0;
931              if (ep->param2) ep->param2->state = 0;
932           }
933 #endif
934      }
935    for (i = 0; i < ed->table_parts_size; i++)
936      {
937         ep = ed->table_parts[i];
938 
939         if (ep->calculated != FLAG_XY) // FIXME: this is always true (see for above)
940           _edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY, NULL);
941      }
942 #ifdef EDJE_CALC_CACHE
943    return need_reinit_state;
944 #endif
945 }
946 
947 void
_edje_recalc_do(Edje * ed)948 _edje_recalc_do(Edje *ed)
949 {
950    unsigned short i;
951    Eina_Bool need_calc;
952 #ifdef EDJE_CALC_CACHE
953    Eina_Bool need_reinit_state = EINA_FALSE;
954 #endif
955 
956    ed->has_size = EINA_TRUE;
957 
958    need_calc = evas_object_smart_need_recalculate_get(ed->obj);
959    evas_object_smart_need_recalculate_set(ed->obj, 0);
960    if (!ed->dirty) return;
961    ed->dirty = EINA_FALSE;
962    ed->state++;
963 
964    /* Avoid overflow problem */
965    if (ed->state == USHRT_MAX)
966      {
967         ed->state = 0;
968 #ifdef EDJE_CALC_CACHE
969         need_reinit_state = EINA_TRUE;
970 #endif
971      }
972 
973    if (EINA_LIKELY(ed->table_parts_size > 0))
974 #ifdef EDJE_CALC_CACHE
975      need_reinit_state =
976 #endif
977        _edje_recalc_table_parts(ed
978 #ifdef EDJE_CALC_CACHE
979                                 , need_reinit_state
980 #endif
981                                );
982 
983    if (!ed->calc_only) ed->recalc = EINA_FALSE;
984 #ifdef EDJE_CALC_CACHE
985    ed->all_part_change = EINA_FALSE;
986    ed->text_part_change = EINA_FALSE;
987 #endif
988    if (!ed->calc_only)
989      {
990         if (ed->recalc_call && ed->has_recalc_event_cb)
991           efl_event_callback_legacy_call(ed->obj, EFL_LAYOUT_EVENT_RECALC, NULL);
992      }
993    else
994      evas_object_smart_need_recalculate_set(ed->obj, need_calc);
995    ed->recalc_call = EINA_FALSE;
996 
997    if (ed->update_hints && ed->recalc_hints && !ed->calc_only)
998      {
999         Eina_Size2D min;
1000 
1001         ed->recalc_hints = EINA_FALSE;
1002 
1003         edje_object_size_min_calc(ed->obj, &min.w, &min.h);
1004         efl_gfx_hint_size_restricted_min_set(ed->obj, min);
1005      }
1006 
1007    if (!ed->collection) return;
1008 
1009    for (i = 0; i < ed->collection->limits.parts_count; i++)
1010      {
1011         const char *name;
1012         unsigned char limit;
1013         int part;
1014 
1015         part = ed->collection->limits.parts[i].part;
1016         name = ed->collection->parts[part]->name;
1017         limit = ed->table_parts[part]->chosen_description->limit;
1018         switch (limit)
1019           {
1020            case 0:
1021              ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_UNKNOWN;
1022              ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_UNKNOWN;
1023              break;
1024 
1025            case 1:
1026              ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_UNKNOWN;
1027              break;
1028 
1029            case 2:
1030              ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_UNKNOWN;
1031              break;
1032 
1033            case 3:
1034              break;
1035           }
1036 
1037         if ((limit & 1) == 1)
1038           {
1039              if (ed->table_parts[part]->w > 0 &&
1040                  (ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_OVER))
1041                {
1042                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_OVER;
1043                   _edje_emit(ed, "limit,width,over", name);
1044                }
1045              else if (ed->table_parts[part]->w < 0 &&
1046                       ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_BELOW)
1047                {
1048                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_BELOW;
1049                   _edje_emit(ed, "limit,width,below", name);
1050                }
1051              else if (ed->table_parts[part]->w == 0 &&
1052                       ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_ZERO)
1053                {
1054                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_ZERO;
1055                   _edje_emit(ed, "limit,width,zero", name);
1056                }
1057           }
1058         if ((limit & 2) == 2)
1059           {
1060              if (ed->table_parts[part]->h > 0 &&
1061                  (ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_OVER))
1062                {
1063                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_OVER;
1064                   _edje_emit(ed, "limit,height,over", name);
1065                }
1066              else if (ed->table_parts[part]->h < 0 &&
1067                       ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_BELOW)
1068                {
1069                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_BELOW;
1070                   _edje_emit(ed, "limit,height,below", name);
1071                }
1072              else if (ed->table_parts[part]->h == 0 &&
1073                       ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_ZERO)
1074                {
1075                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_ZERO;
1076                   _edje_emit(ed, "limit,height,zero", name);
1077                }
1078           }
1079      }
1080 }
1081 
1082 int
_edje_part_dragable_calc(Edje * ed EINA_UNUSED,Edje_Real_Part * ep,FLOAT_T * x,FLOAT_T * y)1083 _edje_part_dragable_calc(Edje *ed EINA_UNUSED, Edje_Real_Part *ep, FLOAT_T *x, FLOAT_T *y)
1084 {
1085    if (ep->drag)
1086      {
1087         Eina_Bool tx = EINA_FALSE;
1088         Eina_Bool ty = EINA_FALSE;
1089 
1090         if (ep->drag->threshold)
1091           {
1092              // Check if we are in the threshold or not and cancel the movement.
1093              tx = ep->drag->threshold_x && ep->drag->threshold_started_x;
1094              ty = ep->drag->threshold_y && ep->drag->threshold_started_y;
1095           }
1096         if (ep->drag->confine_to)
1097           {
1098              FLOAT_T dx, dy, dw, dh;
1099              int ret = 0;
1100 
1101              if ((ep->part->dragable.x != 0) &&
1102                  (ep->part->dragable.y != 0)) ret = 3;
1103              else if (ep->part->dragable.x != 0)
1104                ret = 1;
1105              else if (ep->part->dragable.y != 0)
1106                ret = 2;
1107 
1108              dx = FROM_INT(ep->x - ep->drag->confine_to->x);
1109              dw = FROM_INT(ep->drag->confine_to->w - ep->w);
1110              if (NEQ(dw, ZERO)) dx = DIV(dx, dw);
1111              else dx = ZERO;
1112 
1113              dy = FROM_INT(ep->y - ep->drag->confine_to->y);
1114              dh = FROM_INT(ep->drag->confine_to->h - ep->h);
1115              if (NEQ(dh, ZERO)) dy = DIV(dy, dh);
1116              else dy = ZERO;
1117 
1118              if (x) *x = tx ? ep->drag->x : dx;
1119              if (y) *y = ty ? ep->drag->y : dy;
1120 
1121              return ret;
1122           }
1123         else
1124           {
1125              if (x) *x = tx ? ep->drag->x : ADD(FROM_INT(ep->drag->tmp.x), ep->drag->x);
1126              if (y) *y = ty ? ep->drag->y : ADD(FROM_INT(ep->drag->tmp.y), ep->drag->y);
1127              return 0;
1128           }
1129      }
1130    if (x) *x = ZERO;
1131    if (y) *y = ZERO;
1132    return 0;
1133 }
1134 
1135 void
_edje_dragable_pos_set(Edje * ed,Edje_Real_Part * ep,FLOAT_T x,FLOAT_T y)1136 _edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, FLOAT_T x, FLOAT_T y)
1137 {
1138    /* check whether this part is dragable at all */
1139    if (!ep->drag) return;
1140    if (ep->drag->down.count > 0) return;
1141 
1142    /* instead of checking for equality, we really should check that
1143     * the difference is greater than foo, but I have no idea what
1144     * value we would set foo to, because it would depend on the
1145     * size of the dragable...
1146     */
1147 
1148    if (NEQ(ep->drag->x, x) || ep->drag->tmp.x)
1149      {
1150         ep->drag->x = x;
1151         ep->drag->tmp.x = 0;
1152         ep->drag->need_reset = 0;
1153         ed->dirty = EINA_TRUE;
1154         ed->recalc_call = EINA_TRUE;
1155      }
1156 
1157    if (NEQ(ep->drag->y, y) || ep->drag->tmp.y)
1158      {
1159         ep->drag->y = y;
1160         ep->drag->tmp.y = 0;
1161         ep->drag->need_reset = 0;
1162         ed->dirty = EINA_TRUE;
1163         ed->recalc_call = EINA_TRUE;
1164      }
1165 
1166 #ifdef EDJE_CALC_CACHE
1167    ep->invalidate = EINA_TRUE;
1168 #endif
1169    _edje_recalc(ed); /* won't do anything if dirty flag isn't set */
1170 }
1171 
1172 static void
_edje_part_recalc_single_rel(Edje * ed,Edje_Real_Part * ep EINA_UNUSED,Edje_Part_Description_Common * desc,Edje_Real_Part * rel1_to_x,Edje_Real_Part * rel1_to_y,Edje_Real_Part * rel2_to_x,Edje_Real_Part * rel2_to_y,Edje_Calc_Params * params)1173 _edje_part_recalc_single_rel(Edje *ed,
1174                              Edje_Real_Part *ep EINA_UNUSED,
1175                              Edje_Part_Description_Common *desc,
1176                              Edje_Real_Part *rel1_to_x,
1177                              Edje_Real_Part *rel1_to_y,
1178                              Edje_Real_Part *rel2_to_x,
1179                              Edje_Real_Part *rel2_to_y,
1180                              Edje_Calc_Params *params)
1181 {
1182    FLOAT_T x, w;
1183    FLOAT_T y, h;
1184    FLOAT_T offset, sc;
1185    Eina_Bool offset_is_scaled = (desc->offset_is_scaled) && (ep->part->scale);
1186 
1187    if (offset_is_scaled)
1188      {
1189         sc = DIV(ed->scale, ed->file->base_scale);
1190         if (EQ(sc, ZERO)) sc = DIV(_edje_scale, ed->file->base_scale);
1191      }
1192 
1193    if (offset_is_scaled)
1194      offset = SCALE(sc, desc->rel1.offset_x);
1195    else
1196      offset = FROM_INT(desc->rel1.offset_x);
1197 
1198    if (rel1_to_x)
1199      x = ADD(ADD(offset, FROM_INT(rel1_to_x->x)),
1200              SCALE(desc->rel1.relative_x, rel1_to_x->w));
1201    else
1202      x = ADD(offset,
1203              SCALE(desc->rel1.relative_x, ed->w));
1204    params->eval.x = x;
1205 
1206    if (offset_is_scaled)
1207      offset = SUB(SCALE(sc, desc->rel2.offset_x + 1), FROM_INT(1));
1208    else
1209      offset = FROM_INT(desc->rel2.offset_x);
1210 
1211    if (rel2_to_x)
1212      w = ADD(SUB(ADD(ADD(offset, FROM_INT(rel2_to_x->x)),
1213                      SCALE(desc->rel2.relative_x, rel2_to_x->w)),
1214                  x),
1215              FROM_INT(1));
1216    else
1217      w = ADD(SUB(ADD(offset,
1218                      SCALE(desc->rel2.relative_x, ed->w)),
1219                  x),
1220              FROM_INT(1));
1221    params->eval.w = w;
1222 
1223 
1224    if (offset_is_scaled)
1225      offset = SCALE(sc, desc->rel1.offset_y);
1226    else
1227      offset = FROM_INT(desc->rel1.offset_y);
1228 
1229    if (rel1_to_y)
1230      y = ADD(ADD(offset, FROM_INT(rel1_to_y->y)),
1231              SCALE(desc->rel1.relative_y, rel1_to_y->h));
1232    else
1233      y = ADD(offset,
1234              SCALE(desc->rel1.relative_y, ed->h));
1235    params->eval.y = y;
1236 
1237    if (offset_is_scaled)
1238      offset = SUB(SCALE(sc, desc->rel2.offset_y + 1), FROM_INT(1));
1239    else
1240      offset = FROM_INT(desc->rel2.offset_y);
1241 
1242    if (rel2_to_y)
1243      h = ADD(SUB(ADD(ADD(offset, FROM_INT(rel2_to_y->y)),
1244                      SCALE(desc->rel2.relative_y, rel2_to_y->h)),
1245                  y),
1246              FROM_INT(1));
1247    else
1248      h = ADD(SUB(ADD(offset,
1249                      SCALE(desc->rel2.relative_y, ed->h)),
1250                  y),
1251              FROM_INT(1));
1252    params->eval.h = h;
1253 }
1254 
1255 static Edje_Internal_Aspect
_edje_part_recalc_single_aspect(Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Common * desc,Edje_Calc_Params * params,int * minw,int * minh,int * maxw,int * maxh,FLOAT_T pos)1256 _edje_part_recalc_single_aspect(Edje *ed,
1257                                 Edje_Real_Part *ep,
1258                                 Edje_Part_Description_Common *desc,
1259                                 Edje_Calc_Params *params,
1260                                 int *minw, int *minh,
1261                                 int *maxw, int *maxh,
1262                                 FLOAT_T pos)
1263 {
1264    Edje_Internal_Aspect apref = EDJE_ASPECT_PREFER_NONE;
1265    FLOAT_T aspect, amax, amin;
1266    FLOAT_T new_w = ZERO, new_h = ZERO, want_x, want_y, want_w, want_h;
1267 
1268    if (params->eval.h <= ZERO) aspect = FROM_INT(999999);
1269    else aspect = DIV(params->eval.w, params->eval.h);
1270    amax = desc->aspect.max;
1271    amin = desc->aspect.min;
1272    if (desc->aspect.prefer == EDJE_ASPECT_PREFER_SOURCE &&
1273        ep->part->type == EDJE_PART_TYPE_IMAGE)
1274      {
1275         Evas_Coord w, h;
1276 
1277         /* We only need pose to find the right image that would be displayed,
1278            and the right aspect ratio in that case */
1279         _edje_real_part_image_set(ed, ep, NULL, pos);
1280         evas_object_image_size_get(ep->object, &w, &h);
1281         amin = amax = DIV(FROM_INT(w), FROM_INT(h));
1282      }
1283    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
1284        (ep->typedata.swallow))
1285      {
1286         if ((ep->typedata.swallow->swallow_params.aspect.w > 0) &&
1287             (ep->typedata.swallow->swallow_params.aspect.h > 0))
1288           amin = amax =
1289               DIV(FROM_INT(ep->typedata.swallow->swallow_params.aspect.w),
1290                   FROM_INT(ep->typedata.swallow->swallow_params.aspect.h));
1291      }
1292    want_x = params->eval.x;
1293    want_w = new_w = params->eval.w;
1294 
1295    want_y = params->eval.y;
1296    want_h = new_h = params->eval.h;
1297 
1298    if ((amin > ZERO) && (amax > ZERO))
1299      {
1300         apref = desc->aspect.prefer;
1301         if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
1302             (ep->typedata.swallow))
1303           {
1304              if (ep->typedata.swallow->swallow_params.aspect.mode > EDJE_ASPECT_CONTROL_NONE)
1305                {
1306                   switch (ep->typedata.swallow->swallow_params.aspect.mode)
1307                     {
1308                      case EDJE_ASPECT_CONTROL_NEITHER:
1309                        apref = EDJE_ASPECT_PREFER_NONE;
1310                        break;
1311 
1312                      case EDJE_ASPECT_CONTROL_HORIZONTAL:
1313                        apref = EDJE_ASPECT_PREFER_HORIZONTAL;
1314                        break;
1315 
1316                      case EDJE_ASPECT_CONTROL_VERTICAL:
1317                        apref = EDJE_ASPECT_PREFER_VERTICAL;
1318                        break;
1319 
1320                      case EDJE_ASPECT_CONTROL_BOTH:
1321                        apref = EDJE_ASPECT_PREFER_BOTH;
1322                        break;
1323 
1324                      default:
1325                        break;
1326                     }
1327                }
1328           }
1329         switch (apref)
1330           {
1331            case EDJE_ASPECT_PREFER_NONE:
1332              /* keep both dimensions in check */
1333              /* adjust for min aspect (width / height) */
1334              if (aspect < amin)
1335                {
1336                   new_h = DIV(params->eval.w, amin);
1337                   new_w = MUL(amin, params->eval.h);
1338                }
1339              /* adjust for max aspect (width / height) */
1340              if (aspect > amax)
1341                {
1342                   new_h = DIV(params->eval.w, amax);
1343                   new_w = MUL(amax, params->eval.h);
1344                }
1345              if (new_w < params->eval.w)
1346                {
1347                   new_w = params->eval.w;
1348                   new_h = DIV(params->eval.w, amax);
1349                }
1350              if (new_h < params->eval.h)
1351                {
1352                   new_w = MUL(amax, params->eval.h);
1353                   new_h = params->eval.h;
1354                }
1355              break;
1356 
1357            /* prefer vertical size as determiner */
1358            case  EDJE_ASPECT_PREFER_VERTICAL:
1359              /* keep both dimensions in check */
1360              /* adjust for max aspect (width / height) */
1361              if (aspect > amax)
1362                new_w = MUL(amax, params->eval.h);
1363              /* adjust for min aspect (width / height) */
1364              if (aspect < amin)
1365                new_w = MUL(amin, params->eval.h);
1366              break;
1367 
1368            /* prefer horizontal size as determiner */
1369            case EDJE_ASPECT_PREFER_HORIZONTAL:
1370              /* keep both dimensions in check */
1371              /* adjust for max aspect (width / height) */
1372              if (aspect > amax)
1373                new_h = DIV(params->eval.w, amax);
1374              /* adjust for min aspect (width / height) */
1375              if (aspect < amin)
1376                new_h = DIV(params->eval.w, amin);
1377              break;
1378 
1379            case EDJE_ASPECT_PREFER_SOURCE:
1380            case EDJE_ASPECT_PREFER_BOTH:
1381              /* keep both dimensions in check */
1382              /* adjust for max aspect (width / height) */
1383              if (aspect > amax)
1384                {
1385                   new_w = MUL(amax, params->eval.h);
1386                   new_h = DIV(params->eval.w, amax);
1387                }
1388              /* adjust for min aspect (width / height) */
1389              if (aspect < amin)
1390                {
1391                   new_w = MUL(amin, params->eval.h);
1392                   new_h = DIV(params->eval.w, amin);
1393                }
1394              break;
1395 
1396            default:
1397              break;
1398           }
1399 
1400         if (apref != EDJE_ASPECT_PREFER_NONE)
1401           {
1402              if ((*maxw >= 0) && (new_w > FROM_INT(*maxw)))
1403                new_w = FROM_INT(*maxw);
1404              if (new_w < FROM_INT(*minw))
1405                new_w = FROM_INT(*minw);
1406 
1407              if ((FROM_INT(*maxh) >= 0) && (new_h > FROM_INT(*maxh)))
1408                new_h = FROM_INT(*maxh);
1409              if (new_h < FROM_INT(*minh))
1410                new_h = FROM_INT(*minh);
1411           }
1412 
1413         /* do real adjustment */
1414         if (apref == EDJE_ASPECT_PREFER_BOTH)
1415           {
1416              /* fix h and vary w */
1417              if (new_w > params->eval.w)
1418                {
1419                   //		  params->w = new_w;
1420                   // EXCEEDS BOUNDS in W
1421                   new_h = DIV(params->eval.w, amin);
1422                   new_w = params->eval.w;
1423                   if (new_h > params->eval.h)
1424                     {
1425                        new_h = params->eval.h;
1426                        new_w = MUL(amin, params->eval.h);
1427                     }
1428                }
1429              /* fix w and vary h */
1430              else
1431                {
1432                   //		  params->h = new_h;
1433                   // EXCEEDS BOUNDS in H
1434                   new_h = params->eval.h;
1435                   new_w = MUL(amin, params->eval.h);
1436                   if (new_w > params->eval.w)
1437                     {
1438                        new_h = DIV(params->eval.w, amin);
1439                        new_w = params->eval.w;
1440                     }
1441                }
1442              params->eval.w = new_w;
1443              params->eval.h = new_h;
1444           }
1445      }
1446    if (apref != EDJE_ASPECT_PREFER_BOTH)
1447      {
1448         if ((amin > 0.0) && (amax > ZERO) && (apref == EDJE_ASPECT_PREFER_NONE))
1449           {
1450              params->eval.w = new_w;
1451              params->eval.h = new_h;
1452           }
1453         else if (SUB(params->eval.h, new_h) > SUB(params->eval.w, new_w))
1454           {
1455              if (params->eval.h < new_h)
1456                params->eval.h = new_h;
1457              else if (params->eval.h > new_h)
1458                params->eval.h = new_h;
1459              if (apref == EDJE_ASPECT_PREFER_VERTICAL)
1460                params->eval.w = new_w;
1461           }
1462         else
1463           {
1464              if (params->eval.w < new_w)
1465                params->eval.w = new_w;
1466              else if (params->eval.w > new_w)
1467                params->eval.w = new_w;
1468              if (apref == EDJE_ASPECT_PREFER_HORIZONTAL)
1469                params->eval.h = new_h;
1470           }
1471      }
1472 
1473    params->eval.x = ADD(want_x,
1474                         MUL(SUB(want_w, params->eval.w),
1475                             desc->align.x));
1476    params->eval.y = ADD(want_y,
1477                         MUL(SUB(want_h, params->eval.h),
1478                             desc->align.y));
1479    return apref;
1480 }
1481 
1482 static void
_edje_part_recalc_single_step(Edje_Part_Description_Common * desc,Edje_Calc_Params * params)1483 _edje_part_recalc_single_step(Edje_Part_Description_Common *desc,
1484                               Edje_Calc_Params *params)
1485 {
1486    if (desc->step.x > 0)
1487      {
1488         int steps;
1489         int new_w;
1490 
1491         steps = TO_INT(params->eval.w) / desc->step.x;
1492         new_w = desc->step.x * steps;
1493         if (params->eval.w > FROM_INT(new_w))
1494           {
1495              params->eval.x = ADD(params->eval.x, SCALE(desc->align.x, SUB(params->eval.w, FROM_INT(new_w))));
1496              params->eval.w = FROM_INT(new_w);
1497           }
1498      }
1499 
1500    if (desc->step.y > 0)
1501      {
1502         int steps;
1503         int new_h;
1504 
1505         steps = TO_INT(params->eval.h) / desc->step.y;
1506         new_h = desc->step.y * steps;
1507         if (params->eval.h > FROM_INT(new_h))
1508           {
1509              params->eval.y = ADD(params->eval.y, SCALE(desc->align.y, SUB(params->eval.h, FROM_INT(new_h))));
1510              params->eval.h = FROM_INT(new_h);
1511           }
1512      }
1513 }
1514 
1515 static void
_edje_part_recalc_single_text(FLOAT_T sc EINA_UNUSED,Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Text * desc,Edje_Part_Description_Text * chosen_desc,Edje_Calc_Params * params,int * minw,int * minh,int * maxw,int * maxh)1516 _edje_part_recalc_single_text(FLOAT_T sc EINA_UNUSED,
1517                               Edje *ed,
1518                               Edje_Real_Part *ep,
1519                               Edje_Part_Description_Text *desc,
1520                               Edje_Part_Description_Text *chosen_desc,
1521                               Edje_Calc_Params *params,
1522                               int *minw, int *minh,
1523                               int *maxw, int *maxh)
1524 #define RECALC_SINGLE_TEXT_USING_APPLY 1
1525 #if RECALC_SINGLE_TEXT_USING_APPLY
1526 /*
1527  * XXX TODO NOTE:
1528  *
1529  * Original _edje_part_recalc_single_text() was not working as
1530  * expected since it was not doing size fit, range, ellipsis and so
1531  * on.
1532  *
1533  * The purpose of this function compared with
1534  * _edje_text_recalc_apply() is to be faster, not calling Evas update
1535  * functions. However for text this is quite difficult given that to
1536  * fit we need to set the font, size, style, etc. If it was done
1537  * correctly, we'd save some calls to move and some color sets,
1538  * however those shouldn't matter much in the overall picture.
1539  *
1540  * I've changed this to force applying the value, it should be more
1541  * correct and not so slow. The previous code is kept below for
1542  * reference but should be removed before next release!
1543  *
1544  * -- Gustavo Barbieri at 20-Aug-2011
1545  */
1546 {
1547    int mw, mh, size;
1548    Eina_Size2D sz;
1549    char *sfont = NULL;
1550 
1551    _edje_text_class_font_get(ed, desc, &size, &sfont);
1552    free(sfont);
1553 
1554    _edje_calc_params_need_type_text(params);
1555    params->type.text->size = size; /* XXX TODO used by further calcs, go inside recalc_apply? */
1556 
1557    _edje_text_recalc_apply(ed, ep, params, chosen_desc, EINA_TRUE);
1558 
1559    if ((!chosen_desc) ||
1560        ((!chosen_desc->text.min_x) && (!chosen_desc->text.min_y) &&
1561         (!chosen_desc->text.max_x) && (!chosen_desc->text.max_y)))
1562      return;
1563 
1564    // Note: No need to add padding to that, it's already in the geometry
1565    sz = efl_gfx_entity_size_get(ep->object);
1566    mw = sz.w;
1567    mh = sz.h;
1568 
1569    if (chosen_desc->text.max_x)
1570      {
1571         if ((*maxw < 0) || (mw > *maxw)) *maxw = mw;
1572      }
1573    if (chosen_desc->text.max_y)
1574      {
1575         if ((*maxh < 0) || (mh > *maxh)) *maxh = mh;
1576      }
1577    if (chosen_desc->text.min_x)
1578      {
1579         if (mw > *minw) *minw = mw;
1580         if ((*maxw > -1) && (*minw > *maxw)) *minw = *maxw;
1581      }
1582    if (chosen_desc->text.min_y)
1583      {
1584         if (mh > *minh) *minh = mh;
1585         if ((*maxh > -1) && (*minh > *maxh)) *minh = *maxh;
1586      }
1587    if ((*maxw > -1) && (mw > *maxw)) mw = *maxw;
1588    if ((*maxh > -1) && (mh > *maxh)) mh = *maxh;
1589 
1590    evas_object_resize(ep->object, mw, mh);
1591 }
1592 
1593 #else
1594 {
1595    char *sfont = NULL;
1596    int size;
1597 
1598    if (chosen_desc)
1599      {
1600         const char *text;
1601         const char *font;
1602         Eina_Size2D ts;
1603         int inlined_font = 0;
1604         Edje_Real_Part *source, *text_source;
1605 
1606         /* Update a object_text part */
1607 
1608         if (chosen_desc->text.id_source >= 0)
1609           ep->typedata.text->source = ed->table_parts[chosen_desc->text.id_source % ed->table_parts_size];
1610         else
1611           source = ep->typedata.text->source = NULL;
1612 
1613         if (chosen_desc->text.id_text_source >= 0)
1614           ep->typedata.text->text_source = ed->table_parts[chosen_desc->text.id_text_source % ed->table_parts_size];
1615         else
1616           text_source = ep->typedata.text->text_source = NULL;
1617 
1618         if (ep->typedata.text->text_source)
1619           text = edje_string_get(&_edje_real_part_text_text_source_description_get(ep, &text_source)->text.text);
1620         else
1621           text = edje_string_get(&chosen_desc->text.text);
1622 
1623         if (ep->typedata.text->source)
1624           font = _edje_text_class_font_get(ed, _edje_real_part_text_source_description_get(ep, &source), &size, &sfont);
1625         else
1626           font = _edje_text_class_font_get(ed, chosen_desc, &size, &sfont);
1627 
1628         if (!font) font = "";
1629 
1630         if (text_source)
1631           {
1632              if (text_source->typedata.text->text) text = text_source->typedata.text->text;
1633           }
1634         else
1635           {
1636              if (ep->typedata.text->text) text = ep->typedata.text->text;
1637           }
1638 
1639         if (source)
1640           {
1641              if (source->typedata.text->font) font = source->typedata.text->font;
1642              if (source->typedata.text->size > 0) size = source->typedata.text->size;
1643           }
1644         else
1645           {
1646              if (ep->typedata.text->font) font = ep->typedata.text->font;
1647              if (ep->typedata.text->size > 0) size = ep->typedata.text->size;
1648           }
1649         if (!text) text = "";
1650 
1651         /* check if the font is embedded in the .eet */
1652         if (ed->file->fonts)
1653           {
1654              Edje_Font_Directory_Entry *fnt;
1655 
1656              fnt = eina_hash_find(ed->file->fonts, font);
1657 
1658              if (fnt)
1659                {
1660                   char *font2;
1661 
1662                   size_t len = strlen(font) + sizeof("edje/fonts/") + 1;
1663                   font2 = alloca(len);
1664                   sprintf(font2, "edje/fonts/%s", font);
1665                   font = font2;
1666                   inlined_font = 1;
1667                }
1668           }
1669         if (ep->part->scale)
1670           evas_object_scale_set(ep->object, TO_DOUBLE(sc));
1671         if (inlined_font)
1672           {
1673              evas_object_text_font_source_set(ep->object, ed->path);
1674           }
1675         else evas_object_text_font_source_set(ep->object, NULL);
1676 
1677         if ((_edje_fontset_append) && (font))
1678           {
1679              char *font2;
1680 
1681              font2 = malloc(strlen(font) + 1 + strlen(_edje_fontset_append) + 1);
1682              if (font2)
1683                {
1684                   strcpy(font2, font);
1685                   strcat(font2, ",");
1686                   strcat(font2, _edje_fontset_append);
1687                   evas_object_text_font_set(ep->object, font2, size);
1688                   free(font2);
1689                }
1690           }
1691         else
1692           evas_object_text_font_set(ep->object, font, size);
1693         if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y) ||
1694             (chosen_desc->text.max_x) || (chosen_desc->text.max_y))
1695           {
1696              int mw, mh;
1697              Evas_Text_Style_Type
1698                style = EVAS_TEXT_STYLE_PLAIN,
1699                shadow = EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT;
1700              const Evas_Text_Style_Type styles[] = {
1701                 EVAS_TEXT_STYLE_PLAIN,
1702                 EVAS_TEXT_STYLE_PLAIN,
1703                 EVAS_TEXT_STYLE_OUTLINE,
1704                 EVAS_TEXT_STYLE_SOFT_OUTLINE,
1705                 EVAS_TEXT_STYLE_SHADOW,
1706                 EVAS_TEXT_STYLE_SOFT_SHADOW,
1707                 EVAS_TEXT_STYLE_OUTLINE_SHADOW,
1708                 EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW,
1709                 EVAS_TEXT_STYLE_FAR_SHADOW,
1710                 EVAS_TEXT_STYLE_FAR_SOFT_SHADOW,
1711                 EVAS_TEXT_STYLE_GLOW
1712              };
1713              const Evas_Text_Style_Type shadows[] = {
1714                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT,
1715                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM,
1716                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT,
1717                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT,
1718                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT,
1719                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP,
1720                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT,
1721                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT
1722              };
1723 
1724              if ((ep->part->effect & EVAS_TEXT_STYLE_MASK_BASIC)
1725                  < EDJE_TEXT_EFFECT_LAST)
1726                style = styles[ep->part->effect];
1727              shadow = shadows
1728                [(ep->part->effect & EDJE_TEXT_EFFECT_MASK_SHADOW_DIRECTION) >> 4];
1729              EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(style, shadow);
1730 
1731              evas_obj_text_style_set(ep->object, style);
1732              evas_obj_text_set(ep->object, text);
1733              ts = efl_gfx_entity_size_get(ep->object);
1734              if (chosen_desc->text.max_x)
1735                {
1736                   int l, r;
1737                   evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
1738                   mw = ts.w + l + r;
1739                   if ((*maxw < 0) || (mw < *maxw)) *maxw = mw;
1740                }
1741              if (chosen_desc->text.max_y)
1742                {
1743                   int t, b;
1744                   evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
1745                   mh = ts.h + t + b;
1746                   if ((*maxh < 0) || (mh < *maxh)) *maxh = mh;
1747                }
1748              if (chosen_desc->text.min_x)
1749                {
1750                   int l, r;
1751                   evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
1752                   mw = ts.w + l + r;
1753                   if (mw > *minw) *minw = mw;
1754                }
1755              if (chosen_desc->text.min_y)
1756                {
1757                   int t, b;
1758                   evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
1759                   mh = ts.h + t + b;
1760                   if (mh > *minh) *minh = mh;
1761                }
1762           }
1763         if (sfont) free(sfont);
1764      }
1765 
1766    /* FIXME: Do we really need to call it twice if chosen_desc ? */
1767    sfont = NULL;
1768    _edje_text_class_font_get(ed, desc, &size, &sfont);
1769    free(sfont);
1770    params->type.text.size = size;
1771 }
1772 #endif
1773 
1774 static void
_edje_part_recalc_single_min_length(FLOAT_T align,FLOAT_T * start,FLOAT_T * length,int min)1775 _edje_part_recalc_single_min_length(FLOAT_T align, FLOAT_T *start, FLOAT_T *length, int min)
1776 {
1777    if (min >= 0)
1778      {
1779         if (*length < FROM_INT(min))
1780           {
1781              *start = ADD(*start, (SCALE(align, (*length - min))));
1782              *length = FROM_INT(min);
1783           }
1784      }
1785 }
1786 
1787 static void
_edje_part_recalc_single_min(Edje_Part_Description_Common * desc,Edje_Calc_Params * params,int minw,int minh,Edje_Internal_Aspect aspect)1788 _edje_part_recalc_single_min(Edje_Part_Description_Common *desc,
1789                              Edje_Calc_Params *params,
1790                              int minw, int minh,
1791                              Edje_Internal_Aspect aspect)
1792 {
1793    FLOAT_T tmp;
1794    FLOAT_T w;
1795    FLOAT_T h;
1796 
1797    w = NEQ(params->eval.w, ZERO) ? params->eval.w : FROM_INT(99999);
1798    h = NEQ(params->eval.h, ZERO) ? params->eval.h : FROM_INT(99999);
1799 
1800    switch (aspect)
1801      {
1802       case EDJE_ASPECT_PREFER_NONE:
1803         break;
1804 
1805       case EDJE_ASPECT_PREFER_VERTICAL:
1806         tmp = DIV(SCALE(params->eval.w, minh), h);
1807         if (tmp >= FROM_INT(minw))
1808           {
1809              minw = TO_INT(tmp);
1810              break;
1811           }
1812         EINA_FALLTHROUGH;
1813 
1814       case EDJE_ASPECT_PREFER_HORIZONTAL:
1815         tmp = DIV(SCALE(params->eval.h, minw), w);
1816         if (tmp >= FROM_INT(minh))
1817           {
1818              minh = TO_INT(tmp);
1819              break;
1820           }
1821         EINA_FALLTHROUGH;
1822 
1823       case EDJE_ASPECT_PREFER_SOURCE:
1824          EINA_FALLTHROUGH;
1825       case EDJE_ASPECT_PREFER_BOTH:
1826         tmp = DIV(SCALE(params->eval.w, minh), h);
1827         if (tmp >= FROM_INT(minw))
1828           {
1829              minw = TO_INT(tmp);
1830              break;
1831           }
1832 
1833         tmp = DIV(SCALE(params->eval.h, minw), w);
1834         if (tmp >= FROM_INT(minh))
1835           {
1836              minh = TO_INT(tmp);
1837              break;
1838           }
1839 
1840         break;
1841      }
1842 
1843    _edje_part_recalc_single_min_length(desc->align.x, &params->eval.x, &params->eval.w, minw);
1844    _edje_part_recalc_single_min_length(desc->align.y, &params->eval.y, &params->eval.h, minh);
1845 }
1846 
1847 static void
_edje_part_recalc_single_max_length(FLOAT_T align,FLOAT_T * start,FLOAT_T * length,int max)1848 _edje_part_recalc_single_max_length(FLOAT_T align, FLOAT_T *start, FLOAT_T *length, int max)
1849 {
1850    if (max >= 0)
1851      {
1852         if (*length > max)
1853           {
1854              *start = ADD(*start, SCALE(align, (*length - max)));
1855              *length = max;
1856           }
1857      }
1858 }
1859 
1860 static void
_edje_part_recalc_single_max(Edje_Part_Description_Common * desc,Edje_Calc_Params * params,int maxw,int maxh,Edje_Internal_Aspect aspect)1861 _edje_part_recalc_single_max(Edje_Part_Description_Common *desc,
1862                              Edje_Calc_Params *params,
1863                              int maxw, int maxh,
1864                              Edje_Internal_Aspect aspect)
1865 {
1866    FLOAT_T tmp;
1867    FLOAT_T w;
1868    FLOAT_T h;
1869 
1870    w = NEQ(params->eval.w, 0) ? params->eval.w : FROM_INT(99999);
1871    h = NEQ(params->eval.h, 0) ? params->eval.h : FROM_INT(99999);
1872 
1873    switch (aspect)
1874      {
1875       case EDJE_ASPECT_PREFER_NONE:
1876         break;
1877 
1878       case EDJE_ASPECT_PREFER_VERTICAL:
1879         tmp = DIV(SCALE(params->eval.w, maxh), h);
1880         if (tmp <= FROM_INT(maxw))
1881           {
1882              maxw = TO_INT(tmp);
1883              break;
1884           }
1885         EINA_FALLTHROUGH;
1886 
1887       case EDJE_ASPECT_PREFER_HORIZONTAL:
1888         tmp = DIV(SCALE(params->eval.h, maxw), w);
1889         if (tmp <= FROM_INT(maxh))
1890           {
1891              maxh = TO_INT(tmp);
1892              break;
1893           }
1894         EINA_FALLTHROUGH;
1895 
1896       case EDJE_ASPECT_PREFER_SOURCE:
1897         EINA_FALLTHROUGH;
1898       case EDJE_ASPECT_PREFER_BOTH:
1899         tmp = DIV(SCALE(params->eval.w, maxh), h);
1900         if (tmp <= FROM_INT(maxw))
1901           {
1902              maxw = TO_INT(tmp);
1903              break;
1904           }
1905 
1906         tmp = DIV(SCALE(params->eval.h, maxw), w);
1907         if (tmp <= FROM_INT(maxh))
1908           {
1909              maxh = TO_INT(tmp);
1910              break;
1911           }
1912 
1913         break;
1914      }
1915 
1916    _edje_part_recalc_single_max_length(desc->align.x, &params->eval.x, &params->eval.w, maxw);
1917    _edje_part_recalc_single_max_length(desc->align.y, &params->eval.y, &params->eval.h, maxh);
1918 }
1919 
1920 static void
_edje_part_recalc_single_drag_threshold(Edje_Real_Part * ep,Edje_Real_Part * threshold,Edje_Calc_Params * params)1921 _edje_part_recalc_single_drag_threshold(Edje_Real_Part *ep,
1922                                         Edje_Real_Part *threshold,
1923                                         Edje_Calc_Params *params)
1924 {
1925    _edje_calc_params_need_ext(params);
1926    if (threshold)
1927      {
1928         if (ep->drag->threshold_started_x &&
1929             threshold->x < TO_INT(params->eval.x) &&
1930             TO_INT(params->eval.x) + TO_INT(params->eval.w) < threshold->x + threshold->w)
1931           {
1932              // Cancel movement to previous position due to our presence inside the threshold
1933              params->eval.x = FROM_INT(params->ext->req_drag.x);
1934              params->eval.w = FROM_INT(params->ext->req_drag.w);
1935              ep->drag->threshold_x = EINA_TRUE;
1936           }
1937         else
1938           {
1939              params->ext->req_drag.x = TO_INT(params->eval.x);
1940              params->ext->req_drag.w = TO_INT(params->eval.w);
1941              ep->drag->threshold_started_x = EINA_FALSE;
1942           }
1943         if (ep->drag->threshold_started_y &&
1944             threshold->y < TO_INT(params->eval.y) &&
1945             TO_INT(params->eval.y) + TO_INT(params->eval.h) < threshold->y + threshold->h)
1946           {
1947              // Cancel movement to previous position due to our presence inside the threshold
1948              params->eval.y = FROM_INT(params->ext->req_drag.y);
1949              params->eval.h = FROM_INT(params->ext->req_drag.h);
1950              ep->drag->threshold_y = EINA_TRUE;
1951           }
1952         else
1953           {
1954              params->ext->req_drag.y = TO_INT(params->eval.y);
1955              params->ext->req_drag.h = TO_INT(params->eval.h);
1956              ep->drag->threshold_started_y = EINA_FALSE;
1957           }
1958      }
1959    else
1960      {
1961         params->ext->req_drag.x = TO_INT(params->eval.x);
1962         params->ext->req_drag.w = TO_INT(params->eval.w);
1963         params->ext->req_drag.y = TO_INT(params->eval.y);
1964         params->ext->req_drag.h = TO_INT(params->eval.h);
1965      }
1966 }
1967 
1968 static void
_edje_part_recalc_single_drag(Edje_Real_Part * ep,Edje_Real_Part * confine_to,Edje_Real_Part * threshold,Edje_Calc_Params * params,int minw,int minh,int maxw,int maxh)1969 _edje_part_recalc_single_drag(Edje_Real_Part *ep,
1970                               Edje_Real_Part *confine_to,
1971                               Edje_Real_Part *threshold,
1972                               Edje_Calc_Params *params,
1973                               int minw, int minh,
1974                               int maxw, int maxh)
1975 {
1976    /* confine */
1977    if (confine_to)
1978      {
1979         int offset;
1980         int step;
1981         FLOAT_T v;
1982 
1983         /* complex dragable params */
1984         v = SCALE(ep->drag->size.x, confine_to->w);
1985 
1986         if ((minw > 0) && (TO_INT(v) < minw)) params->eval.w = FROM_INT(minw);
1987         else if ((maxw >= 0) && (TO_INT(v) > maxw))
1988           params->eval.w = FROM_INT(maxw);
1989         else params->eval.w = v;
1990 
1991         offset = TO_INT(SCALE(ep->drag->x, (confine_to->w - TO_INT(params->eval.w))))
1992           + ep->drag->tmp.x;
1993         if (ep->part->dragable.step_x > 0)
1994           {
1995              params->eval.x = FROM_INT(confine_to->x +
1996                                        ((offset / ep->part->dragable.step_x) * ep->part->dragable.step_x));
1997           }
1998         else if (ep->part->dragable.count_x > 0)
1999           {
2000              step = (confine_to->w - TO_INT(params->eval.w)) / ep->part->dragable.count_x;
2001              if (step < 1) step = 1;
2002              params->eval.x = FROM_INT(confine_to->x +
2003                                        ((offset / step) * step));
2004           }
2005 
2006         v = SCALE(ep->drag->size.y, confine_to->h);
2007 
2008         if ((minh > 0) && (TO_INT(v) < minh)) params->eval.h = FROM_INT(minh);
2009         else if ((maxh >= 0) && (TO_INT(v) > maxh))
2010           params->eval.h = FROM_INT(maxh);
2011         else params->eval.h = v;
2012 
2013         offset = TO_INT(SCALE(ep->drag->y, (confine_to->h - TO_INT(params->eval.h))))
2014           + ep->drag->tmp.y;
2015         if (ep->part->dragable.step_y > 0)
2016           {
2017              params->eval.y = FROM_INT(confine_to->y +
2018                                        ((offset / ep->part->dragable.step_y) * ep->part->dragable.step_y));
2019           }
2020         else if (ep->part->dragable.count_y > 0)
2021           {
2022              step = (confine_to->h - TO_INT(params->eval.h)) / ep->part->dragable.count_y;
2023              if (step < 1) step = 1;
2024              params->eval.y = FROM_INT(confine_to->y +
2025                                        ((offset / step) * step));
2026           }
2027 
2028         _edje_part_recalc_single_drag_threshold(ep, threshold, params);
2029 
2030         /* limit to confine */
2031         if (params->eval.x < FROM_INT(confine_to->x))
2032           {
2033              params->eval.x = FROM_INT(confine_to->x);
2034           }
2035         if ((ADD(params->eval.x, params->eval.w)) > FROM_INT(confine_to->x + confine_to->w))
2036           {
2037              params->eval.x = SUB(FROM_INT(confine_to->x + confine_to->w), params->eval.w);
2038           }
2039         if (params->eval.y < FROM_INT(confine_to->y))
2040           {
2041              params->eval.y = FROM_INT(confine_to->y);
2042           }
2043         if ((ADD(params->eval.y, params->eval.h)) > FROM_INT(confine_to->y + confine_to->h))
2044           {
2045              params->eval.y = SUB(FROM_INT(confine_to->y + confine_to->h), params->eval.h);
2046           }
2047      }
2048    else
2049      {
2050         /* simple dragable params */
2051         params->eval.x = ADD(ADD(params->eval.x, ep->drag->x), FROM_INT(ep->drag->tmp.x));
2052         params->eval.y = ADD(ADD(params->eval.y, ep->drag->y), FROM_INT(ep->drag->tmp.y));
2053 
2054         _edje_part_recalc_single_drag_threshold(ep, threshold, params);
2055      }
2056 }
2057 
2058 static void
_edje_part_recalc_single_fill(Edje_Real_Part * ep,Edje_Part_Description_Spec_Fill * fill,Edje_Calc_Params * params)2059 _edje_part_recalc_single_fill(Edje_Real_Part *ep,
2060                               Edje_Part_Description_Spec_Fill *fill,
2061                               Edje_Calc_Params *params)
2062 {
2063    int fw;
2064    int fh;
2065 
2066    params->smooth = fill->smooth;
2067 
2068    if (fill->type == EDJE_FILL_TYPE_TILE)
2069      evas_object_image_size_get(ep->object, &fw, NULL);
2070    else
2071      fw = params->final.w;
2072 
2073    _edje_calc_params_need_type_common(params);
2074    params->type.common->fill.x = fill->pos_abs_x
2075      + TO_INT(SCALE(fill->pos_rel_x, fw));
2076    params->type.common->fill.w = fill->abs_x
2077      + TO_INT(SCALE(fill->rel_x, fw));
2078 
2079    if (fill->type == EDJE_FILL_TYPE_TILE)
2080      evas_object_image_size_get(ep->object, NULL, &fh);
2081    else
2082      fh = params->final.h;
2083 
2084    params->type.common->fill.y = fill->pos_abs_y
2085      + TO_INT(SCALE(fill->pos_rel_y, fh));
2086    params->type.common->fill.h = fill->abs_y
2087      + TO_INT(SCALE(fill->rel_y, fh));
2088 }
2089 
2090 static void
_edje_part_recalc_single_min_max(FLOAT_T sc,Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Common * desc,int * minw,int * minh,int * maxw,int * maxh)2091 _edje_part_recalc_single_min_max(FLOAT_T sc,
2092                                  Edje *ed,
2093                                  Edje_Real_Part *ep,
2094                                  Edje_Part_Description_Common *desc,
2095                                  int *minw, int *minh,
2096                                  int *maxw, int *maxh)
2097 {
2098    Edje_Size_Class *size_class = NULL;
2099    Evas_Coord mnw, mnh, mxw, mxh;
2100 
2101    if (desc->size_class)
2102      size_class = _edje_size_class_find(ed, desc->size_class);
2103 
2104    if (size_class)
2105      {
2106         mnw = size_class->minw;
2107         mnh = size_class->minh;
2108         mxw = size_class->maxw;
2109         mxh = size_class->maxh;
2110      }
2111    else
2112      {
2113         mnw = desc->min.w;
2114         mnh = desc->min.h;
2115         mxw = desc->max.w;
2116         mxh = desc->max.h;
2117      }
2118 
2119    *minw = mnw;
2120    if (ep->part->scale) *minw = TO_INT_ROUND(SCALE(sc, *minw));
2121    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2122        (ep->typedata.swallow))
2123      {
2124         if (ep->typedata.swallow->swallow_params.min.w > *minw)
2125           *minw = ep->typedata.swallow->swallow_params.min.w;
2126      }
2127 
2128    if (ed->calc_only)
2129      {
2130         if (desc->minmul.have)
2131           {
2132              FLOAT_T mmw = desc->minmul.w;
2133              if (NEQ(mmw, FROM_INT(1))) *minw = TO_INT(SCALE(mmw, *minw));
2134           }
2135      }
2136 
2137    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2138        (ep->typedata.swallow))
2139      {
2140         /* XXX TODO: remove need of EDJE_INF_MAX_W, see edje_util.c */
2141         if ((ep->typedata.swallow->swallow_params.max.w <= 0) ||
2142             (ep->typedata.swallow->swallow_params.max.w == EDJE_INF_MAX_W))
2143           {
2144              *maxw = mxw;
2145              if (*maxw > 0)
2146                {
2147                   if (ep->part->scale) *maxw = TO_INT_ROUND(SCALE(sc, *maxw));
2148                   if (*maxw < 1) *maxw = 1;
2149                }
2150           }
2151         else
2152           {
2153              if (mxw <= 0)
2154                *maxw = ep->typedata.swallow->swallow_params.max.w;
2155              else
2156                {
2157                   *maxw = mxw;
2158                   if (*maxw > 0)
2159                     {
2160                        if (ep->part->scale) *maxw = TO_INT_ROUND(SCALE(sc, *maxw));
2161                        if (*maxw < 1) *maxw = 1;
2162                     }
2163                   if (ep->typedata.swallow->swallow_params.max.w < *maxw)
2164                     *maxw = ep->typedata.swallow->swallow_params.max.w;
2165                }
2166           }
2167      }
2168    else
2169      {
2170         *maxw = mxw;
2171         if (*maxw > 0)
2172           {
2173              if (ep->part->scale) *maxw = TO_INT_ROUND(SCALE(sc, *maxw));
2174              if (*maxw < 1) *maxw = 1;
2175           }
2176      }
2177    if ((ed->calc_only) && (desc->minmul.have) &&
2178        (NEQ(desc->minmul.w, FROM_INT(1)))) *maxw = *minw;
2179    if (*maxw >= 0)
2180      {
2181         if (*maxw < *minw) *maxw = *minw;
2182      }
2183 
2184    *minh = mnh;
2185    if (ep->part->scale) *minh = TO_INT_ROUND(SCALE(sc, *minh));
2186    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2187        (ep->typedata.swallow))
2188      {
2189         if (ep->typedata.swallow->swallow_params.min.h > *minh)
2190           *minh = ep->typedata.swallow->swallow_params.min.h;
2191      }
2192 
2193    if (ed->calc_only)
2194      {
2195         if (desc->minmul.have)
2196           {
2197              FLOAT_T mmh = desc->minmul.h;
2198              if (NEQ(mmh, FROM_INT(1))) *minh = TO_INT(SCALE(mmh, *minh));
2199           }
2200      }
2201 
2202    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2203        (ep->typedata.swallow))
2204      {
2205         /* XXX TODO: remove need of EDJE_INF_MAX_H, see edje_util.c */
2206         if ((ep->typedata.swallow->swallow_params.max.h <= 0) ||
2207             (ep->typedata.swallow->swallow_params.max.h == EDJE_INF_MAX_H))
2208           {
2209              *maxh = mxh;
2210              if (*maxh > 0)
2211                {
2212                   if (ep->part->scale) *maxh = TO_INT_ROUND(SCALE(sc, *maxh));
2213                   if (*maxh < 1) *maxh = 1;
2214                }
2215           }
2216         else
2217           {
2218              if (mxh <= 0)
2219                *maxh = ep->typedata.swallow->swallow_params.max.h;
2220              else
2221                {
2222                   *maxh = mxh;
2223                   if (*maxh > 0)
2224                     {
2225                        if (ep->part->scale) *maxh = TO_INT_ROUND(SCALE(sc, *maxh));
2226                        if (*maxh < 1) *maxh = 1;
2227                     }
2228                   if (ep->typedata.swallow->swallow_params.max.h < *maxh)
2229                     *maxh = ep->typedata.swallow->swallow_params.max.h;
2230                }
2231           }
2232      }
2233    else
2234      {
2235         *maxh = mxh;
2236         if (*maxh > 0)
2237           {
2238              if (ep->part->scale) *maxh = TO_INT_ROUND(SCALE(sc, *maxh));
2239              if (*maxh < 1) *maxh = 1;
2240           }
2241      }
2242    if ((ed->calc_only) && (desc->minmul.have) &&
2243        (NEQ(desc->minmul.h, FROM_INT(1)))) *maxh = *minh;
2244    if (*maxh >= 0)
2245      {
2246         if (*maxh < *minh) *maxh = *minh;
2247      }
2248 }
2249 
2250 static void
_edje_part_recalc_single_map(Edje * ed,Edje_Real_Part * ep EINA_UNUSED,Edje_Real_Part * center,Edje_Real_Part * zoom_center,Edje_Real_Part * light,Edje_Real_Part * persp,Edje_Part_Description_Common * desc,Edje_Part_Description_Common * chosen_desc,Edje_Calc_Params * params)2251 _edje_part_recalc_single_map(Edje *ed,
2252                              Edje_Real_Part *ep EINA_UNUSED,
2253                              Edje_Real_Part *center,
2254                              Edje_Real_Part *zoom_center,
2255                              Edje_Real_Part *light,
2256                              Edje_Real_Part *persp,
2257                              Edje_Part_Description_Common *desc,
2258                              Edje_Part_Description_Common *chosen_desc,
2259                              Edje_Calc_Params *params)
2260 {
2261    params->mapped = chosen_desc->map.on;
2262    params->lighted = params->mapped ? !!light : 0;
2263    params->persp_on = params->mapped ? !!persp : 0;
2264 
2265    if (!params->mapped) return;
2266 
2267    EINA_COW_CALC_MAP_BEGIN(params, params_write)
2268    {
2269       //rotation center
2270       if (center)
2271         {
2272            params_write->center.x = ed->x + center->x + (center->w / 2);
2273            params_write->center.y = ed->y + center->y + (center->h / 2);
2274         }
2275       else
2276         {
2277            params_write->center.x = ed->x + params->final.x + (params->final.w / 2);
2278            params_write->center.y = ed->y + params->final.y + (params->final.h / 2);
2279         }
2280       params_write->center.z = 0;
2281       //zoom center
2282       if (zoom_center)
2283         {
2284            params_write->zoom_center.x = ed->x + zoom_center->x + (zoom_center->w / 2);
2285            params_write->zoom_center.y = ed->y + zoom_center->y + (zoom_center->h / 2);
2286         }
2287       else
2288         {
2289            params_write->zoom_center.x = ed->x + params->final.x + (params->final.w / 2);
2290            params_write->zoom_center.y = ed->y + params->final.y + (params->final.h / 2);
2291         }
2292 
2293       params_write->rotation.x = desc->map.rot.x;
2294       params_write->rotation.y = desc->map.rot.y;
2295       params_write->rotation.z = desc->map.rot.z;
2296       params_write->zoom.x = desc->map.zoom.x;
2297       params_write->zoom.y = desc->map.zoom.y;
2298 
2299       if (light)
2300         {
2301            Edje_Part_Description_Common *light_desc2;
2302            FLOAT_T pos, pos2;
2303 
2304            params_write->light.x = ed->x + light->x + (light->w / 2);
2305            params_write->light.y = ed->y + light->y + (light->h / 2);
2306 
2307            pos = light->description_pos;
2308            pos2 = (pos < ZERO) ? ZERO : ((pos > FROM_INT(1)) ? FROM_INT(1) : pos);
2309 
2310            light_desc2 = light->param2 ? light->param2->description : NULL;
2311 
2312            /* take into account CURRENT state also */
2313            if (NEQ(pos, ZERO) && light_desc2)
2314              {
2315                 params_write->light.z = light->param1.description->persp.zplane +
2316                   TO_INT(SCALE(pos, light_desc2->persp.zplane - light->param1.description->persp.zplane));
2317                 params_write->light.r = light->param1.description->color.r +
2318                   TO_INT(SCALE(pos2, light_desc2->color.r - light->param1.description->color.r));
2319                 params_write->light.g = light->param1.description->color.g +
2320                   TO_INT(SCALE(pos2, light_desc2->color.g - light->param1.description->color.g));
2321                 params_write->light.b = light->param1.description->color.b +
2322                   TO_INT(SCALE(pos2, light_desc2->color.b - light->param1.description->color.b));
2323                 params_write->light.ar = light->param1.description->color2.r +
2324                   TO_INT(SCALE(pos2, light_desc2->color2.r - light->param1.description->color2.r));
2325                 params_write->light.ag = light->param1.description->color2.g +
2326                   TO_INT(SCALE(pos2, light_desc2->color2.g - light->param1.description->color2.g));
2327                 params_write->light.ab = light->param1.description->color2.b +
2328                   TO_INT(SCALE(pos2, light_desc2->color2.b - light->param1.description->color2.b));
2329              }
2330            else
2331              {
2332                 params_write->light.z = light->param1.description->persp.zplane;
2333                 params_write->light.r = light->param1.description->color.r;
2334                 params_write->light.g = light->param1.description->color.g;
2335                 params_write->light.b = light->param1.description->color.b;
2336                 params_write->light.ar = light->param1.description->color2.r;
2337                 params_write->light.ag = light->param1.description->color2.g;
2338                 params_write->light.ab = light->param1.description->color2.b;
2339              }
2340         }
2341 
2342       if (persp)
2343         {
2344            FLOAT_T pos;
2345 
2346            params_write->persp.x = ed->x + persp->x + (persp->w / 2);
2347            params_write->persp.y = ed->y + persp->y + (persp->h / 2);
2348 
2349            pos = persp->description_pos;
2350 
2351            if (NEQ(pos, ZERO) && persp->param2)
2352              {
2353                 params_write->persp.z = persp->param1.description->persp.zplane +
2354                   TO_INT(SCALE(pos, persp->param2->description->persp.zplane -
2355                                persp->param1.description->persp.zplane));
2356                 params_write->persp.focal = persp->param1.description->persp.focal +
2357                   TO_INT(SCALE(pos, persp->param2->description->persp.focal -
2358                                persp->param1.description->persp.focal));
2359              }
2360            else
2361              {
2362                 params_write->persp.z = persp->param1.description->persp.zplane;
2363                 params_write->persp.focal = persp->param1.description->persp.focal;
2364              }
2365         }
2366       params_write->colors = desc->map.colors;
2367       params_write->colors_count = desc->map.colors_count;
2368    }
2369    EINA_COW_CALC_MAP_END(params, params_write);
2370 }
2371 
2372 static int
_filter_bsearch_cmp(const void * a,const void * b)2373 _filter_bsearch_cmp(const void *a, const void *b)
2374 {
2375    const Edje_Gfx_Filter *filter = b;
2376    const char *key = a;
2377 
2378    return strcmp(key, filter->name);
2379 }
2380 
2381 static inline const char *
_edje_filter_get(Edje * ed,Edje_Part_Description_Spec_Filter * filter)2382 _edje_filter_get(Edje *ed, Edje_Part_Description_Spec_Filter *filter)
2383 {
2384    if (!filter->code) return NULL;
2385    if (EINA_UNLIKELY(!filter->checked_data))
2386      {
2387         Edje_Gfx_Filter *found;
2388 
2389         filter->checked_data = EINA_TRUE;
2390         if (!ed->file->filter_dir)
2391           return filter->code;
2392 
2393         found = bsearch(filter->code, &(ed->file->filter_dir->filters[0]),
2394                         ed->file->filter_dir->filters_count,
2395                         sizeof(Edje_Gfx_Filter), _filter_bsearch_cmp);
2396         if (found)
2397           {
2398              filter->name = found->name;
2399              filter->code = found->script;
2400              filter->no_free = EINA_TRUE;
2401              return filter->code;
2402           }
2403      }
2404    return filter->code;
2405 }
2406 
2407 static void
_edje_part_pixel_adjust(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * params)2408 _edje_part_pixel_adjust(Edje *ed,
2409                         Edje_Real_Part *ep,
2410                         Edje_Calc_Params *params)
2411 {
2412    /* Adjust rounding to not loose one pixels compared to float
2413       information only when rendering to avoid infinite adjustement
2414       when doing min restricted calc */
2415    if (ABS(params->final.x) + params->final.w < TO_INT(ADD(ABS(params->eval.x), params->eval.w)))
2416      {
2417         if (!ed->calc_only)
2418           {
2419              params->final.w += 1;
2420           }
2421         else
2422           {
2423              ep->invalidate = EINA_TRUE;
2424           }
2425      }
2426    else if (ABS(params->final.x) + params->final.w > TO_INT(ADD(ABS(params->eval.x), params->eval.w)))
2427      {
2428         if (!ed->calc_only)
2429           {
2430              params->final.w -= 1;
2431           }
2432         else
2433           {
2434              ep->invalidate = EINA_TRUE;
2435           }
2436      }
2437    if (ABS(params->final.y) + params->final.h < TO_INT(ADD(ABS(params->eval.y), params->eval.h)))
2438      {
2439         if (!ed->calc_only)
2440           {
2441              params->final.h += 1;
2442           }
2443         else
2444           {
2445              ep->invalidate = EINA_TRUE;
2446           }
2447      }
2448    else if (ABS(params->final.y) + params->final.h > TO_INT(ADD(ABS(params->eval.y), params->eval.h)))
2449      {
2450         if (!ed->calc_only)
2451           {
2452              params->final.h -= 1;
2453           }
2454         else
2455           {
2456              ep->invalidate = EINA_TRUE;
2457           }
2458      }
2459 
2460    if (params->final.w < 0 || params->final.h < 0)
2461      ERR("The params final size became negative");
2462 
2463 }
2464 
2465 static void
_edje_part_recalc_single_filter(Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Common * desc,Edje_Part_Description_Common * chosen_desc,double pos)2466 _edje_part_recalc_single_filter(Edje *ed,
2467                                 Edje_Real_Part *ep,
2468                                 Edje_Part_Description_Common *desc,
2469                                 Edje_Part_Description_Common *chosen_desc,
2470                                 double pos)
2471 {
2472    Edje_Part_Description_Spec_Filter *filter, *prevfilter;
2473    Eina_List *filter_sources = NULL, *prev_sources = NULL;
2474    const char *src1, *src2, *part, *code;
2475    Evas_Object *obj = ep->object;
2476    Eina_List *li1, *li2;
2477 
2478    /* handle TEXT, IMAGE, PROXY, SNAPSHOT part types here */
2479    if (ep->part->type == EDJE_PART_TYPE_TEXT)
2480      {
2481         Edje_Part_Description_Text *chosen_edt = (Edje_Part_Description_Text *) chosen_desc;
2482         Edje_Part_Description_Text *edt = (Edje_Part_Description_Text *) desc;
2483         filter = &chosen_edt->filter;
2484         prev_sources = edt->filter.sources;
2485         filter_sources = chosen_edt->filter.sources;
2486         prevfilter = &(edt->filter);
2487      }
2488    else if (ep->part->type == EDJE_PART_TYPE_IMAGE)
2489      {
2490         Edje_Part_Description_Image *chosen_edi = (Edje_Part_Description_Image *) chosen_desc;
2491         Edje_Part_Description_Image *edi = (Edje_Part_Description_Image *) desc;
2492         filter = &chosen_edi->filter;
2493         prev_sources = edi->filter.sources;
2494         filter_sources = chosen_edi->filter.sources;
2495         prevfilter = &(edi->filter);
2496      }
2497    else if (ep->part->type == EDJE_PART_TYPE_PROXY)
2498      {
2499         Edje_Part_Description_Proxy *chosen_edp = (Edje_Part_Description_Proxy *) chosen_desc;
2500         Edje_Part_Description_Proxy *edp = (Edje_Part_Description_Proxy *) desc;
2501         filter = &chosen_edp->filter;
2502         prev_sources = edp->filter.sources;
2503         filter_sources = chosen_edp->filter.sources;
2504         prevfilter = &(edp->filter);
2505      }
2506    else if (ep->part->type == EDJE_PART_TYPE_SNAPSHOT)
2507      {
2508         Edje_Part_Description_Snapshot *chosen_eds = (Edje_Part_Description_Snapshot *) chosen_desc;
2509         Edje_Part_Description_Snapshot *eds = (Edje_Part_Description_Snapshot *) desc;
2510         filter = &chosen_eds->filter;
2511         prev_sources = eds->filter.sources;
2512         filter_sources = chosen_eds->filter.sources;
2513         prevfilter = &(eds->filter);
2514      }
2515    else
2516      {
2517         CRI("Invalid call to filter recalc");
2518         return;
2519      }
2520 
2521    if ((!filter->code) && (!prevfilter->code)) return;
2522 
2523    /* common code below */
2524    code = _edje_filter_get(ed, filter);
2525    if (!code)
2526      {
2527         efl_gfx_filter_program_set(obj, NULL, NULL);
2528         return;
2529      }
2530 
2531    if (!filter->sources_set)
2532      {
2533         filter->sources_set = 1;
2534         prev_sources = NULL;
2535      }
2536 
2537    /* pass extra data items */
2538    if (filter->data)
2539      {
2540         unsigned int k;
2541         for (k = 0; k < filter->data_count; k++)
2542           {
2543              Edje_Part_Description_Spec_Filter_Data *data = &(filter->data[k]);
2544              if (data->invalid_cc)
2545                 continue;
2546              if (!data->value)
2547                {
2548                   efl_gfx_filter_data_set(obj, data->name, NULL, EINA_FALSE);
2549                }
2550              else if (!strncmp(data->value, "color_class('", sizeof("color_class('") - 1))
2551                {
2552                   /* special handling for color classes even tho they're not that great */
2553                   char *ccname, *buffer, *r;
2554                   Edje_Color_Class *cc;
2555 
2556                   ccname = strdup(data->value + sizeof("color_class('") - 1);
2557                   if (ccname)
2558                     {
2559                        r = strchr(ccname, '\'');
2560                        if (r && (r[1] == ')') && (r[2] == '\0'))
2561                          {
2562                             *r = '\0';
2563                             cc = _edje_color_class_find(ed, ccname);
2564                             if (cc)
2565                               {
2566                                  static const char fmt[] =
2567                                        "{r=%d,g=%d,b=%d,a=%d,"
2568                                        "r2=%d,g2=%d,b2=%d,a2=%d,"
2569                                        "r3=%d,g3=%d,b3=%d,a3=%d}";
2570                                  int len = sizeof(fmt) + 20;
2571                                  len += strlen(data->name);
2572                                  buffer = alloca(len);
2573                                  snprintf(buffer, len - 1, fmt,
2574                                           (int) cc->r, (int) cc->g, (int) cc->b, (int) cc->a,
2575                                           (int) cc->r2, (int) cc->g2, (int) cc->b2, (int) cc->a2,
2576                                           (int) cc->r3, (int) cc->g3, (int) cc->b3, (int) cc->a3);
2577                                  buffer[len - 1] = 0;
2578                                  efl_gfx_filter_data_set(obj, data->name, buffer, EINA_TRUE);
2579                               }
2580                             else
2581                               {
2582                                  ERR("Unknown color class: %s", ccname);
2583                                  data->invalid_cc = EINA_TRUE;
2584                               }
2585                          }
2586                        else
2587                          {
2588                             ERR("Failed to parse color class: %s", data->value);
2589                             data->invalid_cc = EINA_TRUE;
2590                          }
2591                        free(ccname);
2592                     }
2593                }
2594              else
2595                 efl_gfx_filter_data_set(obj, data->name, data->value, EINA_FALSE);
2596           }
2597      }
2598    efl_gfx_filter_program_set(obj, code, filter->name);
2599    if (prev_sources != filter_sources)
2600      {
2601         /* remove sources that are not there anymore
2602          * this O(n^2) loop assumes a very small number of sources */
2603         EINA_LIST_FOREACH(prev_sources, li1, src1)
2604           {
2605              Eina_Bool found = 0;
2606              EINA_LIST_FOREACH(filter_sources, li2, src2)
2607                {
2608                   if (!strcmp(src1, src2))
2609                     {
2610                        found = 1;
2611                        break;
2612                     }
2613                }
2614              if (!found)
2615                {
2616                   part = strchr(src1, ':');
2617                   if (!part)
2618                      efl_gfx_filter_source_set(obj, src1, NULL);
2619                   else
2620                     {
2621                        char *name = strdup(src1);
2622                        if (!name) continue ;
2623                        name[part - src1] = 0;
2624                        efl_gfx_filter_source_set(obj, name, NULL);
2625                        free(name);
2626                     }
2627                }
2628           }
2629         /* add all sources by part name */
2630         EINA_LIST_FOREACH(filter_sources, li1, src1)
2631           {
2632              Edje_Real_Part *rp;
2633              char *name = NULL;
2634              if ((part = strchr(src1, ':')) != NULL)
2635                {
2636                   name = strdup(src1);
2637                   if (!name) continue ;
2638                   name[part - src1] = 0;
2639                   part++;
2640                }
2641              else
2642                 part = src1;
2643              rp = _edje_real_part_get(ed, part);
2644              efl_gfx_filter_source_set(obj, name ? name : part, rp ? rp->object : NULL);
2645              free(name);
2646           }
2647      }
2648    /* pass edje state for transitions */
2649    if (ep->param2)
2650      {
2651         efl_gfx_filter_state_set(obj, chosen_desc->state.name, chosen_desc->state.value,
2652               ep->param2->description->state.name, ep->param2->description->state.value,
2653               pos);
2654      }
2655    else
2656      {
2657         efl_gfx_filter_state_set(obj, chosen_desc->state.name, chosen_desc->state.value,
2658               NULL, 0.0, pos);
2659      }
2660 }
2661 
2662 static void
_edje_part_recalc_single_table(Edje_Real_Part * ep,Edje_Part_Description_Common * chosen_desc,int * minw,int * minh)2663 _edje_part_recalc_single_table(Edje_Real_Part *ep,
2664                                Edje_Part_Description_Common *chosen_desc,
2665                                int *minw, int *minh)
2666 {
2667    Eina_Size2D lmin;
2668 
2669    efl_canvas_group_need_recalculate_set(ep->object, 1);
2670    efl_canvas_group_calculate(ep->object);
2671    lmin = efl_gfx_hint_size_restricted_min_get(ep->object);
2672    if (((Edje_Part_Description_Table *)chosen_desc)->table.min.h)
2673      {
2674         if (lmin.w > *minw) *minw = lmin.w;
2675      }
2676    if (((Edje_Part_Description_Table *)chosen_desc)->table.min.v)
2677      {
2678         if (lmin.h > *minh) *minh = lmin.h;
2679      }
2680 }
2681 
2682 static void
_edje_part_recalc_single_box(Edje_Real_Part * ep,Edje_Part_Description_Common * chosen_desc,int * minw,int * minh)2683 _edje_part_recalc_single_box(Edje_Real_Part *ep,
2684                              Edje_Part_Description_Common *chosen_desc,
2685                              int *minw, int *minh)
2686 {
2687    Eina_Size2D lmin;
2688 
2689    efl_canvas_group_need_recalculate_set(ep->object, 1);
2690    efl_canvas_group_calculate(ep->object);
2691    lmin = efl_gfx_hint_size_restricted_min_get(ep->object);
2692    if (((Edje_Part_Description_Box *)chosen_desc)->box.min.h)
2693      {
2694         if (lmin.w > *minw) *minw = lmin.w;
2695      }
2696    if (((Edje_Part_Description_Box *)chosen_desc)->box.min.v)
2697      {
2698         if (lmin.h > *minh) *minh = lmin.h;
2699      }
2700 }
2701 
2702 static void
_edje_part_recalc_single_image(Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Common * chosen_desc,FLOAT_T pos,int * minw,int * minh,int * maxw,int * maxh)2703 _edje_part_recalc_single_image(Edje *ed, Edje_Real_Part *ep,
2704                                Edje_Part_Description_Common *chosen_desc,
2705                                FLOAT_T pos,
2706                                int *minw, int *minh, int *maxw, int *maxh)
2707 {
2708    Evas_Coord w, h;
2709 
2710    /* We only need pos to find the right image that would be displayed */
2711    /* Yes, if someone set aspect preference to SOURCE and also max,min
2712     to SOURCE, it will be under efficient, but who cares at the
2713     moment. */
2714    _edje_real_part_image_set(ed, ep, NULL, pos);
2715    evas_object_image_size_get(ep->object, &w, &h);
2716    if (chosen_desc->min.limit)
2717      {
2718         if (w > *minw) *minw = w;
2719         if (h > *minh) *minh = h;
2720      }
2721    if (chosen_desc->max.limit)
2722      {
2723         if ((*maxw <= 0) || (w < *maxw)) *maxw = w;
2724         if ((*maxh <= 0) || (h < *maxh)) *maxh = h;
2725      }
2726 }
2727 
2728 #ifdef HAVE_EPHYSICS
2729 static void
_edje_part_recalc_single_physics(Edje_Calc_Params * params,Edje_Part_Description_Common * desc)2730 _edje_part_recalc_single_physics(Edje_Calc_Params *params,
2731                                  Edje_Part_Description_Common *desc)
2732 {
2733    EINA_COW_CALC_PHYSICS_BEGIN(params, params_write)
2734      {
2735         params_write->mass = desc->physics.mass;
2736         params_write->restitution = desc->physics.restitution;
2737         params_write->friction = desc->physics.friction;
2738         params_write->damping.linear = desc->physics.damping.linear;
2739         params_write->damping.angular = desc->physics.damping.angular;
2740         params_write->sleep.linear = desc->physics.sleep.linear;
2741         params_write->sleep.angular = desc->physics.sleep.angular;
2742         params_write->material = desc->physics.material;
2743         params_write->density = desc->physics.density;
2744         params_write->hardness = desc->physics.hardness;
2745         params_write->ignore_part_pos = desc->physics.ignore_part_pos;
2746         params_write->light_on = desc->physics.light_on;
2747         params_write->mov_freedom.lin.x = desc->physics.mov_freedom.lin.x;
2748         params_write->mov_freedom.lin.y = desc->physics.mov_freedom.lin.y;
2749         params_write->mov_freedom.lin.z = desc->physics.mov_freedom.lin.z;
2750         params_write->mov_freedom.ang.x = desc->physics.mov_freedom.ang.x;
2751         params_write->mov_freedom.ang.y = desc->physics.mov_freedom.ang.y;
2752         params_write->mov_freedom.ang.z = desc->physics.mov_freedom.ang.z;
2753         params_write->backcull = desc->physics.backcull;
2754         params_write->z = desc->physics.z;
2755         params_write->depth = desc->physics.depth;
2756      }
2757    EINA_COW_CALC_PHYSICS_END(params, params_write);
2758 }
2759 #endif
2760 
2761 static void
_edje_part_recalc_single_fixed_info(Edje * ed,Edje_Real_Part * ep,Eina_Bool fixedw,Eina_Bool fixedh)2762 _edje_part_recalc_single_fixed_info(Edje *ed, Edje_Real_Part *ep,
2763                                     Eina_Bool fixedw, Eina_Bool fixedh)
2764 {
2765    INF("file %s, group %s has a non-fixed part '%s'. You should add "
2766        "'fixed: %d %d'. But in order to optimize the edje calc, we "
2767        "add it automatically.", ed->path, ed->group, ep->part->name,
2768        fixedw, fixedh);
2769 }
2770 
2771 static void
_edje_part_recalc_single_image0(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * params,Edje_Part_Description_Image * img_desc,FLOAT_T pos)2772 _edje_part_recalc_single_image0(Edje *ed, Edje_Real_Part *ep,
2773                                 Edje_Calc_Params *params,
2774                                 Edje_Part_Description_Image *img_desc,
2775                                 FLOAT_T pos)
2776 {
2777    Edje_Real_Part_Set *set;
2778 
2779    _edje_real_part_image_set(ed, ep, &set, pos);
2780 
2781    /* border */
2782    _edje_calc_params_need_type_common(params);
2783    params->type.common->spec.image.l = img_desc->image.border.l;
2784    params->type.common->spec.image.r = img_desc->image.border.r;
2785    params->type.common->spec.image.t = img_desc->image.border.t;
2786    params->type.common->spec.image.b = img_desc->image.border.b;
2787 
2788    params->type.common->spec.image.border_scale_by = img_desc->image.border.scale_by;
2789 
2790    if (set && set->set)
2791      {
2792 #define SET_BORDER_DEFINED(Result, Value) Result = Value ? Value : Result;
2793         SET_BORDER_DEFINED(params->type.common->spec.image.l, set->entry->border.l);
2794         SET_BORDER_DEFINED(params->type.common->spec.image.r, set->entry->border.r);
2795         SET_BORDER_DEFINED(params->type.common->spec.image.t, set->entry->border.t);
2796         SET_BORDER_DEFINED(params->type.common->spec.image.b, set->entry->border.b);
2797 
2798         params->type.common->spec.image.border_scale_by = NEQ(set->entry->border.scale_by, ZERO) ?
2799           set->entry->border.scale_by : params->type.common->spec.image.border_scale_by;
2800      }
2801 }
2802 
2803 static void
_edje_part_recalc_single_text0(Edje_Calc_Params * params,Edje_Part_Description_Text * text_desc,Edje_Color_Class * cc)2804 _edje_part_recalc_single_text0(Edje_Calc_Params *params,
2805                                Edje_Part_Description_Text *text_desc,
2806                                Edje_Color_Class *cc)
2807 {
2808    _edje_calc_params_need_type_text(params);
2809    /* text.align */
2810    params->type.text->align.x = text_desc->text.align.x;
2811    params->type.text->align.y = text_desc->text.align.y;
2812    params->type.text->ellipsis = text_desc->text.ellipsis;
2813 
2814    /* text colors */
2815    if (cc)
2816      {
2817         params->type.text->color2.r = (((int)cc->r2 + 1) * text_desc->common.color2.r) >> 8;
2818         params->type.text->color2.g = (((int)cc->g2 + 1) * text_desc->common.color2.g) >> 8;
2819         params->type.text->color2.b = (((int)cc->b2 + 1) * text_desc->common.color2.b) >> 8;
2820         params->type.text->color2.a = (((int)cc->a2 + 1) * text_desc->common.color2.a) >> 8;
2821         params->type.text->color3.r = (((int)cc->r3 + 1) * text_desc->text.color3.r) >> 8;
2822         params->type.text->color3.g = (((int)cc->g3 + 1) * text_desc->text.color3.g) >> 8;
2823         params->type.text->color3.b = (((int)cc->b3 + 1) * text_desc->text.color3.b) >> 8;
2824         params->type.text->color3.a = (((int)cc->a3 + 1) * text_desc->text.color3.a) >> 8;
2825      }
2826    else
2827      {
2828         params->type.text->color2.r = text_desc->common.color2.r;
2829         params->type.text->color2.g = text_desc->common.color2.g;
2830         params->type.text->color2.b = text_desc->common.color2.b;
2831         params->type.text->color2.a = text_desc->common.color2.a;
2832         params->type.text->color3.r = text_desc->text.color3.r;
2833         params->type.text->color3.g = text_desc->text.color3.g;
2834         params->type.text->color3.b = text_desc->text.color3.b;
2835         params->type.text->color3.a = text_desc->text.color3.a;
2836      }
2837 }
2838 
2839 static void
_edje_table_recalc_apply(Edje * ed EINA_UNUSED,Edje_Real_Part * ep,Edje_Calc_Params * p3 EINA_UNUSED,Edje_Part_Description_Table * chosen_desc)2840 _edje_table_recalc_apply(Edje *ed EINA_UNUSED,
2841                          Edje_Real_Part *ep,
2842                          Edje_Calc_Params *p3 EINA_UNUSED,
2843                          Edje_Part_Description_Table *chosen_desc)
2844 {
2845    evas_obj_table_homogeneous_set(ep->object, chosen_desc->table.homogeneous);
2846    evas_obj_table_align_set(ep->object, TO_DOUBLE(chosen_desc->table.align.x), TO_DOUBLE(chosen_desc->table.align.y));
2847    evas_obj_table_padding_set(ep->object, chosen_desc->table.padding.x, chosen_desc->table.padding.y);
2848    if (evas_object_smart_need_recalculate_get(ep->object))
2849      {
2850         efl_canvas_group_need_recalculate_set(ep->object, 0);
2851         efl_canvas_group_calculate(ep->object);
2852      }
2853 }
2854 
2855 static void
_edje_part_recalc_single(Edje * ed,Edje_Real_Part * ep,Edje_Part_Description_Common * desc,Edje_Part_Description_Common * chosen_desc,Edje_Real_Part * center,Edje_Real_Part * zoom_center,Edje_Real_Part * light,Edje_Real_Part * persp,Edje_Real_Part * rel1_to_x,Edje_Real_Part * rel1_to_y,Edje_Real_Part * rel2_to_x,Edje_Real_Part * rel2_to_y,Edje_Real_Part * clip_to,Edje_Real_Part * confine_to,Edje_Real_Part * threshold,Edje_Calc_Params * params,Evas_Coord mmw,Evas_Coord mmh,FLOAT_T pos)2856 _edje_part_recalc_single(Edje *ed,
2857                          Edje_Real_Part *ep,
2858                          Edje_Part_Description_Common *desc,
2859                          Edje_Part_Description_Common *chosen_desc,
2860                          Edje_Real_Part *center,
2861                          Edje_Real_Part *zoom_center,
2862                          Edje_Real_Part *light,
2863                          Edje_Real_Part *persp,
2864                          Edje_Real_Part *rel1_to_x,
2865                          Edje_Real_Part *rel1_to_y,
2866                          Edje_Real_Part *rel2_to_x,
2867                          Edje_Real_Part *rel2_to_y,
2868                          Edje_Real_Part *clip_to,
2869                          Edje_Real_Part *confine_to,
2870                          Edje_Real_Part *threshold,
2871                          Edje_Calc_Params *params,
2872                          Evas_Coord mmw, Evas_Coord mmh,
2873                          FLOAT_T pos)
2874 {
2875    Edje_Color_Class *cc = NULL;
2876    Edje_Internal_Aspect apref;
2877    int minw = 0, minh = 0, maxw = 0, maxh = 0;
2878    Eina_Bool fixedw = EINA_FALSE, fixedh = EINA_FALSE;
2879    FLOAT_T sc;
2880 
2881    sc = DIV(ed->scale, ed->file->base_scale);
2882    if (EQ(sc, ZERO)) sc = DIV(_edje_scale, ed->file->base_scale);
2883    _edje_part_recalc_single_min_max(sc, ed, ep, desc, &minw, &minh, &maxw, &maxh);
2884    if (minw < mmw) minw = mmw;
2885    if (minh < mmh) minh = mmh;
2886 
2887    /* relative coords of top left & bottom right */
2888    _edje_part_recalc_single_rel(ed, ep, desc, rel1_to_x, rel1_to_y, rel2_to_x, rel2_to_y, params);
2889 
2890    /* aspect */
2891    apref = _edje_part_recalc_single_aspect(ed, ep, desc, params, &minw, &minh, &maxw, &maxh, pos);
2892 
2893    /* size step */
2894    _edje_part_recalc_single_step(desc, params);
2895 
2896    /* check whether this part has fixed value or not*/
2897    if ((rel1_to_x == rel2_to_x) &&
2898        (EQ(desc->rel1.relative_x, desc->rel2.relative_x)) &&
2899        (!chosen_desc->fixed.w) && (!chosen_desc->user_set.fixed))
2900      {
2901         chosen_desc->fixed.w = 1;
2902         fixedw = EINA_TRUE;
2903      }
2904    if ((rel1_to_y == rel2_to_y) &&
2905        (EQ(desc->rel1.relative_y, desc->rel2.relative_y)) &&
2906        (!chosen_desc->fixed.h) && (!chosen_desc->user_set.fixed))
2907      {
2908         chosen_desc->fixed.h = 1;
2909         fixedh = EINA_TRUE;
2910      }
2911    if (fixedw || fixedh)
2912      _edje_part_recalc_single_fixed_info(ed, ep, fixedw, fixedh);
2913 
2914    /* colors */
2915    if (ep->part->type != EDJE_PART_TYPE_SPACER)
2916      {
2917         if ((desc->color_class) && (*desc->color_class))
2918           cc = _edje_color_class_recursive_find(ed, desc->color_class);
2919         if (cc)
2920           {
2921              params->color.r = (((int)cc->r + 1) * desc->color.r) >> 8;
2922              params->color.g = (((int)cc->g + 1) * desc->color.g) >> 8;
2923              params->color.b = (((int)cc->b + 1) * desc->color.b) >> 8;
2924              params->color.a = (((int)cc->a + 1) * desc->color.a) >> 8;
2925           }
2926         else
2927           {
2928              params->color.r = desc->color.r;
2929              params->color.g = desc->color.g;
2930              params->color.b = desc->color.b;
2931              params->color.a = desc->color.a;
2932           }
2933      }
2934 
2935    /* visible */
2936    params->visible = desc->visible;
2937 
2938    /* no_render override */
2939    if (EDJE_DESC_NO_RENDER_IS_SET(desc))
2940      {
2941         params->no_render = EDJE_DESC_NO_RENDER_VALUE(desc);
2942         params->no_render_apply = 1;
2943      }
2944    else
2945      {
2946         params->no_render = ep->part->no_render;
2947         params->no_render_apply = 0;
2948      }
2949 
2950    /* clip override */
2951    if (clip_to)
2952      {
2953         _edje_calc_params_need_ext(params);
2954         params->ext->clip_to = clip_to;
2955      }
2956 
2957    // set parameters, some are required for recalc_single_text[block]
2958    switch (ep->part->type)
2959      {
2960       case EDJE_PART_TYPE_TEXT:
2961         _edje_part_recalc_single_text0(params, (Edje_Part_Description_Text *)desc, cc);
2962         // limit size if needed
2963         _edje_part_recalc_single_text(sc, ed, ep, (Edje_Part_Description_Text *)desc, (Edje_Part_Description_Text *)chosen_desc, params, &minw, &minh, &maxw, &maxh);
2964         _edje_part_recalc_single_filter(ed, ep, desc, chosen_desc, pos);
2965         break;
2966       case EDJE_PART_TYPE_TEXTBLOCK:
2967         _edje_part_recalc_single_text0(params, (Edje_Part_Description_Text *)desc, cc);
2968         // limit size if needed
2969         _edje_part_recalc_single_textblock(sc, ed, ep, (Edje_Part_Description_Text *)chosen_desc, params, &minw, &minh, &maxw, &maxh);
2970         break;
2971       // or table/box containers that want to do the same
2972       case EDJE_PART_TYPE_TABLE:
2973         // limit size if needed
2974         if (((((Edje_Part_Description_Table *)chosen_desc)->table.min.h) ||
2975              (((Edje_Part_Description_Table *)chosen_desc)->table.min.v)))
2976           {
2977              _edje_table_recalc_apply(ed, ep, params, (Edje_Part_Description_Table *)chosen_desc);
2978              _edje_part_recalc_single_table(ep, chosen_desc, &minw, &minh);
2979           }
2980         break;
2981       case EDJE_PART_TYPE_BOX:
2982         // limit size if needed
2983         if ((((Edje_Part_Description_Box *)chosen_desc)->box.min.h) ||
2984             (((Edje_Part_Description_Box *)chosen_desc)->box.min.v))
2985           {
2986              _edje_box_recalc_apply(ed, ep, params, (Edje_Part_Description_Box *)chosen_desc);
2987              _edje_part_recalc_single_box(ep, chosen_desc, &minw, &minh);
2988           }
2989         break;
2990       case EDJE_PART_TYPE_IMAGE:
2991         _edje_part_recalc_single_image0(ed, ep, params, (Edje_Part_Description_Image *)desc, pos);
2992         // limit size if needed
2993         if (chosen_desc->min.limit || chosen_desc->max.limit)
2994           _edje_part_recalc_single_image(ed, ep, chosen_desc, pos, &minw, &minh, &maxw, &maxh);
2995         EINA_FALLTHROUGH;
2996       case EDJE_PART_TYPE_PROXY:
2997       case EDJE_PART_TYPE_SNAPSHOT:
2998         // image. proxy, snapshot share this filter recalc, so fall through
2999         _edje_part_recalc_single_filter(ed, ep, desc, chosen_desc, pos);
3000         break;
3001       case EDJE_PART_TYPE_SPACER:
3002       case EDJE_PART_TYPE_RECTANGLE:
3003       case EDJE_PART_TYPE_SWALLOW:
3004       case EDJE_PART_TYPE_GROUP:
3005       case EDJE_PART_TYPE_VECTOR:
3006       case EDJE_PART_TYPE_GRADIENT: // FIXME: THIS ONE SHOULD NEVER BE TRIGGERED
3007       default:
3008         break;
3009      }
3010 
3011    /* remember what our size is BEFORE we go limit it */
3012    params->req.x = TO_INT(params->eval.x);
3013    params->req.y = TO_INT(params->eval.y);
3014    params->req.w = TO_INT(params->eval.w);
3015    params->req.h = TO_INT(params->eval.h);
3016 
3017    /* adjust for min size */
3018    _edje_part_recalc_single_min(desc, params, minw, minh, apref);
3019 
3020    /* adjust for max size */
3021    _edje_part_recalc_single_max(desc, params, maxw, maxh, apref);
3022 
3023    /* take care of dragable part */
3024    if (ep->drag)
3025      _edje_part_recalc_single_drag(ep, confine_to, threshold, params, minw, minh, maxw, maxh);
3026 
3027    /* Update final size after last change to its position */
3028    params->final.x = TO_INT(params->eval.x);
3029    params->final.y = TO_INT(params->eval.y);
3030    params->final.w = TO_INT(params->eval.w);
3031    params->final.h = TO_INT(params->eval.h);
3032 
3033    _edje_part_pixel_adjust(ed, ep, params);
3034    /* fill */
3035    if (ep->part->type == EDJE_PART_TYPE_IMAGE)
3036      _edje_part_recalc_single_fill(ep, &((Edje_Part_Description_Image *)desc)->image.fill, params);
3037    else if (ep->part->type == EDJE_PART_TYPE_PROXY)
3038      _edje_part_recalc_single_fill(ep, &((Edje_Part_Description_Proxy *)desc)->proxy.fill, params);
3039 
3040 #ifdef HAVE_EPHYSICS
3041    if (EINA_UNLIKELY(ep->part->physics_body || ep->body))
3042      _edje_part_recalc_single_physics(params, desc);
3043 #endif
3044    _edje_part_recalc_single_map(ed, ep, center, zoom_center, light, persp, desc, chosen_desc, params);
3045 }
3046 
3047 static void
_edje_proxy_recalc_apply(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * p3,Edje_Part_Description_Proxy * chosen_desc,FLOAT_T pos)3048 _edje_proxy_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Proxy *chosen_desc, FLOAT_T pos)
3049 {
3050    Edje_Real_Part *pp;
3051    int part_id = -1;
3052 
3053    if (ep->param2 && (pos >= FROM_DOUBLE(0.5)))
3054      part_id = ((Edje_Part_Description_Proxy *)ep->param2->description)->proxy.id;
3055    else
3056      part_id = chosen_desc->proxy.id;
3057 
3058    if ((p3->type.common->fill.w == 0) || (p3->type.common->fill.h == 0) ||
3059        (part_id < 0))
3060      {
3061         evas_object_image_source_set(ep->object, NULL);
3062         return;
3063      }
3064    pp = ed->table_parts[part_id % ed->table_parts_size];
3065 
3066    if (pp->nested_smart)  /* using nested_smart for nested parts */
3067      {
3068         evas_object_image_source_set(ep->object, pp->nested_smart);
3069      }
3070    else
3071      {
3072         switch (pp->part->type)
3073           {
3074            case EDJE_PART_TYPE_IMAGE:
3075            case EDJE_PART_TYPE_TEXT:
3076            case EDJE_PART_TYPE_TEXTBLOCK:
3077            case EDJE_PART_TYPE_RECTANGLE:
3078            case EDJE_PART_TYPE_BOX:
3079            case EDJE_PART_TYPE_TABLE:
3080            case EDJE_PART_TYPE_PROXY:
3081            case EDJE_PART_TYPE_SNAPSHOT:
3082            case EDJE_PART_TYPE_VECTOR:
3083              evas_object_image_source_set(ep->object, pp->object);
3084              break;
3085 
3086            case EDJE_PART_TYPE_GRADIENT:
3087              /* FIXME: THIS ONE SHOULD NEVER BE TRIGGERED. */
3088              break;
3089 
3090            case EDJE_PART_TYPE_GROUP:
3091            case EDJE_PART_TYPE_SWALLOW:
3092            case EDJE_PART_TYPE_EXTERNAL:
3093              if ((pp->type == EDJE_RP_TYPE_SWALLOW) &&
3094                  (pp->typedata.swallow))
3095                {
3096                   evas_object_image_source_set(ep->object, pp->typedata.swallow->swallowed_object);
3097                }
3098              break;
3099 
3100            case EDJE_PART_TYPE_SPACER:
3101              /* FIXME: detect that at compile time and prevent it */
3102              break;
3103           }
3104      }
3105 
3106    efl_gfx_fill_set(ep->object, (Eina_Rect) p3->type.common->fill);
3107    efl_gfx_image_smooth_scale_set(ep->object, p3->smooth);
3108    evas_object_image_source_visible_set(ep->object, chosen_desc->proxy.source_visible);
3109    evas_object_image_source_clip_set(ep->object, chosen_desc->proxy.source_clip);
3110 }
3111 
3112 static void
_edje_image_recalc_apply(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * p3,Edje_Part_Description_Image * chosen_desc,FLOAT_T pos)3113 _edje_image_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Image *chosen_desc, FLOAT_T pos)
3114 {
3115    FLOAT_T sc;
3116    Edje_Real_Part_Set *set;
3117 
3118    sc = DIV(ed->scale, ed->file->base_scale);
3119    if (EQ(sc, ZERO)) sc = DIV(_edje_scale, ed->file->base_scale);
3120 
3121    _edje_real_part_image_set(ed, ep, &set, pos);
3122 
3123    /* border */
3124    _edje_calc_params_need_type_common(p3);
3125    p3->type.common->spec.image.l = chosen_desc->image.border.l;
3126    p3->type.common->spec.image.r = chosen_desc->image.border.r;
3127 
3128    p3->type.common->spec.image.t = chosen_desc->image.border.t;
3129    p3->type.common->spec.image.b = chosen_desc->image.border.b;
3130 
3131 //  XXX: do NOT do this. you can use border scale by to animate transitions
3132 //   p3->type.common->spec.image.border_scale_by = chosen_desc->image.border.scale_by;
3133 
3134    if (set && set->set)
3135      {
3136 #define SET_BORDER_DEFINED(Result, Value) Result = Value ? Value : Result;
3137         SET_BORDER_DEFINED(p3->type.common->spec.image.l, set->entry->border.l);
3138         SET_BORDER_DEFINED(p3->type.common->spec.image.r, set->entry->border.r);
3139         SET_BORDER_DEFINED(p3->type.common->spec.image.t, set->entry->border.t);
3140         SET_BORDER_DEFINED(p3->type.common->spec.image.b, set->entry->border.b);
3141 
3142         p3->type.common->spec.image.border_scale_by = NEQ(set->entry->border.scale_by, ZERO) ?
3143           set->entry->border.scale_by : p3->type.common->spec.image.border_scale_by;
3144      }
3145 
3146    efl_gfx_fill_set(ep->object, (Eina_Rect) p3->type.common->fill);
3147    efl_gfx_image_smooth_scale_set(ep->object, p3->smooth);
3148    if (chosen_desc->image.border.scale)
3149      {
3150         if (p3->type.common->spec.image.border_scale_by > FROM_DOUBLE(0.0))
3151           {
3152              FLOAT_T sc2 = MUL(sc, p3->type.common->spec.image.border_scale_by);
3153              evas_object_image_border_scale_set(ep->object, TO_DOUBLE(sc2));
3154           }
3155         else
3156           evas_object_image_border_scale_set(ep->object, TO_DOUBLE(sc));
3157      }
3158    else
3159      {
3160         if (p3->type.common->spec.image.border_scale_by > FROM_DOUBLE(0.0))
3161           evas_object_image_border_scale_set
3162             (ep->object, TO_DOUBLE(p3->type.common->spec.image.border_scale_by));
3163         else
3164           evas_object_image_border_scale_set(ep->object, 1.0);
3165      }
3166    evas_object_image_border_set(ep->object, p3->type.common->spec.image.l, p3->type.common->spec.image.r,
3167                                 p3->type.common->spec.image.t, p3->type.common->spec.image.b);
3168    if (chosen_desc->image.border.no_fill == 0)
3169      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_DEFAULT);
3170    else if (chosen_desc->image.border.no_fill == 1)
3171      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_NONE);
3172    else if (chosen_desc->image.border.no_fill == 2)
3173      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_SOLID);
3174 }
3175 
3176 #ifdef BUILD_VG_LOADER_JSON
3177 static void
_edje_vector_animation_running_cb(void * data,const Efl_Event * event)3178 _edje_vector_animation_running_cb(void *data, const Efl_Event *event)
3179 {
3180    double pos = *((double*)event->info);
3181    Edje_Real_Part *ep = (Edje_Real_Part *)data;
3182    int frame, frame_count;
3183 
3184    frame_count = efl_gfx_frame_controller_frame_count_get(ep->object) - 1;
3185    if (frame_count < 0) frame_count = 0;
3186 
3187    if (ep->typedata.vector->backward)
3188      frame = ep->typedata.vector->start_frame - (int) (frame_count * pos);
3189    else
3190      frame = ep->typedata.vector->start_frame + (int) (frame_count * pos);
3191 
3192    efl_gfx_frame_controller_frame_set(ep->object, frame);
3193 
3194    if ((ep->typedata.vector->backward && (frame <= 0)) ||
3195        (!ep->typedata.vector->backward && (frame >= frame_count)))
3196      {
3197         if (ep->typedata.vector->loop)
3198           {
3199              if (ep->typedata.vector->backward)
3200                ep->typedata.vector->start_frame = frame_count;
3201              else
3202                ep->typedata.vector->start_frame = 0;
3203 
3204              efl_canvas_object_animation_start(ep->object,
3205                                                ep->typedata.vector->anim,
3206                                                1.0, 0.0);
3207           }
3208         else
3209           {
3210              efl_canvas_object_animation_stop(ep->object);
3211           }
3212      }
3213 }
3214 
3215 static void
_edje_vector_load_lottie(Edje * ed,Edje_Real_Part * ep,const char * key)3216 _edje_vector_load_lottie(Edje *ed, Edje_Real_Part *ep, const char *key)
3217 {
3218    Edje_Part_Description_Vector *desc = (Edje_Part_Description_Vector *)ep->chosen_description;
3219    Eina_File *file;
3220    char *lottie_data;
3221    double frame_duration;
3222    int lottie_data_len = 0;
3223    int frame_count;
3224 
3225    if (ep->typedata.vector->anim == NULL)
3226      {
3227         Eo *anim = efl_add(EFL_CANVAS_ANIMATION_CLASS, ed->base.evas);
3228         ep->typedata.vector->anim = anim;
3229         efl_event_callback_add(ep->object,
3230                                EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_PROGRESS_UPDATED,
3231                                _edje_vector_animation_running_cb, ep);
3232      }
3233 
3234    if (ep->typedata.vector->current_id != desc->vg.id)
3235      {
3236         lottie_data = (char *)eet_read(ed->file->ef, key, &lottie_data_len);
3237         if (lottie_data)
3238           {
3239              lottie_data[lottie_data_len] = '\0';
3240              file = eina_file_virtualize(NULL, lottie_data, lottie_data_len + 1, EINA_FALSE);
3241              if (efl_file_loaded_get(ep->object)) efl_file_unload(ep->object);
3242              efl_file_simple_mmap_load(ep->object, file, NULL);
3243 
3244              if (ep->typedata.vector->lottie_virtual_file)
3245                eina_file_close(ep->typedata.vector->lottie_virtual_file);
3246              ep->typedata.vector->lottie_virtual_file = file;
3247 
3248              if (ep->typedata.vector->lottie_data)
3249                free(ep->typedata.vector->lottie_data);
3250              ep->typedata.vector->lottie_data = lottie_data;
3251 
3252              ep->typedata.vector->current_id = desc->vg.id;
3253           }
3254      }
3255 
3256    frame_duration = efl_gfx_frame_controller_frame_duration_get(ep->object, 0, 0);
3257    efl_animation_duration_set(ep->typedata.vector->anim, frame_duration);
3258 
3259    if (!ep->typedata.vector->is_playing)
3260      {
3261         frame_count = efl_gfx_frame_controller_frame_count_get(ep->object);
3262         efl_gfx_frame_controller_frame_set(ep->object, (int)(frame_count * desc->vg.frame));
3263      }
3264 }
3265 #endif
3266 
3267 static void
_edje_vector_recalc_apply(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * p3 EINA_UNUSED,Edje_Part_Description_Vector * chosen_desc,FLOAT_T pos)3268 _edje_vector_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_UNUSED, Edje_Part_Description_Vector *chosen_desc, FLOAT_T pos)
3269 {
3270    int new_id = -1; //invalid svg
3271    int w, h;
3272    char src_key[32], dest_key[32];
3273    Efl_VG *src_root, *dest_root, *root;
3274    Edje_Vector_File_Type type = chosen_desc->vg.type;
3275    Edje_Vector_File_Type new_type = EDJE_VECTOR_FILE_TYPE_SVG;
3276 
3277    evas_object_geometry_get(ep->object, NULL, NULL, &w, &h);
3278    if( (w == 0) || (h == 0)) return;
3279 
3280    snprintf(src_key, sizeof(src_key), "edje/vectors/%i", chosen_desc->vg.id);
3281 
3282    if (type == EDJE_VECTOR_FILE_TYPE_LOTTIE)
3283      {
3284 #ifdef BUILD_VG_LOADER_JSON
3285         _edje_vector_load_lottie(ed, ep, src_key);
3286 #else
3287         ERR("Evas Vg Lottie (Lottie) Loader is not supported, Only Static Vector Image(SVG) is available!");
3288 #endif
3289         return;
3290      }
3291 
3292    if (ep->param2)
3293      {
3294         Edje_Part_Description_Vector *next_state = (Edje_Part_Description_Vector *)ep->param2->description;
3295         if (chosen_desc->vg.id != next_state->vg.id)
3296           {
3297              new_id = next_state->vg.id;
3298              new_type = next_state->vg.type;
3299           }
3300         else
3301           {
3302              pos = 0;
3303           }
3304      }
3305 
3306    if ((new_id < 0) || (new_type == EDJE_VECTOR_FILE_TYPE_LOTTIE))
3307      {
3308 #ifndef BUILD_VG_LOADER_JSON
3309         if (new_type == EDJE_VECTOR_FILE_TYPE_LOTTIE)
3310           ERR("Evas Vg Lottie (Lottie) Loader is not supported, Only Static Vector Image(SVG) is available!");
3311         else
3312 #endif
3313           efl_file_simple_load(ep->object, ed->file->path, src_key);
3314      }
3315    else
3316      {
3317         Eina_Rect viewbox;
3318 
3319         snprintf(dest_key, sizeof(dest_key), "edje/vectors/%i", new_id);
3320 
3321         efl_file_simple_load(ep->object, ed->file->path, src_key);
3322         src_root = efl_canvas_vg_object_root_node_get(ep->object);
3323         efl_ref(src_root);
3324 
3325         // Note: Assume that the viewboxes of two interpolation objects are the same.
3326         viewbox = efl_canvas_vg_object_viewbox_get(ep->object);
3327 
3328         efl_file_simple_load(ep->object, ed->file->path, dest_key);
3329         dest_root = efl_canvas_vg_object_root_node_get(ep->object);
3330         efl_ref(dest_root);
3331 
3332         root = efl_duplicate(src_root);
3333         efl_canvas_vg_object_viewbox_set(ep->object, viewbox);
3334 
3335         if (!efl_gfx_path_interpolate(root, src_root, dest_root, pos))
3336           ERR("Can't interpolate check the svg file");
3337 
3338         efl_canvas_vg_object_root_node_set(ep->object, root);
3339 
3340         efl_unref(root);
3341         efl_unref(src_root);
3342         efl_unref(dest_root);
3343      }
3344 }
3345 
3346 #ifdef BUILD_VG_LOADER_JSON
3347 void
_edje_part_vector_anim_stop(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)3348 _edje_part_vector_anim_stop(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
3349 {
3350    Edje_Part_Description_Vector *desc = (Edje_Part_Description_Vector *)rp->chosen_description;
3351    double frame_count = efl_gfx_frame_controller_frame_count_get(rp->object);
3352 
3353    efl_canvas_object_animation_stop(rp->object);
3354    efl_gfx_frame_controller_frame_set(rp->object, (int)(frame_count * desc->vg.frame));
3355    rp->typedata.vector->is_playing = EINA_FALSE;
3356 }
3357 
3358 void
_edje_part_vector_anim_pause(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)3359 _edje_part_vector_anim_pause(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
3360 {
3361    efl_canvas_object_animation_pause_set(rp->object, EINA_TRUE);
3362 }
3363 
3364 void
_edje_part_vector_anim_resume(Edje * ed EINA_UNUSED,Edje_Real_Part * rp)3365 _edje_part_vector_anim_resume(Edje *ed EINA_UNUSED, Edje_Real_Part *rp)
3366 {
3367    if (rp->typedata.vector->is_playing)
3368      {
3369         rp->typedata.vector->start_frame = efl_gfx_frame_controller_frame_get(rp->object);
3370         efl_canvas_object_animation_pause_set(rp->object, EINA_FALSE);
3371      }
3372 }
3373 
3374 void
_edje_part_vector_anim_play(Edje * ed EINA_UNUSED,Edje_Real_Part * rp,Eina_Bool backward,Eina_Bool loop)3375 _edje_part_vector_anim_play(Edje *ed EINA_UNUSED, Edje_Real_Part *rp, Eina_Bool backward, Eina_Bool loop)
3376 {
3377    rp->typedata.vector->backward = backward;
3378    rp->typedata.vector->loop = loop;
3379    rp->typedata.vector->start_frame = efl_gfx_frame_controller_frame_get(rp->object);
3380    rp->typedata.vector->is_playing = EINA_TRUE;
3381    efl_canvas_object_animation_start(rp->object, rp->typedata.vector->anim, 1.0, 0.0);
3382 }
3383 #endif
3384 
3385 static Edje_Real_Part *
_edje_real_part_state_get(Edje * ed,Edje_Real_Part * ep,int flags,int id,int * state)3386 _edje_real_part_state_get(Edje *ed, Edje_Real_Part *ep, int flags, int id, int *state)
3387 {
3388    Edje_Real_Part *result = NULL;
3389 
3390    if (id >= 0 && id != ep->part->id)
3391      {
3392         result = ed->table_parts[id % ed->table_parts_size];
3393         if (result)
3394           {
3395              if (!result->calculated) _edje_part_recalc(ed, result, flags, NULL);
3396 #ifdef EDJE_CALC_CACHE
3397              if (state) *state = result->state;
3398 #else
3399              (void)state;
3400 #endif
3401           }
3402      }
3403    return result;
3404 }
3405 
3406 #ifdef HAVE_EPHYSICS
3407 static Eina_Bool
_edje_physics_world_geometry_check(EPhysics_World * world)3408 _edje_physics_world_geometry_check(EPhysics_World *world)
3409 {
3410    Evas_Coord w, h, d;
3411    if (!EPH_LOAD()) return EINA_FALSE;
3412    EPH_CALL(ephysics_world_render_geometry_get)(world, NULL, NULL, NULL, &w, &h, &d);
3413    return w && h && d;
3414 }
3415 
3416 static void
_edje_physics_body_props_update(Edje * ed,Edje_Real_Part * ep,Edje_Calc_Params * pf,Eina_Bool pos_update)3417 _edje_physics_body_props_update(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *pf,
3418                                 Eina_Bool pos_update)
3419 {
3420    if (!EPH_LOAD()) return;
3421    _edje_calc_params_need_ext(pf);
3422    EPH_CALL(ephysics_body_linear_movement_enable_set)
3423      (ep->body,
3424       pf->ext->physics->mov_freedom.lin.x,
3425       pf->ext->physics->mov_freedom.lin.y,
3426       pf->ext->physics->mov_freedom.lin.z);
3427    EPH_CALL(ephysics_body_angular_movement_enable_set)
3428      (ep->body,
3429       pf->ext->physics->mov_freedom.ang.x,
3430       pf->ext->physics->mov_freedom.ang.y,
3431       pf->ext->physics->mov_freedom.ang.z);
3432 
3433    /* Boundaries geometry and mass shouldn't be changed */
3434    if (ep->part->physics_body < EDJE_PART_PHYSICS_BODY_BOUNDARY_TOP)
3435      {
3436         Evas_Coord x, y, z, w, h, d;
3437 
3438         if (pos_update)
3439           {
3440              EPH_CALL(ephysics_body_move)
3441                (ep->body,
3442                 ed->x + pf->final.x,
3443                 ed->y + pf->final.y,
3444                 pf->ext->physics->z);
3445              ep->x = pf->final.x;
3446              ep->y = pf->final.y;
3447              ep->w = pf->final.w;
3448              ep->h = pf->final.h;
3449           }
3450 
3451         EPH_CALL(ephysics_body_geometry_get)(ep->body, &x, &y, &z, &w, &h, &d);
3452         if ((d) && (d != pf->ext->physics->depth))
3453           EPH_CALL(ephysics_body_resize)(ep->body, w, h, pf->ext->physics->depth);
3454         if (z != pf->ext->physics->z)
3455           EPH_CALL(ephysics_body_move)(ep->body, x, y, pf->ext->physics->z);
3456 
3457         EPH_CALL(ephysics_body_material_set)(ep->body, pf->ext->physics->material);
3458         if (!pf->ext->physics->material)
3459           {
3460              if (NEQ(pf->ext->physics->density, ZERO))
3461                EPH_CALL(ephysics_body_density_set)(ep->body, pf->ext->physics->density);
3462              else
3463                EPH_CALL(ephysics_body_mass_set)(ep->body, pf->ext->physics->mass);
3464           }
3465 
3466         if ((ep->part->physics_body == EDJE_PART_PHYSICS_BODY_SOFT_BOX) ||
3467             (ep->part->physics_body == EDJE_PART_PHYSICS_BODY_SOFT_SPHERE) ||
3468             (ep->part->physics_body == EDJE_PART_PHYSICS_BODY_SOFT_CYLINDER) ||
3469             (ep->part->physics_body == EDJE_PART_PHYSICS_BODY_CLOTH))
3470           EPH_CALL(ephysics_body_soft_body_hardness_set)
3471             (ep->body, pf->ext->physics->hardness * 100);
3472      }
3473 
3474    if (!pf->ext->physics->material)
3475      {
3476         EPH_CALL(ephysics_body_restitution_set)(ep->body, pf->ext->physics->restitution);
3477         EPH_CALL(ephysics_body_friction_set)(ep->body, pf->ext->physics->friction);
3478      }
3479 
3480    EPH_CALL(ephysics_body_damping_set)(ep->body, pf->ext->physics->damping.linear,
3481                                        pf->ext->physics->damping.angular);
3482    EPH_CALL(ephysics_body_sleeping_threshold_set)(ep->body, pf->ext->physics->sleep.linear,
3483                                                   pf->ext->physics->sleep.angular);
3484    EPH_CALL(ephysics_body_light_set)(ep->body, pf->ext->physics->light_on);
3485    EPH_CALL(ephysics_body_back_face_culling_set)(ep->body, pf->ext->physics->backcull);
3486 }
3487 
3488 static void
_edje_physics_body_update_cb(void * data,EPhysics_Body * body,void * event_info EINA_UNUSED)3489 _edje_physics_body_update_cb(void *data, EPhysics_Body *body, void *event_info EINA_UNUSED)
3490 {
3491    Edje_Real_Part *rp = data;
3492    Edje *ed;
3493 
3494    if (!EPH_LOAD()) return;
3495    ed = EPH_CALL(ephysics_body_data_get(body));
3496    EPH_CALL(ephysics_body_geometry_get)(body, &(rp->x), &(rp->y), NULL,
3497                                         &(rp->w), &(rp->h), NULL);
3498    EPH_CALL(ephysics_body_evas_object_update)(body);
3499    ed->dirty = EINA_TRUE;
3500 }
3501 
3502 static void
_edje_physics_body_add(Edje * ed,Edje_Real_Part * rp,EPhysics_World * world)3503 _edje_physics_body_add(Edje *ed, Edje_Real_Part *rp, EPhysics_World *world)
3504 {
3505    Eina_Bool resize = EINA_TRUE;
3506    Edje_Physics_Face *pface;
3507    Eina_List *l;
3508 
3509    if (!EPH_LOAD()) return;
3510    switch (rp->part->physics_body)
3511      {
3512       case EDJE_PART_PHYSICS_BODY_RIGID_BOX:
3513         rp->body = EPH_CALL(ephysics_body_box_add)(world);
3514         break;
3515 
3516       case EDJE_PART_PHYSICS_BODY_RIGID_SPHERE:
3517         rp->body = EPH_CALL(ephysics_body_sphere_add)(world);
3518         break;
3519 
3520       case EDJE_PART_PHYSICS_BODY_RIGID_CYLINDER:
3521         rp->body = EPH_CALL(ephysics_body_cylinder_add)(world);
3522         break;
3523 
3524       case EDJE_PART_PHYSICS_BODY_SOFT_BOX:
3525         rp->body = EPH_CALL(ephysics_body_soft_box_add)(world);
3526         break;
3527 
3528       case EDJE_PART_PHYSICS_BODY_SOFT_SPHERE:
3529         rp->body = EPH_CALL(ephysics_body_soft_sphere_add)(world, 0);
3530         break;
3531 
3532       case EDJE_PART_PHYSICS_BODY_SOFT_CYLINDER:
3533         rp->body = EPH_CALL(ephysics_body_soft_cylinder_add)(world);
3534         break;
3535 
3536       case EDJE_PART_PHYSICS_BODY_CLOTH:
3537         rp->body = EPH_CALL(ephysics_body_cloth_add)(world, 0, 0);
3538         break;
3539 
3540       case EDJE_PART_PHYSICS_BODY_BOUNDARY_TOP:
3541         rp->body = EPH_CALL(ephysics_body_top_boundary_add)(world);
3542         resize = EINA_FALSE;
3543         break;
3544 
3545       case EDJE_PART_PHYSICS_BODY_BOUNDARY_BOTTOM:
3546         rp->body = EPH_CALL(ephysics_body_bottom_boundary_add)(world);
3547         resize = EINA_FALSE;
3548         break;
3549 
3550       case EDJE_PART_PHYSICS_BODY_BOUNDARY_RIGHT:
3551         rp->body = EPH_CALL(ephysics_body_right_boundary_add)(world);
3552         resize = EINA_FALSE;
3553         break;
3554 
3555       case EDJE_PART_PHYSICS_BODY_BOUNDARY_LEFT:
3556         rp->body = EPH_CALL(ephysics_body_left_boundary_add)(world);
3557         resize = EINA_FALSE;
3558         break;
3559 
3560       case EDJE_PART_PHYSICS_BODY_BOUNDARY_FRONT:
3561         rp->body = EPH_CALL(ephysics_body_front_boundary_add)(world);
3562         resize = EINA_FALSE;
3563         break;
3564 
3565       case EDJE_PART_PHYSICS_BODY_BOUNDARY_BACK:
3566         rp->body = EPH_CALL(ephysics_body_back_boundary_add)(world);
3567         resize = EINA_FALSE;
3568         break;
3569 
3570       default:
3571         ERR("Invalid body: %i", rp->part->physics_body);
3572         return;
3573      }
3574 
3575    EINA_LIST_FOREACH(rp->part->default_desc->physics.faces, l, pface)
3576      {
3577         Evas_Object *edje_obj;
3578         Evas *evas;
3579 
3580         if (!pface->source) continue;
3581 
3582         evas = evas_object_evas_get(rp->object);
3583         edje_obj = edje_object_add(evas);
3584         if (!edje_obj) continue;
3585 
3586         edje_object_file_set(edje_obj, ed->path, pface->source);
3587         evas_object_resize(edje_obj, 1, 1);
3588         EPH_CALL(ephysics_body_face_evas_object_set)(rp->body, pface->type,
3589                                                      edje_obj, EINA_FALSE);
3590         rp->body_faces = eina_list_append(rp->body_faces, edje_obj);
3591      }
3592 
3593    EPH_CALL(ephysics_body_evas_object_set)(rp->body, rp->object, resize);
3594    EPH_CALL(ephysics_body_event_callback_add)(rp->body, EPHYSICS_CALLBACK_BODY_UPDATE,
3595                                               _edje_physics_body_update_cb, rp);
3596    EPH_CALL(ephysics_body_data_set)(rp->body, ed);
3597 }
3598 
3599 #endif
3600 
3601 #define FINTP(_x1, _x2, _p)                     \
3602   ((((int)_x1) == ((int)_x2))                   \
3603    ? FROM_INT((_x1))                            \
3604    : ADD(FROM_INT(_x1),                         \
3605          SCALE((_p), (_x2) - (_x1))))
3606 
3607 #define FFP(_x1, _x2, _p) \
3608   (EQ((_x1), (_x2))       \
3609    ? (_x1)                \
3610    : ADD(_x1, MUL(_p, SUB(_x2, _x1))));
3611 
3612 #define INTP(_x1, _x2, _p) TO_INT(FINTP(_x1, _x2, _p))
3613 
3614 static void
_map_colors_free(Edje_Calc_Params * pf)3615 _map_colors_free(Edje_Calc_Params *pf)
3616 {
3617    if (pf->ext)
3618      {
3619         Edje_Map_Color **colors = pf->ext->map->colors;
3620         int i;
3621 
3622         for (i = 0; i < (int)pf->ext->map->colors_count; i++) free(colors[i]);
3623         free(colors);
3624      }
3625 }
3626 
3627 static Eina_Bool
_map_colors_interp(Edje_Calc_Params * p1,Edje_Calc_Params * p2,Edje_Calc_Params_Map * pmap,FLOAT_T pos)3628 _map_colors_interp(Edje_Calc_Params *p1, Edje_Calc_Params *p2,
3629                    Edje_Calc_Params_Map *pmap, FLOAT_T pos)
3630 {
3631    Edje_Map_Color *col = NULL, *col2 = NULL, *col3;
3632    int i, j;
3633 
3634    unsigned char col1_r = 255, col1_g = 255, col1_b = 255, col1_a = 255;
3635    unsigned char col2_r = 255, col2_g = 255, col2_b = 255, col2_a = 255;
3636 
3637    _edje_calc_params_need_ext(p1);
3638    _edje_calc_params_need_ext(p2);
3639 
3640    if ((p1->ext->map->colors_count > 0) || (p2->ext->map->colors_count > 0))
3641      {
3642         pmap->colors_count = (p1->ext->map->colors_count > p2->ext->map->colors_count ? p1->ext->map->colors_count : p2->ext->map->colors_count);
3643 
3644         pmap->colors = (Edje_Map_Color **)malloc(sizeof(Edje_Map_Color *) * (int)pmap->colors_count);
3645 
3646         /* create all Map Color structs at first
3647            to make sure we won't get SIGSEV later on cleanup. */
3648         for (i = 0; i < (int)pmap->colors_count; i++)
3649           {
3650              col3 = malloc(sizeof(Edje_Map_Color));
3651              col3->idx = i; /* we don't care about index position anyway */
3652 
3653              /* find color with idx from first */
3654              for (j = 0; j < (int)p1->ext->map->colors_count; j++)
3655                {
3656                   col = p1->ext->map->colors[j];
3657                   if (col3->idx == col->idx)
3658                     {
3659                        col1_r = col->r;
3660                        col1_g = col->g;
3661                        col1_b = col->b;
3662                        col1_a = col->a;
3663                        break;
3664                     }
3665                }
3666              /* find color from idx from second */
3667              for (j = 0; j < (int)p2->ext->map->colors_count; j++)
3668                {
3669                   col2 = p2->ext->map->colors[j];
3670                   if (col3->idx == col2->idx)
3671                     {
3672                        col2_r = col2->r;
3673                        col2_g = col2->g;
3674                        col2_b = col2->b;
3675                        col2_a = col2->a;
3676                        break;
3677                     }
3678                }
3679 
3680              /* interpolate!
3681                 if color didn't existed, then there are default 255 values */
3682              col3->r = INTP(col1_r, col2_r, pos);
3683              col3->g = INTP(col1_g, col2_g, pos);
3684              col3->b = INTP(col1_b, col2_b, pos);
3685              col3->a = INTP(col1_a, col2_a, pos);
3686 
3687              pmap->colors[i] = col3;
3688           }
3689 
3690         return EINA_TRUE;
3691      }
3692 
3693    return EINA_FALSE;
3694 }
3695 
3696 static void
_edje_map_prop_set(Evas_Map * map,const Edje_Calc_Params * pf,Edje_Part_Description_Common * chosen_desc,Edje_Real_Part * ep,Evas_Object * mo,Evas_Object * populate_obj)3697 _edje_map_prop_set(Evas_Map *map, const Edje_Calc_Params *pf,
3698                    Edje_Part_Description_Common *chosen_desc,
3699                    Edje_Real_Part *ep, Evas_Object *mo, Evas_Object *populate_obj)
3700 {
3701    Edje_Map_Color *color, **colors;
3702    int colors_cnt, i;
3703 
3704    if (!pf->ext) return;
3705 
3706    colors = pf->ext->map->colors;
3707    colors_cnt = pf->ext->map->colors_count;
3708 
3709    evas_map_util_points_populate_from_object(map, populate_obj ?: ep->object);
3710 
3711    if (ep->part->type == EDJE_PART_TYPE_IMAGE ||
3712        ((ep->part->type == EDJE_PART_TYPE_SWALLOW) &&
3713         (efl_isa(mo, EFL_CANVAS_IMAGE_INTERNAL_CLASS) &&
3714          (!evas_object_image_source_get(mo))))
3715        )
3716      {
3717         int iw = 1, ih = 1;
3718 
3719         evas_object_image_size_get(mo, &iw, &ih);
3720         evas_map_point_image_uv_set(map, 0, 0.0, 0.0);
3721         evas_map_point_image_uv_set(map, 1, iw, 0.0);
3722         evas_map_point_image_uv_set(map, 2, iw, ih);
3723         evas_map_point_image_uv_set(map, 3, 0.0, ih);
3724      }
3725 
3726    //map color
3727    if (colors_cnt == 0)
3728      {
3729         evas_map_point_color_set(map, 0, 255, 255, 255, 255);
3730         evas_map_point_color_set(map, 1, 255, 255, 255, 255);
3731         evas_map_point_color_set(map, 2, 255, 255, 255, 255);
3732         evas_map_point_color_set(map, 3, 255, 255, 255, 255);
3733      }
3734    else
3735      {
3736         for (i = 0; i < colors_cnt; i++)
3737           {
3738              color = colors[i];
3739              evas_map_point_color_set(map, color->idx, color->r, color->g,
3740                                       color->b, color->a);
3741           }
3742      }
3743 
3744    //zoom
3745    evas_map_util_zoom(map,
3746                       pf->ext->map->zoom.x, pf->ext->map->zoom.y,
3747                       pf->ext->map->zoom_center.x, pf->ext->map->zoom_center.y);
3748 
3749    //rotate
3750    evas_map_util_3d_rotate(map,
3751                            TO_DOUBLE(pf->ext->map->rotation.x),
3752                            TO_DOUBLE(pf->ext->map->rotation.y),
3753                            TO_DOUBLE(pf->ext->map->rotation.z),
3754                            pf->ext->map->center.x, pf->ext->map->center.y,
3755                            pf->ext->map->center.z);
3756 
3757    // calculate light color & position etc. if there is one
3758    if (pf->lighted)
3759      {
3760         evas_map_util_3d_lighting(map, pf->ext->map->light.x, pf->ext->map->light.y,
3761                                   pf->ext->map->light.z, pf->ext->map->light.r,
3762                                   pf->ext->map->light.g, pf->ext->map->light.b,
3763                                   pf->ext->map->light.ar, pf->ext->map->light.ag,
3764                                   pf->ext->map->light.ab);
3765      }
3766 
3767    // calculate perspective point
3768    if (chosen_desc->map.persp_on)
3769      {
3770         evas_map_util_3d_perspective(map,
3771                                      pf->ext->map->persp.x, pf->ext->map->persp.y,
3772                                      pf->ext->map->persp.z, pf->ext->map->persp.focal);
3773      }
3774 
3775    // handle backface culling (object is facing away from view
3776    if (chosen_desc->map.backcull)
3777      {
3778         if (pf->visible)
3779           {
3780              if (evas_map_util_clockwise_get(map))
3781                evas_object_show(mo);
3782              else evas_object_hide(mo);
3783           }
3784      }
3785 
3786    // handle smooth
3787    if (chosen_desc->map.smooth) evas_map_smooth_set(map, EINA_TRUE);
3788    else evas_map_smooth_set(map, EINA_FALSE);
3789    // handle alpha
3790    if (chosen_desc->map.alpha) evas_map_alpha_set(map, EINA_TRUE);
3791    else evas_map_alpha_set(map, EINA_FALSE);
3792 }
3793 
3794 #define Rel1X 0
3795 #define Rel1Y 1
3796 #define Rel2X 2
3797 #define Rel2Y 3
3798 static Eina_Bool
_circular_dependency_find(Edje * ed,Edje_Real_Part * ep,Edje_Real_Part * cep,Eina_Array * arr)3799 _circular_dependency_find(Edje *ed, Edje_Real_Part *ep, Edje_Real_Part *cep, Eina_Array *arr)
3800 {
3801    Edje_Real_Part *rp = NULL;
3802 
3803    if (cep == ep) return EINA_TRUE;
3804    if (!cep) cep = ep;
3805 
3806    if ((cep->calculating & FLAG_X))
3807      {
3808         if (cep->param1.description)
3809           {
3810              if (cep->param1.description->rel1.id_x >= 0)
3811                {
3812                   rp = ed->table_parts[cep->param1.description->rel1.id_x];
3813                   if (_circular_dependency_find(ed, ep, rp, arr))
3814                     {
3815                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3816                        return EINA_TRUE;
3817                     }
3818                }
3819              if (cep->param1.description->rel2.id_x >= 0)
3820                {
3821                   rp = ed->table_parts[cep->param1.description->rel2.id_x];
3822                   if (_circular_dependency_find(ed, ep, rp, arr))
3823                     {
3824                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3825                        return EINA_TRUE;
3826                     }
3827                }
3828           }
3829 
3830         if (cep->param2)
3831           {
3832              if (cep->param2->description->rel1.id_x >= 0)
3833                {
3834                   rp = ed->table_parts[cep->param2->description->rel1.id_x];
3835                   if (_circular_dependency_find(ed, ep, rp, arr))
3836                     {
3837                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3838                        return EINA_TRUE;
3839                     }
3840                }
3841              if (cep->param2->description->rel2.id_x >= 0)
3842                {
3843                   rp = ed->table_parts[cep->param2->description->rel2.id_x];
3844                   if (_circular_dependency_find(ed, ep, rp, arr))
3845                     {
3846                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3847                        return EINA_TRUE;
3848                     }
3849                }
3850           }
3851      }
3852    if ((cep->calculating & FLAG_Y))
3853      {
3854         if (cep->param1.description)
3855           {
3856              if (cep->param1.description->rel1.id_y >= 0)
3857                {
3858                   rp = ed->table_parts[cep->param1.description->rel1.id_y];
3859                   if (_circular_dependency_find(ed, ep, rp, arr))
3860                     {
3861                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3862                        return EINA_TRUE;
3863                     }
3864                }
3865              if (cep->param1.description->rel2.id_y >= 0)
3866                {
3867                   rp = ed->table_parts[cep->param1.description->rel2.id_y];
3868                   if (_circular_dependency_find(ed, ep, rp, arr))
3869                     {
3870                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3871                        return EINA_TRUE;
3872                     }
3873                }
3874           }
3875         if (cep->param2)
3876           {
3877              if (cep->param2->description->rel1.id_y >= 0)
3878                {
3879                   rp = ed->table_parts[cep->param2->description->rel1.id_y];
3880                   if (_circular_dependency_find(ed, ep, rp, arr))
3881                     {
3882                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3883                        return EINA_TRUE;
3884                     }
3885                }
3886              if (cep->param2->description->rel2.id_y >= 0)
3887                {
3888                   rp = ed->table_parts[cep->param2->description->rel2.id_y];
3889                   if (_circular_dependency_find(ed, ep, rp, arr))
3890                     {
3891                        eina_array_push(arr, eina_stringshare_add(rp->part->name));
3892                        return EINA_TRUE;
3893                     }
3894                }
3895           }
3896      }
3897 
3898    return EINA_FALSE;
3899 }
3900 
3901 static void
_edje_part_calc_params_memcpy(Edje_Calc_Params * p,Edje_Calc_Params * s,Edje_Part_Type t)3902 _edje_part_calc_params_memcpy(Edje_Calc_Params *p, Edje_Calc_Params *s, Edje_Part_Type t)
3903 {
3904    _edje_calc_params_clear(p);
3905    memcpy(p, s, sizeof(Edje_Calc_Params));
3906    if (s->ext)
3907      {
3908         p->ext = NULL;
3909         _edje_calc_params_need_ext(p);
3910 #ifdef EDJE_CALC_CACHE
3911         eina_cow_memcpy(_edje_calc_params_map_cow,
3912                         (const Eina_Cow_Data **)&(p->ext->map),
3913                         s->ext->map);
3914 # ifdef HAVE_EPHYSICS
3915         eina_cow_memcpy(_edje_calc_params_physics_cow,
3916                         (const Eina_Cow_Data **)&(p->ext->physics),
3917                         s->ext->physics);
3918 # endif
3919 #endif
3920      }
3921    switch (t)
3922      {
3923       case EDJE_PART_TYPE_IMAGE:
3924           {
3925              Edje_Calc_Params_Type_Common *d = malloc(sizeof(*d));
3926              if (d)
3927                {
3928                   memcpy(d, s->type.common, sizeof(*d));
3929                   p->type.common = d;
3930                }
3931              else p->type.common = NULL;
3932           }
3933         break;
3934       case EDJE_PART_TYPE_TEXT:
3935       case EDJE_PART_TYPE_TEXTBLOCK:
3936           {
3937              Edje_Calc_Params_Type_Text *d = malloc(sizeof(*d));
3938              if (d)
3939                {
3940                   memcpy(d, s->type.text, sizeof(*d));
3941                   p->type.text = d;
3942                }
3943              else p->type.text = NULL;
3944           }
3945         break;
3946       default:
3947         break;
3948      }
3949 }
3950 
3951 void
_edje_part_recalc(Edje * ed,Edje_Real_Part * ep,int flags,Edje_Calc_Params * state)3952 _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state)
3953 {
3954 #ifdef EDJE_CALC_CACHE
3955    Eina_Bool proxy_invalidate = EINA_FALSE;
3956    int state1 = -1;
3957    int state2 = -1;
3958    int statec = -1;
3959    int statet = -1;
3960 #else
3961    Edje_Calc_Params lp1, lp2;
3962 #endif
3963    int statec1 = -1;
3964    int statec2 = -1;
3965    int statel1 = -1;
3966    int statel2 = -1;
3967    int statep1 = -1;
3968    int statep2 = -1;
3969    int statecl = -1;
3970    Edje_Real_Part *center[2] = { NULL, NULL };
3971    Edje_Real_Part *zoom_center[2] = { NULL, NULL };
3972    Edje_Real_Part *light[2] = { NULL, NULL };
3973    Edje_Real_Part *persp[2] = { NULL, NULL };
3974    Edje_Real_Part *rp1[4] = { NULL, NULL, NULL, NULL };
3975    Edje_Real_Part *rp2[4] = { NULL, NULL, NULL, NULL };
3976    Edje_Real_Part *clip1 = NULL, *clip2 = NULL;
3977    Edje_Calc_Params *p1, *pf;
3978    Edje_Part_Description_Common *chosen_desc;
3979    Edje_Real_Part *confine_to = NULL;
3980    Edje_Real_Part *threshold = NULL;
3981    FLOAT_T pos = ZERO, pos2;
3982    Edje_Calc_Params lp3 = { { 0 } };
3983    Evas_Coord mmw = 0, mmh = 0;
3984    Eina_Bool map_colors_free = EINA_FALSE;
3985 
3986 #ifdef EDJE_CALC_CACHE
3987 #else
3988    lp1.type.common = NULL;
3989    lp1.ext = NULL;
3990 
3991    lp2.type.common = NULL;
3992    lp2.ext = NULL;
3993 #endif
3994 
3995    lp3.type.common = NULL;
3996    lp3.ext = NULL;
3997 
3998    /* GRADIENT ARE GONE, WE MUST IGNORE IT FROM OLD FILE. */
3999    if (ep->part->type == EDJE_PART_TYPE_GRADIENT)
4000      {
4001         ERR("GRADIENT spotted during recalc ! That should never happen ! Send your edje file to devel ml.");
4002         return;
4003      }
4004 
4005    EINA_SAFETY_ON_FALSE_RETURN(flags != FLAG_NONE);
4006    if (!state)
4007      {
4008         if ((ep->calculated & FLAG_XY) == FLAG_XY) return;
4009         if ((ep->calculated & flags) == flags) return;
4010      }
4011 
4012    if (ep->calculating & flags)
4013      {
4014 #if 1
4015         const char *axes = "NONE", *faxes = "NONE";
4016 
4017         if ((ep->calculating & FLAG_X) &&
4018             (ep->calculating & FLAG_Y))
4019           axes = "XY";
4020         else if ((ep->calculating & FLAG_X))
4021           axes = "X";
4022         else if ((ep->calculating & FLAG_Y))
4023           axes = "Y";
4024 
4025         if ((flags & FLAG_X) &&
4026             (flags & FLAG_Y))
4027           faxes = "XY";
4028         else if ((flags & FLAG_X))
4029           faxes = "X";
4030         else if ((flags & FLAG_Y))
4031           faxes = "Y";
4032         ERR("Circular dependency when calculating part \"%s\". "
4033             "Already calculating %s [%02x] axes. "
4034             "Need to calculate %s [%02x] axes",
4035             ep->part->name,
4036             axes, ep->calculating,
4037             faxes, flags);
4038 
4039         Eina_Array *part_array = eina_array_new(10);;
4040 
4041         if (_circular_dependency_find(ed, ep, NULL, part_array))
4042           {
4043              Eina_Array_Iterator it;
4044              unsigned int i;
4045              char *part_name;
4046              char depends_path[PATH_MAX] = "";
4047 
4048              efl_event_callback_legacy_call(ed->obj, EFL_LAYOUT_EVENT_CIRCULAR_DEPENDENCY, part_array);
4049              strncat(depends_path, ep->part->name,
4050                      sizeof(depends_path) - strlen(depends_path) - 1);
4051              EINA_ARRAY_ITER_NEXT(part_array, i, part_name, it)
4052                {
4053                   strncat(depends_path, " -> ",
4054                           sizeof(depends_path) - strlen(depends_path) - 1);
4055                   strncat(depends_path, part_name,
4056                           sizeof(depends_path) - strlen(depends_path) - 1);
4057                   eina_stringshare_del(part_name);
4058                }
4059              ERR("Circular dependency in the group '%s' : %s",
4060                  ed->group, depends_path);
4061           }
4062 
4063         eina_array_free(part_array);
4064 #endif
4065         return;
4066      }
4067 
4068    if (ep->part->type == EDJE_PART_TYPE_GROUP &&
4069        ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
4070         (ep->typedata.swallow)) &&
4071        ep->typedata.swallow->swallowed_object)
4072      {
4073         edje_object_scale_set(ep->typedata.swallow->swallowed_object, TO_DOUBLE(ed->scale));
4074 
4075         if (ep->description_pos > FROM_DOUBLE(0.5) && ep->param2)
4076           {
4077              edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param2->description->min.limit);
4078           }
4079         else
4080           {
4081              edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param1.description->min.limit);
4082           }
4083         if (edje_object_update_hints_get(ep->typedata.swallow->swallowed_object))
4084           {
4085              Edje *ted;
4086 
4087              ted = _edje_fetch(ep->typedata.swallow->swallowed_object);
4088              _edje_recalc_do(ted);
4089           }
4090 
4091         Edje_Size *min = NULL, *max = NULL;
4092 
4093         if (ep->chosen_description)
4094           {
4095              min = &ep->chosen_description->min;
4096              max = &ep->chosen_description->max;
4097           }
4098         if (min && max && (min->w == max->w) && (min->h == max->h) && (min->w > 0) && (min->h > 0))
4099           mmw = min->w, mmh = min->h;
4100         else
4101           edje_object_size_min_calc(ep->typedata.swallow->swallowed_object,
4102                                     &mmw, &mmh);
4103      }
4104 
4105 #ifdef EDJE_CALC_CACHE
4106    if (ep->state == ed->state && !state)
4107      return;
4108 #endif
4109 
4110    if (ep->param1.description)
4111      {
4112         if (ep->param1.description->rel1.id_x >= 0)
4113           rp1[Rel1X] = ed->table_parts[ep->param1.description->rel1.id_x];
4114         if (ep->param1.description->rel2.id_x >= 0)
4115           rp1[Rel2X] = ed->table_parts[ep->param1.description->rel2.id_x];
4116         if (ep->param1.description->rel1.id_y >= 0)
4117           rp1[Rel1Y] = ed->table_parts[ep->param1.description->rel1.id_y];
4118         if (ep->param1.description->rel2.id_y >= 0)
4119           rp1[Rel2Y] = ed->table_parts[ep->param1.description->rel2.id_y];
4120         if (ep->param1.description->clip_to_id >= 0)
4121           {
4122              clip1 = ed->table_parts[ep->param1.description->clip_to_id % ed->table_parts_size];
4123              ed->has_state_clip = EINA_TRUE;
4124           }
4125      }
4126    if (ep->param2)
4127      {
4128         if (ep->param2->description->rel1.id_x >= 0)
4129           rp2[Rel1X] = ed->table_parts[ep->param2->description->rel1.id_x];
4130         if (ep->param2->description->rel2.id_x >= 0)
4131           rp2[Rel2X] = ed->table_parts[ep->param2->description->rel2.id_x];
4132         if (ep->param2->description->rel1.id_y >= 0)
4133           rp2[Rel1Y] = ed->table_parts[ep->param2->description->rel1.id_y];
4134         if (ep->param2->description->rel2.id_y >= 0)
4135           rp2[Rel2Y] = ed->table_parts[ep->param2->description->rel2.id_y];
4136         if (ep->param2->description->clip_to_id >= 0)
4137           {
4138              clip2 = ed->table_parts[ep->param2->description->clip_to_id % ed->table_parts_size];
4139              ed->has_state_clip = EINA_TRUE;
4140           }
4141      }
4142 
4143    if (flags & FLAG_X)
4144      {
4145         ep->calculating |= flags & FLAG_X;
4146         if (rp1[Rel1X])
4147           {
4148              _edje_part_recalc(ed, rp1[Rel1X], FLAG_X, NULL);
4149 #ifdef EDJE_CALC_CACHE
4150              state1 = rp1[Rel1X]->state;
4151 #endif
4152           }
4153         if (rp1[Rel2X])
4154           {
4155              _edje_part_recalc(ed, rp1[Rel2X], FLAG_X, NULL);
4156 #ifdef EDJE_CALC_CACHE
4157              if (state1 < rp1[Rel2X]->state)
4158                state1 = rp1[Rel2X]->state;
4159 #endif
4160           }
4161         if (ep->param2)
4162           {
4163              if (rp2[Rel1X])
4164                {
4165                   _edje_part_recalc(ed, rp2[Rel1X], FLAG_X, NULL);
4166 #ifdef EDJE_CALC_CACHE
4167                   state2 = rp2[Rel1X]->state;
4168 #endif
4169                }
4170              if (rp2[Rel2X])
4171                {
4172                   _edje_part_recalc(ed, rp2[Rel2X], FLAG_X, NULL);
4173 #ifdef EDJE_CALC_CACHE
4174                   if (state2 < rp2[Rel2X]->state)
4175                     state2 = rp2[Rel2X]->state;
4176 #endif
4177                }
4178           }
4179      }
4180    if (flags & FLAG_Y)
4181      {
4182         ep->calculating |= flags & FLAG_Y;
4183         if (rp1[Rel1Y])
4184           {
4185              _edje_part_recalc(ed, rp1[Rel1Y], FLAG_Y, NULL);
4186 #ifdef EDJE_CALC_CACHE
4187              if (state1 < rp1[Rel1Y]->state)
4188                state1 = rp1[Rel1Y]->state;
4189 #endif
4190           }
4191         if (rp1[Rel2Y])
4192           {
4193              _edje_part_recalc(ed, rp1[Rel2Y], FLAG_Y, NULL);
4194 #ifdef EDJE_CALC_CACHE
4195              if (state1 < rp1[Rel2Y]->state)
4196                state1 = rp1[Rel2Y]->state;
4197 #endif
4198           }
4199         if (ep->param2)
4200           {
4201              if (rp2[Rel1Y])
4202                {
4203                   _edje_part_recalc(ed, rp2[Rel1Y], FLAG_Y, NULL);
4204 #ifdef EDJE_CALC_CACHE
4205                   if (state2 < rp2[Rel1Y]->state)
4206                     state2 = rp2[Rel1Y]->state;
4207 #endif
4208                }
4209              if (rp2[Rel2Y])
4210                {
4211                   _edje_part_recalc(ed, rp2[Rel2Y], FLAG_Y, NULL);
4212 #ifdef EDJE_CALC_CACHE
4213                   if (state2 < rp2[Rel2Y]->state)
4214                     state2 = rp2[Rel2Y]->state;
4215 #endif
4216                }
4217           }
4218      }
4219    if (clip1)
4220      {
4221         _edje_part_recalc(ed, clip1, flags, NULL);
4222         statecl = clip1->state;
4223      }
4224    if (clip2)
4225      {
4226         _edje_part_recalc(ed, clip2, flags, NULL);
4227         if (statecl < clip2->state)
4228           statecl = clip2->state;
4229      }
4230    if (ep->drag)
4231      {
4232         if (ep->drag->confine_to)
4233           {
4234              confine_to = ep->drag->confine_to;
4235              _edje_part_recalc(ed, confine_to, flags, NULL);
4236 #ifdef EDJE_CALC_CACHE
4237              statec = confine_to->state;
4238 #endif
4239           }
4240         if (ep->drag->threshold)
4241           {
4242              threshold = ep->drag->threshold;
4243              // We shall not recalculate the threshold position as
4244              // we use it's previous position to assert the threshold
4245              // the one before moving take action.
4246 #ifdef EDJE_CALC_CACHE
4247              statet = threshold->state;
4248 #endif
4249           }
4250      }
4251    //   if (ep->text.source)       _edje_part_recalc(ed, ep->text.source, flags);
4252    //   if (ep->text.text_source)  _edje_part_recalc(ed, ep->text.text_source, flags);
4253 
4254    /* actually calculate now */
4255    chosen_desc = ep->chosen_description;
4256    if (!chosen_desc)
4257      {
4258         ep->calculating = FLAG_NONE;
4259         ep->calculated |= flags;
4260         return;
4261      }
4262 
4263    pos = ep->description_pos;
4264 
4265    if ((ep->part->type == EDJE_PART_TYPE_PROXY) && chosen_desc->visible)
4266      {
4267         int part_id = -1;
4268 
4269         if (ep->param2 && (pos >= FROM_DOUBLE(0.5)))
4270           part_id = ((Edje_Part_Description_Proxy *)ep->param2->description)->proxy.id;
4271         else
4272           part_id = ((Edje_Part_Description_Proxy *)chosen_desc)->proxy.id;
4273 
4274 #ifdef EDJE_CALC_CACHE
4275         Edje_Real_Part *pp;
4276         pp = _edje_real_part_state_get(ed, ep, flags, part_id, NULL);
4277         if (pp && pp->invalidate) proxy_invalidate = EINA_TRUE;
4278 #else
4279         _edje_real_part_state_get(ed, ep, flags, part_id, NULL);
4280 #endif
4281      }
4282 
4283    /* Recalc if needed the map center && light source */
4284    if (ep->param1.description && ep->param1.description->map.on)
4285      {
4286         center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.rot.id_center, &statec1);
4287         zoom_center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.zoom.id_center, &statec1);
4288         light[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_light, &statel1);
4289 
4290         if (chosen_desc->map.persp_on)
4291           {
4292              persp[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_persp, &statep1);
4293           }
4294      }
4295 
4296    if (ep->param2 && ep->param2->description->map.on)
4297      {
4298         center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.rot.id_center, &statec2);
4299         zoom_center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.zoom.id_center, &statec2);
4300         light[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_light, &statel2);
4301 
4302         if (chosen_desc->map.persp_on)
4303           {
4304              persp[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_persp, &statep2);
4305           }
4306      }
4307 
4308 #ifndef EDJE_CALC_CACHE
4309    p1 = &lp1;
4310 #else
4311    p1 = &ep->param1.p;
4312 #endif
4313 
4314    if (ep->param1.description)
4315      {
4316 #ifdef EDJE_CALC_CACHE
4317         if (ed->all_part_change ||
4318             ep->invalidate ||
4319             (state1 >= ep->param1.state) ||
4320             (statec >= ep->param1.state) ||
4321             (statet >= ep->param1.state) ||
4322             (statec1 >= ep->param1.state) ||
4323             (statel1 >= ep->param1.state) ||
4324             (statep1 >= ep->param1.state) ||
4325             (statecl >= ep->param1.state) ||
4326             proxy_invalidate ||
4327             state ||
4328             ed->need_map_update ||
4329             ((ep->part->type == EDJE_PART_TYPE_TEXT ||
4330               ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
4331              ed->text_part_change))
4332 #endif
4333         {
4334            _edje_part_recalc_single(ed, ep, ep->param1.description,
4335                                     chosen_desc, center[0], zoom_center[0], light[0],
4336                                     persp[0], rp1[Rel1X], rp1[Rel1Y],
4337                                     rp1[Rel2X], rp1[Rel2Y], clip1, confine_to,
4338                                     threshold, p1, mmw, mmh,
4339                                     pos);
4340 
4341 #ifdef EDJE_CALC_CACHE
4342            if (flags == FLAG_XY) ep->param1.state = ed->state;
4343 #endif
4344         }
4345      }
4346    if (ep->param2)
4347      {
4348         int beginning_pos, part_type;
4349         Edje_Calc_Params *p2, *p3;
4350 
4351         if (ep->current)
4352           {
4353              _edje_calc_params_clear(p1);
4354              _edje_part_calc_params_memcpy(p1, ep->current, ep->part->type);
4355           }
4356 
4357         p3 = &lp3;
4358 #ifndef EDJE_CALC_CACHE
4359         p2 = &lp2;
4360 #else
4361         p2 = &ep->param2->p;
4362 
4363         if (ed->all_part_change ||
4364             ep->invalidate ||
4365             (state2 >= ep->param2->state) ||
4366             (statec >= ep->param2->state) ||
4367             (statet >= ep->param2->state) ||
4368             (statec2 >= ep->param2->state) ||
4369             (statel2 >= ep->param2->state) ||
4370             (statep2 >= ep->param2->state) ||
4371             (statecl >= ep->param2->state) ||
4372             proxy_invalidate ||
4373             state ||
4374             ed->need_map_update ||
4375             ((ep->part->type == EDJE_PART_TYPE_TEXT ||
4376               ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) &&
4377              ed->text_part_change))
4378 #endif
4379         {
4380            _edje_part_recalc_single(ed, ep, ep->param2->description,
4381                                     chosen_desc, center[1], zoom_center[1], light[1],
4382                                     persp[1], rp2[Rel1X], rp2[Rel1Y],
4383                                     rp2[Rel2X], rp2[Rel2Y], clip2, confine_to,
4384                                     threshold, p2, mmw, mmh,
4385                                     pos);
4386 
4387 #ifdef EDJE_CALC_CACHE
4388            if (flags == FLAG_XY) ep->param2->state = ed->state;
4389 #endif
4390         }
4391 
4392         pos2 = pos;
4393         if (pos2 < ZERO) pos2 = ZERO;
4394         else if (pos2 > FROM_INT(1))
4395           pos2 = FROM_INT(1);
4396         beginning_pos = (pos < FROM_DOUBLE(0.5));
4397         part_type = ep->part->type;
4398 
4399         /* visible is special */
4400         if ((p1->visible) && (!p2->visible))
4401           p3->visible = NEQ(pos, FROM_INT(1));
4402         else if ((!p1->visible) && (p2->visible))
4403           p3->visible = NEQ(pos, ZERO);
4404         else
4405           p3->visible = p1->visible;
4406 
4407         /* clip_to will behave a bit like visible */
4408         if (EQ(pos, ZERO))
4409           {
4410              if ((p1->ext) && (p1->ext->clip_to))
4411                {
4412                   _edje_calc_params_need_ext(p3);
4413                   p3->ext->clip_to = p1->ext->clip_to;
4414                }
4415           }
4416         else if (EQ(pos, FROM_INT(1)))
4417           {
4418              if ((p2->ext) && (p2->ext->clip_to))
4419                {
4420                   _edje_calc_params_need_ext(p3);
4421                   p3->ext->clip_to = p2->ext->clip_to;
4422                }
4423           }
4424         else if ((!p1->ext) || (!p1->ext->clip_to))
4425           {
4426              if ((p2->ext) && (p2->ext->clip_to))
4427                {
4428                   _edje_calc_params_need_ext(p3);
4429                   p3->ext->clip_to = p2->ext->clip_to;
4430                }
4431              else
4432                {
4433                   if (p3->ext) p3->ext->clip_to = NULL;
4434                }
4435           }
4436         else
4437           {
4438              if ((p1->ext) && (p1->ext->clip_to))
4439                {
4440                   _edje_calc_params_need_ext(p3);
4441                   p3->ext->clip_to = p1->ext->clip_to;
4442                }
4443           }
4444 
4445         /* and no_render as well */
4446         if ((p1->no_render) && (!p2->no_render))
4447           {
4448              p3->no_render = EQ(pos, FROM_INT(1));
4449              p3->no_render_apply = 1;
4450           }
4451         else if ((!p1->no_render) && (p2->no_render))
4452           {
4453              p3->no_render = EQ(pos, ZERO);
4454              p3->no_render_apply = 1;
4455           }
4456         else if (p1->no_render != ep->part->no_render)
4457           {
4458              p3->no_render = p1->no_render;
4459              p3->no_render_apply = 1;
4460           }
4461         else p3->no_render = ep->part->no_render;
4462 
4463         p3->smooth = (beginning_pos) ? p1->smooth : p2->smooth;
4464 
4465         /* FIXME: do x and y separately base on flag */
4466         p3->final.x = INTP(p1->final.x, p2->final.x, pos);
4467         p3->final.y = INTP(p1->final.y, p2->final.y, pos);
4468         p3->final.w = INTP(p1->final.w, p2->final.w, pos);
4469         p3->final.h = INTP(p1->final.h, p2->final.h, pos);
4470 
4471         p3->eval.x = FFP(p1->eval.x, p2->eval.x, pos);
4472         p3->eval.y = FFP(p1->eval.y, p2->eval.y, pos);
4473         p3->eval.w = FFP(p1->eval.w, p2->eval.w, pos);
4474         p3->eval.h = FFP(p1->eval.h, p2->eval.h, pos);
4475 
4476         p3->req.x = INTP(p1->req.x, p2->req.x, pos);
4477         p3->req.y = INTP(p1->req.y, p2->req.y, pos);
4478         p3->req.w = INTP(p1->req.w, p2->req.w, pos);
4479         p3->req.h = INTP(p1->req.h, p2->req.h, pos);
4480 
4481         _edje_part_pixel_adjust(ed, ep, p3);
4482 
4483         if (ep->part->dragable.x)
4484           {
4485              _edje_calc_params_need_ext(p3);
4486              p3->ext->req_drag.x = INTP(p1->ext->req_drag.x, p2->ext->req_drag.x, pos);
4487              p3->ext->req_drag.w = INTP(p1->ext->req_drag.w, p2->ext->req_drag.w, pos);
4488           }
4489         if (ep->part->dragable.y)
4490           {
4491              _edje_calc_params_need_ext(p3);
4492              p3->ext->req_drag.y = INTP(p1->ext->req_drag.y, p2->ext->req_drag.y, pos);
4493              p3->ext->req_drag.h = INTP(p1->ext->req_drag.h, p2->ext->req_drag.h, pos);
4494           }
4495 
4496         p3->color.r = INTP(p1->color.r, p2->color.r, pos2);
4497         p3->color.g = INTP(p1->color.g, p2->color.g, pos2);
4498         p3->color.b = INTP(p1->color.b, p2->color.b, pos2);
4499         p3->color.a = INTP(p1->color.a, p2->color.a, pos2);
4500 
4501 #ifdef HAVE_EPHYSICS
4502         if (ep->part->physics_body || ep->body)
4503           {
4504              _edje_calc_params_need_ext(p1);
4505              _edje_calc_params_need_ext(p2);
4506              EINA_COW_CALC_PHYSICS_BEGIN(p3, p3_write)
4507              {
4508                 p3_write->mass = FFP(p1->ext->physics->mass,
4509                                      p2->ext->physics->mass,
4510                                      pos);
4511                 p3_write->restitution = FFP(p1->ext->physics->restitution,
4512                                             p2->ext->physics->restitution,
4513                                             pos);
4514                 p3_write->friction = FFP(p1->ext->physics->friction,
4515                                          p2->ext->physics->friction,
4516                                          pos);
4517                 p3_write->density = FFP(p1->ext->physics->density,
4518                                         p2->ext->physics->density,
4519                                         pos);
4520                 p3_write->hardness = FFP(p1->ext->physics->hardness,
4521                                          p2->ext->physics->hardness,
4522                                          pos);
4523 
4524                 p3_write->damping.linear = FFP(p1->ext->physics->damping.linear,
4525                                                p2->ext->physics->damping.linear,
4526                                                pos);
4527                 p3_write->damping.angular = FFP(p1->ext->physics->damping.angular,
4528                                                 p2->ext->physics->damping.angular,
4529                                                 pos);
4530 
4531                 p3_write->sleep.linear = FFP(p1->ext->physics->sleep.linear,
4532                                              p2->ext->physics->sleep.linear,
4533                                              pos);
4534                 p3_write->sleep.angular = FFP(p1->ext->physics->sleep.angular,
4535                                               p2->ext->physics->sleep.angular,
4536                                               pos);
4537 
4538                 p3_write->z = INTP(p1->ext->physics->z, p2->ext->physics->z, pos);
4539                 p3_write->depth = INTP(p1->ext->physics->depth, p2->ext->physics->depth, pos);
4540 
4541                 if ((p1->ext->physics->ignore_part_pos) && (p2->ext->physics->ignore_part_pos))
4542                   p3_write->ignore_part_pos = 1;
4543                 else
4544                   p3_write->ignore_part_pos = 0;
4545 
4546                 if ((p1->ext->physics->material) && (p2->ext->physics->material))
4547                   p3_write->material = p1->ext->physics->material;
4548                 else
4549                   p3_write->material = EPHYSICS_BODY_MATERIAL_CUSTOM;
4550 
4551                 p3_write->light_on = p1->ext->physics->light_on || p2->ext->physics->light_on;
4552                 p3_write->backcull = p1->ext->physics->backcull || p2->ext->physics->backcull;
4553 
4554                 p3_write->mov_freedom.lin.x = p1->ext->physics->mov_freedom.lin.x ||
4555                   p2->ext->physics->mov_freedom.lin.x;
4556                 p3_write->mov_freedom.lin.y = p1->ext->physics->mov_freedom.lin.y ||
4557                   p2->ext->physics->mov_freedom.lin.y;
4558                 p3_write->mov_freedom.lin.z = p1->ext->physics->mov_freedom.lin.z ||
4559                   p2->ext->physics->mov_freedom.lin.z;
4560                 p3_write->mov_freedom.ang.x = p1->ext->physics->mov_freedom.ang.x ||
4561                   p2->ext->physics->mov_freedom.ang.x;
4562                 p3_write->mov_freedom.ang.y = p1->ext->physics->mov_freedom.ang.y ||
4563                   p2->ext->physics->mov_freedom.ang.y;
4564                 p3_write->mov_freedom.ang.z = p1->ext->physics->mov_freedom.ang.z ||
4565                   p2->ext->physics->mov_freedom.ang.z;
4566              }
4567              EINA_COW_CALC_PHYSICS_END(p3, p3_write);
4568           }
4569 #endif
4570 
4571         switch (part_type)
4572           {
4573            case EDJE_PART_TYPE_IMAGE:
4574              _edje_calc_params_need_type_common(p3);
4575              p3->type.common->spec.image.l = INTP(p1->type.common->spec.image.l, p2->type.common->spec.image.l, pos);
4576              p3->type.common->spec.image.r = INTP(p1->type.common->spec.image.r, p2->type.common->spec.image.r, pos);
4577              p3->type.common->spec.image.t = INTP(p1->type.common->spec.image.t, p2->type.common->spec.image.t, pos);
4578              p3->type.common->spec.image.b = INTP(p1->type.common->spec.image.b, p2->type.common->spec.image.b, pos);
4579              p3->type.common->spec.image.border_scale_by = FFP(p1->type.common->spec.image.border_scale_by, p2->type.common->spec.image.border_scale_by, pos);
4580              EINA_FALLTHROUGH;
4581 
4582              /* No break as proxy and image share code and object. */
4583            case EDJE_PART_TYPE_PROXY:
4584              _edje_calc_params_need_type_common(p3);
4585              p3->type.common->fill.x = INTP(p1->type.common->fill.x, p2->type.common->fill.x, pos);
4586              p3->type.common->fill.y = INTP(p1->type.common->fill.y, p2->type.common->fill.y, pos);
4587              p3->type.common->fill.w = INTP(p1->type.common->fill.w, p2->type.common->fill.w, pos);
4588              p3->type.common->fill.h = INTP(p1->type.common->fill.h, p2->type.common->fill.h, pos);
4589              break;
4590 
4591            case EDJE_PART_TYPE_TEXT:
4592              _edje_calc_params_need_type_text(p3);
4593              p3->type.text->size = INTP(p1->type.text->size, p2->type.text->size, pos);
4594              EINA_FALLTHROUGH;
4595 
4596              /* no break as we share code with the TEXTBLOCK type here. */
4597            case EDJE_PART_TYPE_TEXTBLOCK:
4598              _edje_calc_params_need_type_text(p3);
4599              p3->type.text->color2.r = INTP(p1->type.text->color2.r, p2->type.text->color2.r, pos2);
4600              p3->type.text->color2.g = INTP(p1->type.text->color2.g, p2->type.text->color2.g, pos2);
4601              p3->type.text->color2.b = INTP(p1->type.text->color2.b, p2->type.text->color2.b, pos2);
4602              p3->type.text->color2.a = INTP(p1->type.text->color2.a, p2->type.text->color2.a, pos2);
4603 
4604              p3->type.text->color3.r = INTP(p1->type.text->color3.r, p2->type.text->color3.r, pos2);
4605              p3->type.text->color3.g = INTP(p1->type.text->color3.g, p2->type.text->color3.g, pos2);
4606              p3->type.text->color3.b = INTP(p1->type.text->color3.b, p2->type.text->color3.b, pos2);
4607              p3->type.text->color3.a = INTP(p1->type.text->color3.a, p2->type.text->color3.a, pos2);
4608 
4609              p3->type.text->align.x = FFP(p1->type.text->align.x, p2->type.text->align.x, pos);
4610              p3->type.text->align.y = FFP(p1->type.text->align.y, p2->type.text->align.y, pos);
4611              p3->type.text->ellipsis = TO_DOUBLE(FINTP(p1->type.text->ellipsis, p2->type.text->ellipsis, pos2));
4612              break;
4613           }
4614 
4615         /* mapped is a special case like visible */
4616         if ((p1->mapped) && (!p2->mapped))
4617           p3->mapped = NEQ(pos, FROM_INT(1));
4618         else if ((!p1->mapped) && (p2->mapped))
4619           p3->mapped = NEQ(pos, ZERO);
4620         else
4621           p3->mapped = p1->mapped;
4622 
4623         p3->persp_on = p3->mapped ? p1->persp_on | p2->persp_on : 0;
4624         p3->lighted = p3->mapped ? p1->lighted | p2->lighted : 0;
4625         if (p3->mapped)
4626           {
4627              _edje_calc_params_need_ext(p1);
4628              _edje_calc_params_need_ext(p2);
4629              _edje_calc_params_need_ext(p3);
4630              EINA_COW_CALC_MAP_BEGIN(p3, p3_write)
4631              {
4632                 p3_write->center.x = INTP(p1->ext->map->center.x, p2->ext->map->center.x, pos);
4633                 p3_write->center.y = INTP(p1->ext->map->center.y, p2->ext->map->center.y, pos);
4634                 p3_write->center.z = INTP(p1->ext->map->center.z, p2->ext->map->center.z, pos);
4635                 p3_write->zoom_center.x = INTP(p1->ext->map->zoom_center.x, p2->ext->map->zoom_center.x, pos);
4636                 p3_write->zoom_center.y = INTP(p1->ext->map->zoom_center.y, p2->ext->map->zoom_center.y, pos);
4637                 p3_write->rotation.x = FFP(p1->ext->map->rotation.x, p2->ext->map->rotation.x, pos);
4638                 p3_write->rotation.y = FFP(p1->ext->map->rotation.y, p2->ext->map->rotation.y, pos);
4639                 p3_write->rotation.z = FFP(p1->ext->map->rotation.z, p2->ext->map->rotation.z, pos);
4640                 p3_write->zoom.x = FFP(p1->ext->map->zoom.x, p2->ext->map->zoom.x, pos);
4641                 p3_write->zoom.y = FFP(p1->ext->map->zoom.y, p2->ext->map->zoom.y, pos);
4642 
4643 #define MIX(P1, P2, P3, pos, info) \
4644   P3->info = P1->ext->map->info + TO_INT(SCALE(pos, P2->ext->map->info - P1->ext->map->info));
4645                 map_colors_free = _map_colors_interp(p1, p2, p3_write, pos);
4646 
4647                 if (p1->lighted && p2->lighted)
4648                   {
4649                      MIX(p1, p2, p3_write, pos, light.x);
4650                      MIX(p1, p2, p3_write, pos, light.y);
4651                      MIX(p1, p2, p3_write, pos, light.z);
4652                      MIX(p1, p2, p3_write, pos, light.r);
4653                      MIX(p1, p2, p3_write, pos, light.g);
4654                      MIX(p1, p2, p3_write, pos, light.b);
4655                      MIX(p1, p2, p3_write, pos, light.ar);
4656                      MIX(p1, p2, p3_write, pos, light.ag);
4657                      MIX(p1, p2, p3_write, pos, light.ab);
4658                   }
4659                 else if (p1->lighted)
4660                   {
4661                      memcpy(&p3_write->light, &p1->ext->map->light, sizeof (p1->ext->map->light));
4662                   }
4663                 else if (p2->lighted)
4664                   {
4665                      memcpy(&p3_write->light, &p2->ext->map->light, sizeof (p2->ext->map->light));
4666                   }
4667 
4668                 if (p1->persp_on && p2->persp_on)
4669                   {
4670                      MIX(p1, p2, p3_write, pos, persp.x);
4671                      MIX(p1, p2, p3_write, pos, persp.y);
4672                      MIX(p1, p2, p3_write, pos, persp.z);
4673                      MIX(p1, p2, p3_write, pos, persp.focal);
4674                   }
4675                 else if (p1->persp_on)
4676                   {
4677                      memcpy(&p3_write->persp, &p1->ext->map->persp, sizeof (p1->ext->map->persp));
4678                   }
4679                 else if (p2->persp_on)
4680                   {
4681                      memcpy(&p3_write->persp, &p2->ext->map->persp, sizeof (p2->ext->map->persp));
4682                   }
4683              }
4684              EINA_COW_CALC_MAP_END(p3, p3_write);
4685           }
4686 
4687 #ifndef EDJE_CALC_CACHE
4688         _edje_calc_params_clear(&lp2);
4689 #endif
4690         pf = p3;
4691      }
4692    else
4693      {
4694         pf = p1;
4695      }
4696 
4697    if (!pf->persp_on && chosen_desc->map.persp_on)
4698      {
4699         if (ed->persp)
4700           {
4701              EINA_COW_CALC_MAP_BEGIN(pf, pf_write)
4702              {
4703                 pf_write->persp.x = ed->persp->px;
4704                 pf_write->persp.y = ed->persp->py;
4705                 pf_write->persp.z = ed->persp->z0;
4706                 pf_write->persp.focal = ed->persp->foc;
4707              }
4708              EINA_COW_CALC_MAP_END(pf, pf_write);
4709           }
4710         else
4711           {
4712              const Edje_Perspective *ps;
4713 
4714              // fixme: a tad inefficient as this is a has lookup
4715              ps = edje_object_perspective_get(ed->obj);
4716              if (!ps)
4717                ps = edje_evas_global_perspective_get(evas_object_evas_get(ed->obj));
4718              EINA_COW_CALC_MAP_BEGIN(pf, pf_write)
4719              {
4720                 if (ps)
4721                   {
4722                      pf_write->persp.x = ps->px;
4723                      pf_write->persp.y = ps->py;
4724                      pf_write->persp.z = ps->z0;
4725                      pf_write->persp.focal = ps->foc;
4726                   }
4727                 else
4728                   {
4729                      pf_write->persp.x = ed->x + (ed->w / 2);
4730                      pf_write->persp.y = ed->y + (ed->h / 2);
4731                      pf_write->persp.z = 0;
4732                      pf_write->persp.focal = 1000;
4733                   }
4734              }
4735              EINA_COW_CALC_MAP_END(pf, pf_write);
4736           }
4737      }
4738 
4739    if (state)
4740      {
4741         _edje_calc_params_clear(state);
4742         _edje_part_calc_params_memcpy(state, pf, ep->part->type);
4743      }
4744 
4745    ep->req = pf->req;
4746 
4747    if (ep->drag && ep->drag->need_reset)
4748      {
4749         FLOAT_T dx, dy;
4750 
4751         dx = ZERO;
4752         dy = ZERO;
4753         _edje_part_dragable_calc(ed, ep, &dx, &dy);
4754         ep->drag->x = dx;
4755         ep->drag->val.x = dx;
4756         ep->drag->y = dy;
4757         ep->drag->val.y = dy;
4758         ep->drag->tmp.x = 0;
4759         ep->drag->tmp.y = 0;
4760         ep->drag->need_reset = 0;
4761      }
4762    if (!ed->calc_only)
4763      {
4764         Evas_Object *mo = NULL;
4765 
4766         /* Common move, resize and color_set for all part. */
4767         switch (ep->part->type)
4768           {
4769            case EDJE_PART_TYPE_IMAGE:
4770                {
4771                   Edje_Part_Description_Image *img_desc = (Edje_Part_Description_Image *)chosen_desc;
4772 
4773                   evas_object_image_scale_hint_set(ep->object,
4774                                                    img_desc->image.scale_hint);
4775                }
4776              /* No break here as we share the rest of the code for all types. Intended fall-through*/
4777              EINA_FALLTHROUGH;
4778 
4779            case EDJE_PART_TYPE_PROXY:
4780              EINA_FALLTHROUGH;
4781            case EDJE_PART_TYPE_RECTANGLE:
4782              EINA_FALLTHROUGH;
4783            case EDJE_PART_TYPE_TEXTBLOCK:
4784              EINA_FALLTHROUGH;
4785            case EDJE_PART_TYPE_BOX:
4786              EINA_FALLTHROUGH;
4787            case EDJE_PART_TYPE_TABLE:
4788              EINA_FALLTHROUGH;
4789            case EDJE_PART_TYPE_SNAPSHOT:
4790              EINA_FALLTHROUGH;
4791            case EDJE_PART_TYPE_VECTOR:
4792              evas_object_color_set(ep->object,
4793                                    (pf->color.r * pf->color.a) / 255,
4794                                    (pf->color.g * pf->color.a) / 255,
4795                                    (pf->color.b * pf->color.a) / 255,
4796                                    pf->color.a);
4797 
4798 #ifdef HAVE_EPHYSICS
4799 /* body attributes should be updated for invisible objects */
4800              if (!ep->part->physics_body)
4801                {
4802                   if (!pf->visible)
4803                     {
4804                        evas_object_hide(ep->object);
4805                        break;
4806                     }
4807                   evas_object_show(ep->object);
4808                   if (pf->no_render_apply)
4809                     efl_canvas_object_no_render_set(ep->object, pf->no_render);
4810                }
4811              else if (!pf->visible)
4812                {
4813                   Evas_Object *face_obj;
4814                   Eina_List *l;
4815 
4816                   EINA_LIST_FOREACH(ep->body_faces, l, face_obj)
4817                     evas_object_hide(face_obj);
4818                   evas_object_hide(ep->object);
4819                }
4820 #else
4821              if (!pf->visible)
4822                {
4823                   evas_object_hide(ep->object);
4824                   break;
4825                }
4826              evas_object_show(ep->object);
4827              if (pf->no_render_apply)
4828                efl_canvas_object_no_render_set(ep->object, pf->no_render);
4829 #endif
4830              EINA_FALLTHROUGH;
4831 
4832            /* move and resize are needed for all previous object => no break here. */
4833            case EDJE_PART_TYPE_SWALLOW:
4834            case EDJE_PART_TYPE_GROUP:
4835            case EDJE_PART_TYPE_EXTERNAL:
4836              /* visibility and color have no meaning on SWALLOW and GROUP part. */
4837 #ifdef HAVE_EPHYSICS
4838              efl_gfx_entity_size_set(ep->object, EINA_SIZE2D(pf->final.w,  pf->final.h));
4839              if ((ep->part->physics_body) && (!ep->body))
4840                {
4841                   if (_edje_physics_world_geometry_check(ed->world))
4842                     {
4843                        _edje_physics_body_add(ed, ep, ed->world);
4844                        _edje_physics_body_props_update(ed, ep, pf, EINA_TRUE);
4845                     }
4846                }
4847              else if (ep->body)
4848                {
4849                   if (((ep->prev_description) &&
4850                        (chosen_desc != ep->prev_description)) ||
4851                       (pf != p1))
4852                     {
4853                        _edje_calc_params_need_ext(pf);
4854                        _edje_physics_body_props_update(ed, ep, pf, !pf->ext->physics->ignore_part_pos);
4855                     }
4856                }
4857              else
4858                efl_gfx_entity_position_set(ep->object, EINA_POSITION2D(ed->x + pf->final.x, ed->y + pf->final.y));
4859 #else
4860              efl_gfx_entity_position_set(ep->object, EINA_POSITION2D(ed->x + pf->final.x, ed->y + pf->final.y));
4861              efl_gfx_entity_size_set(ep->object, EINA_SIZE2D(pf->final.w,  pf->final.h));
4862 #endif
4863 
4864              if (ep->nested_smart) /* Move, Resize all nested parts */
4865                {   /* Not really needed but will improve the bounding box evaluation done by Evas */
4866                   efl_gfx_entity_position_set(ep->nested_smart, EINA_POSITION2D(ed->x + pf->final.x, ed->y + pf->final.y));
4867                   efl_gfx_entity_size_set(ep->nested_smart, EINA_SIZE2D(pf->final.w,  pf->final.h));
4868                }
4869              if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
4870                _edje_entry_real_part_configure(ed, ep);
4871 
4872              /* handle clip overrides */
4873              if (ed->has_state_clip)
4874                _edje_calc_handle_state_clip(ed, ep, pf);
4875              break;
4876 
4877            case EDJE_PART_TYPE_TEXT:
4878              /* This is correctly handle in _edje_text_recalc_apply at the moment. */
4879              break;
4880 
4881            case EDJE_PART_TYPE_GRADIENT:
4882              /* FIXME: definitivly remove this code when we switch to new format. */
4883              abort();
4884              break;
4885 
4886            case EDJE_PART_TYPE_SPACER:
4887              /* We really should do nothing on SPACER part */
4888              break;
4889           }
4890 
4891         /* Some object need special recalc. */
4892         switch (ep->part->type)
4893           {
4894            case EDJE_PART_TYPE_TEXT:
4895              _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc, EINA_FALSE);
4896              break;
4897 
4898            case EDJE_PART_TYPE_PROXY:
4899              _edje_proxy_recalc_apply(ed, ep, pf, (Edje_Part_Description_Proxy *)chosen_desc, pos);
4900              break;
4901 
4902            case EDJE_PART_TYPE_IMAGE:
4903              _edje_image_recalc_apply(ed, ep, pf, (Edje_Part_Description_Image *)chosen_desc, pos);
4904              break;
4905 
4906            case EDJE_PART_TYPE_BOX:
4907              _edje_box_recalc_apply(ed, ep, pf, (Edje_Part_Description_Box *)chosen_desc);
4908              break;
4909 
4910            case EDJE_PART_TYPE_TABLE:
4911              _edje_table_recalc_apply(ed, ep, pf, (Edje_Part_Description_Table *)chosen_desc);
4912              break;
4913 
4914            case EDJE_PART_TYPE_VECTOR:
4915              _edje_vector_recalc_apply(ed, ep, pf, (Edje_Part_Description_Vector *)chosen_desc, pos);
4916              break;
4917 
4918            case EDJE_PART_TYPE_TEXTBLOCK:
4919            case EDJE_PART_TYPE_EXTERNAL:
4920            case EDJE_PART_TYPE_RECTANGLE:
4921            case EDJE_PART_TYPE_SWALLOW:
4922            case EDJE_PART_TYPE_GROUP:
4923              /* Nothing special to do for this type of object. */
4924              break;
4925 
4926            case EDJE_PART_TYPE_GRADIENT:
4927              /* FIXME: definitivly remove this code when we switch to new format. */
4928              abort();
4929              break;
4930 
4931            case EDJE_PART_TYPE_SPACER:
4932              /* We really should do nothing on SPACER part */
4933              break;
4934           }
4935 
4936         if (((ep->type == EDJE_RP_TYPE_SWALLOW) &&
4937              (ep->typedata.swallow)) &&
4938             (ep->typedata.swallow->swallowed_object))
4939           {
4940              if (ed->has_state_clip)
4941                _edje_calc_handle_state_clip(ed, ep, pf);
4942              if (pf->visible)
4943                {
4944                   Eina_Bool vis = EINA_TRUE;
4945 
4946                   if (ep->part->type == EDJE_PART_TYPE_GROUP)
4947                     vis = evas_object_visible_get(ed->obj);
4948                   if (ep->typedata.swallow)
4949                     efl_gfx_entity_position_set(ep->typedata.swallow->swallowed_object, EINA_POSITION2D(ed->x + pf->final.x, ed->y + pf->final.y));
4950                   if (ep->typedata.swallow)
4951                     efl_gfx_entity_size_set(ep->typedata.swallow->swallowed_object, EINA_SIZE2D(pf->final.w,  pf->final.h));
4952                   if (ep->typedata.swallow)
4953                     efl_gfx_entity_visible_set(ep->typedata.swallow->swallowed_object, vis);
4954                }
4955              else if (ep->typedata.swallow)
4956                evas_object_hide(ep->typedata.swallow->swallowed_object);
4957              if (ep->typedata.swallow)
4958                mo = ep->typedata.swallow->swallowed_object;
4959           }
4960         else mo = ep->object;
4961         if (ep->part->type != EDJE_PART_TYPE_SPACER)
4962           {
4963              Evas_Object *map_obj;
4964              Evas_Object *cursor_objs[EDJE_ENTRY_NUM_CURSOR_OBJS];
4965              int c = 0, num_cursors = 0;
4966 
4967              /* Apply map to smart obj holding nested parts */
4968              if (ep->nested_smart) map_obj = ep->nested_smart;
4969              else map_obj = mo;
4970              if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
4971                num_cursors = _edje_entry_real_part_cursor_objs_get(ep, cursor_objs);
4972 
4973              if (chosen_desc->map.on)
4974                {
4975                   static Evas_Map *map = NULL;
4976 
4977                   ed->have_mapped_part = EINA_TRUE;
4978                   // create map and populate with part geometry
4979                   if (!map) map = evas_map_new(4);
4980 
4981                   _edje_map_prop_set(map, pf, chosen_desc, ep, mo, NULL);
4982 
4983                   if (map_obj)
4984                     {
4985                        evas_object_map_set(map_obj, map);
4986                        evas_object_map_enable_set(map_obj, EINA_TRUE);
4987                        if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
4988                          {
4989                             for (c = 0; c < num_cursors; c++)
4990                               {
4991                                  _edje_map_prop_set(map, pf, chosen_desc, ep, mo, cursor_objs[c]);
4992                                  evas_object_map_set(cursor_objs[c], map);
4993                                  evas_object_map_enable_set(cursor_objs[c], EINA_TRUE);
4994                               }
4995                          }
4996                     }
4997                }
4998              else
4999                {
5000                   //Disable map only if map were enabled.
5001                   if (map_obj && evas_object_map_enable_get(map_obj))
5002                     {
5003 #ifdef HAVE_EPHYSICS
5004                        if (!ep->nested_smart && !ep->body)
5005                          {
5006 #endif
5007                             evas_object_map_enable_set(mo, EINA_FALSE);
5008                             evas_object_map_set(mo, NULL);
5009                             if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
5010                               {
5011                                  for (c = 0; c < num_cursors; c++)
5012                                    {
5013                                       evas_object_map_enable_set(cursor_objs[c], EINA_FALSE);
5014                                       evas_object_map_set(cursor_objs[c], NULL);
5015                                    }
5016                               }
5017 #ifdef HAVE_EPHYSICS
5018                          }
5019 #endif
5020                     }
5021                }
5022           }
5023      }
5024 
5025    if (map_colors_free) _map_colors_free(pf);
5026 
5027    ep->prev_description = chosen_desc;
5028 #ifdef HAVE_EPHYSICS
5029    if (!ep->body)
5030      {
5031 #endif
5032         ep->x = pf->final.x;
5033         ep->y = pf->final.y;
5034         ep->w = pf->final.w;
5035         ep->h = pf->final.h;
5036 #ifdef HAVE_EPHYSICS
5037      }
5038 #endif
5039 
5040    ep->calculated |= flags;
5041    ep->calculating = FLAG_NONE;
5042 
5043    if (pf == &lp3)
5044      {
5045         _edje_calc_params_clear(&lp3);
5046      }
5047 
5048 #ifdef EDJE_CALC_CACHE
5049    if (ep->calculated == FLAG_XY)
5050      {
5051         ep->state = ed->state;
5052         ep->invalidate = EINA_FALSE;
5053      }
5054 #else
5055    _edje_calc_params_clear(&lp1);
5056 #endif
5057 
5058 }
5059