merge with master
[framework/uifw/edje.git] / src / lib / edje_calc.c
1 #include "edje_private.h"
2
3 static void _edje_part_make_rtl(Edje_Part_Description_Common *desc);
4 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);
5
6 static void _edje_part_recalc_single(Edje *ed, Edje_Real_Part *ep,
7                                      Edje_Part_Description_Common *desc, Edje_Part_Description_Common *chosen_desc,
8                                      Edje_Real_Part *center, Edje_Real_Part *light, Edje_Real_Part *persp,
9                                      Edje_Real_Part *rel1_to_x, Edje_Real_Part *rel1_to_y,
10                                      Edje_Real_Part *rel2_to_x, Edje_Real_Part *rel2_to_y,
11                                      Edje_Real_Part *confine_to, Edje_Calc_Params *params,
12                                      FLOAT_T pos);
13
14 void
15 _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, FLOAT_T pos, FLOAT_T v1, FLOAT_T v2)
16 {
17    FLOAT_T fp_pos;
18    FLOAT_T npos;
19
20    pos = CLAMP(pos, ZERO, FROM_INT(1));
21
22    fp_pos = pos;
23
24    npos = ZERO;
25 #if 0 // old code - easy to enable for comparing float vs fixed point
26    /* take linear pos along timescale and use interpolation method */
27    switch (mode)
28      {
29       case EDJE_TWEEN_MODE_SINUSOIDAL:
30          /* npos = (1.0 - cos(pos * PI)) / 2.0; */
31          npos = DIV2(SUB(FROM_INT(1),
32                          COS(MUL(fp_pos,
33                                  PI))));
34          break;
35       case EDJE_TWEEN_MODE_ACCELERATE:
36          /* npos = 1.0 - sin((PI / 2.0) + (pos * PI / 2.0)); */
37          npos = SUB(FROM_INT(1),
38                     SIN(ADD(DIV2(PI),
39                             MUL(fp_pos,
40                                 DIV2(PI)))));
41          break;
42       case EDJE_TWEEN_MODE_DECELERATE:
43          /* npos = sin(pos * PI / 2.0); */
44          npos = SIN(MUL(fp_pos,
45                         DIV2(PI)));
46         break;
47       case EDJE_TWEEN_MODE_LINEAR:
48          npos = fp_pos;
49          break;
50       default:
51          npos = fp_pos;
52          break;
53      }
54 #else
55    switch (mode & EDJE_TWEEN_MODE_MASK)
56      {
57       case EDJE_TWEEN_MODE_SINUSOIDAL:
58         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
59                                                   ECORE_POS_MAP_SINUSOIDAL,
60                                                   0.0, 0.0));
61         break;
62       case EDJE_TWEEN_MODE_ACCELERATE:
63         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
64                                                   ECORE_POS_MAP_ACCELERATE,
65                                                   0.0, 0.0));
66         break;
67       case EDJE_TWEEN_MODE_DECELERATE:
68         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
69                                                   ECORE_POS_MAP_DECELERATE,
70                                                   0.0, 0.0));
71         break;
72       case EDJE_TWEEN_MODE_LINEAR:
73         npos = fp_pos;
74 /*        npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
75                                                   ECORE_POS_MAP_LINEAR, 
76                                                   0.0, 0.0));
77  */
78         break;
79       case EDJE_TWEEN_MODE_ACCELERATE_FACTOR:
80         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
81                                                   ECORE_POS_MAP_ACCELERATE_FACTOR,
82                                                   TO_DOUBLE(v1), 0.0));
83         break;
84       case EDJE_TWEEN_MODE_DECELERATE_FACTOR:
85         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
86                                                   ECORE_POS_MAP_DECELERATE_FACTOR,
87                                                   TO_DOUBLE(v1), 0.0));
88         break;
89       case EDJE_TWEEN_MODE_SINUSOIDAL_FACTOR:
90         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
91                                                   ECORE_POS_MAP_SINUSOIDAL_FACTOR,
92                                                   TO_DOUBLE(v1), 0.0));
93         break;
94       case EDJE_TWEEN_MODE_DIVISOR_INTERP:
95         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
96                                                   ECORE_POS_MAP_DIVISOR_INTERP,
97                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
98         break;
99       case EDJE_TWEEN_MODE_BOUNCE:
100         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
101                                                   ECORE_POS_MAP_BOUNCE,
102                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
103         break;
104       case EDJE_TWEEN_MODE_SPRING:
105         npos = FROM_DOUBLE(ecore_animator_pos_map(TO_DOUBLE(pos),
106                                                   ECORE_POS_MAP_SPRING,
107                                                   TO_DOUBLE(v1), TO_DOUBLE(v2)));
108         break;
109       default:
110         npos = fp_pos;
111         break;
112      }
113 #endif
114    if (npos == ep->description_pos) return;
115
116    ep->description_pos = npos;
117
118    ed->dirty = EINA_TRUE;
119    ed->recalc_call = EINA_TRUE;
120 #ifdef EDJE_CALC_CACHE
121    ep->invalidate = 1;
122 #endif
123 }
124
125
126 /**
127  * Returns part description
128  *
129  * @internal
130  *
131  * Converts part description to RTL-desc.
132  *
133  * @param desc Pointer to desc buffer.
134  *
135  **/
136 static void
137 _edje_part_make_rtl(Edje_Part_Description_Common *desc)
138 {
139    double t;
140    int i;
141
142    if(!desc)
143      return;
144
145    /* This makes alignment right-oriented */
146    desc->align.x = 1.0 - desc->align.x;
147
148    /* same as above for relative components */
149    t = desc->rel1.relative_x;
150    desc->rel1.relative_x = 1.0 - desc->rel2.relative_x;
151    desc->rel2.relative_x = 1.0 - t;
152
153    /* +1 and +1 are because how edje works with right
154     * side borders - nothing is printed beyond that limit
155     *
156     * rel2 is now to the left of rel1, and Edje assumes
157     * the opposite so we switch corners on x-axis to define
158     * offset from right to left */
159    i = desc->rel1.offset_x;
160    desc->rel1.offset_x = -(desc->rel2.offset_x + 1);
161    desc->rel2.offset_x = -(i + 1);
162
163    i = desc->rel1.id_x;
164    desc->rel1.id_x = desc->rel2.id_x;
165    desc->rel2.id_x = i;
166 }
167
168 /**
169  * Returns part description
170  *
171  * @internal
172  *
173  * Returns part description according to object orientation.
174  * When object is in RTL-orientation (RTL flag is set)
175  * this returns the RTL-desc of it.
176  * RTL-desc would be allocated if was not created by a previous call.
177  * The dst pointer is updated in case of an allocation.
178  *
179  * @param ed Edje object.
180  * @param src The Left To Right (LTR), original desc.
181  * @param dst Pointer to Right To Left (RTL) desc-list.
182  * @param type name of dec type. Example: "default".
183  *
184  * @return Edje part description.
185  *
186  **/
187 static Edje_Part_Description_Common *
188 _edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type)
189 {
190    Edje_Part_Description_Common *desc_rtl = NULL;
191    Edje_Part_Collection_Directory_Entry *ce;
192    size_t memsize = 0;
193
194    /* RTL flag is not set, return original description */
195    if(!edje_object_mirrored_get(ed->obj))
196       return src;
197
198    if(*dst)
199      return *dst; /* Was allocated before and we should use it */
200
201 #define EDIT_ALLOC_POOL_RTL(Short, Type, Name)                          \
202          case EDJE_PART_TYPE_##Short:                                   \
203            {                                                            \
204               Edje_Part_Description_##Type *Name;                       \
205               Name = eina_mempool_malloc(ce->mp_rtl.Short,              \
206                     sizeof (Edje_Part_Description_##Type));             \
207               memset(Name, 0, sizeof(Edje_Part_Description_##Type));    \
208               desc_rtl = &Name->common;                                 \
209               memsize = sizeof(Edje_Part_Description_##Type);           \
210               break;                                                    \
211            }
212
213    ce = eina_hash_find(ed->file->collection, ed->group);
214
215    switch (type)
216      {
217       case EDJE_PART_TYPE_RECTANGLE:
218          desc_rtl = eina_mempool_malloc(ce->mp_rtl.RECTANGLE,
219                                         sizeof (Edje_Part_Description_Common));
220          ce->count.RECTANGLE++;
221          memsize = sizeof(Edje_Part_Description_Common);
222          break;
223       case EDJE_PART_TYPE_SWALLOW:
224          desc_rtl = eina_mempool_malloc(ce->mp_rtl.SWALLOW,
225                                         sizeof (Edje_Part_Description_Common));
226          ce->count.SWALLOW++;
227          memsize = sizeof(Edje_Part_Description_Common);
228          break;
229       case EDJE_PART_TYPE_GROUP:
230          desc_rtl = eina_mempool_malloc(ce->mp_rtl.GROUP,
231                                         sizeof (Edje_Part_Description_Common));
232          ce->count.GROUP++;
233          memsize = sizeof(Edje_Part_Description_Common);
234          break;
235      case EDJE_PART_TYPE_SPACER:
236          desc_rtl = eina_mempool_malloc(ce->mp_rtl.SPACER,
237                                         sizeof (Edje_Part_Description_Common));
238          ce->count.SPACER++;
239          memsize = sizeof(Edje_Part_Description_Common);
240          break;
241          EDIT_ALLOC_POOL_RTL(TEXT, Text, text);
242          EDIT_ALLOC_POOL_RTL(TEXTBLOCK, Text, text);
243          EDIT_ALLOC_POOL_RTL(IMAGE, Image, image);
244          EDIT_ALLOC_POOL_RTL(PROXY, Proxy, proxy);
245          EDIT_ALLOC_POOL_RTL(BOX, Box, box);
246          EDIT_ALLOC_POOL_RTL(TABLE, Table, table);
247          EDIT_ALLOC_POOL_RTL(EXTERNAL, External, external_params);
248      }
249
250    if (desc_rtl)
251       memcpy(desc_rtl, src, memsize);
252
253    _edje_part_make_rtl(desc_rtl);
254
255    *dst = desc_rtl;
256    return desc_rtl;
257 }
258
259 Edje_Part_Description_Common *
260 _edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name,
261                             double val)
262 {
263    Edje_Part *ep = rp->part;
264    Edje_Part_Description_Common *ret = NULL;
265    Edje_Part_Description_Common *d;
266
267    double min_dst = 99999.0;
268    unsigned int i;
269
270    /* RTL flag is set, return RTL description */
271    if(edje_object_mirrored_get(ed->obj))
272      if(!ep->other.desc_rtl)
273        ep->other.desc_rtl = (Edje_Part_Description_Common **)
274           calloc(ep->other.desc_count,
275                 sizeof (Edje_Part_Description_Common *));
276
277    if (!strcmp(name, "default") && val == 0.0)
278      return _edje_get_description_by_orientation(ed,
279            ep->default_desc, &ep->default_desc_rtl, ep->type);
280
281    if (!strcmp(name, "custom"))
282      return rp->custom ?
283         _edje_get_description_by_orientation(ed, rp->custom->description,
284               &rp->custom->description_rtl, ep->type) : NULL;
285
286    if (!strcmp(name, "default"))
287      {
288         ret = _edje_get_description_by_orientation(ed, ep->default_desc,
289                                                    &ep->default_desc_rtl,
290                                                    ep->type);
291
292         min_dst = ABS(ep->default_desc->state.value - val);
293      }
294
295    for (i = 0; i < ep->other.desc_count; ++i)
296      {
297         d = ep->other.desc[i];
298
299         if (d->state.name && (d->state.name == name ||
300                               !strcmp(d->state.name, name)))
301           {
302              double dst;
303
304              dst = ABS(d->state.value - val);
305              if (dst < min_dst)
306                {
307                   ret = _edje_get_description_by_orientation(ed, d,
308                                                              &ep->other.desc_rtl[i], ep->type);
309                   min_dst = dst;
310                }
311           }
312      }
313
314    return ret;
315 }
316
317 static int
318 _edje_image_find(Evas_Object *obj, Edje *ed, Edje_Real_Part_Set **eps, Edje_Part_Description_Image *st, Edje_Part_Image_Id *imid)
319 {
320   Edje_Image_Directory_Set_Entry *entry;
321   Edje_Image_Directory_Set *set = NULL;
322   Eina_List *l;
323   int w = 0;
324   int h = 0;
325   int id;
326
327   if (!st && !imid)
328     return -1;
329
330   if (st && !st->image.set)
331     return st->image.id;
332
333   if (imid && !imid->set)
334     return imid->id;
335
336   if (imid)
337     id = imid->id;
338   else
339     id = st->image.id;
340
341   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
342
343   if (eps && *eps)
344     {
345        if ((*eps)->id == id)
346          set = (*eps)->set;
347
348        if (set)
349          if ((*eps)->entry->size.min.w <= w && w <= (*eps)->entry->size.max.w)
350            if ((*eps)->entry->size.min.h <= h && h <= (*eps)->entry->size.max.h)
351              return (*eps)->entry->id;
352     }
353
354   if (!set)
355     set = ed->file->image_dir->sets + id;
356
357   EINA_LIST_FOREACH(set->entries, l, entry)
358     {
359        if (entry->size.min.w <= w && w <= entry->size.max.w)
360          if (entry->size.min.h <= h && h <= entry->size.max.h)
361            {
362               if (eps)
363                 {
364                    if (!*eps)
365                      *eps = calloc(1, sizeof (Edje_Real_Part_Set));
366
367                    if (*eps)
368                      {
369                         (*eps)->entry = entry;
370                         (*eps)->set = set;
371                         (*eps)->id = id;
372                      }
373                 }
374               return entry->id;
375            }
376     }
377
378   return -1;
379 }
380
381 static void
382 _edje_real_part_image_set(Edje *ed, Edje_Real_Part *ep, FLOAT_T pos)
383 {
384    int image_id;
385    int image_count, image_num;
386
387    image_id = _edje_image_find(ep->object, ed,
388                                &ep->param1.set,
389                                (Edje_Part_Description_Image*) ep->param1.description,
390                                NULL);
391    if (image_id < 0)
392      {
393         Edje_Image_Directory_Entry *ie;
394
395         if (!ed->file->image_dir) ie = NULL;
396         else ie = ed->file->image_dir->entries + (-image_id) - 1;
397         if ((ie) &&
398             (ie->source_type == EDJE_IMAGE_SOURCE_TYPE_EXTERNAL) &&
399             (ie->entry))
400           {
401              evas_object_image_file_set(ep->object, ie->entry, NULL);
402           }
403      }
404    else
405      {
406         image_count = 2;
407         if (ep->param2)
408           image_count += ((Edje_Part_Description_Image*) ep->param2->description)->image.tweens_count;
409         image_num = TO_INT(MUL(pos, SUB(FROM_INT(image_count),
410                                         FROM_DOUBLE(0.5))));
411         if (image_num > (image_count - 1))
412           image_num = image_count - 1;
413         if (image_num <= 0)
414           {
415              image_id = _edje_image_find(ep->object, ed,
416                                          &ep->param1.set,
417                                          (Edje_Part_Description_Image*) ep->param1.description,
418                                          NULL);
419           }
420         else
421           if (ep->param2)
422             {
423                if (image_num == (image_count - 1))
424                  {
425                     image_id = _edje_image_find(ep->object, ed,
426                                                 &ep->param2->set,
427                                                 (Edje_Part_Description_Image*) ep->param2->description,
428                                                 NULL);
429                  }
430                else
431                  {
432                     Edje_Part_Image_Id *imid;
433
434                     imid = ((Edje_Part_Description_Image*) ep->param2->description)->image.tweens[image_num - 1];
435                     image_id = _edje_image_find(ep->object, ed, NULL, NULL, imid);
436                  }
437             }
438         if (image_id < 0)
439           {
440              ERR("¨Part \"%s\" description, "
441                  "\"%s\" %3.3f with image %i index has a missing image id in a set of %i !!!",
442                  ep->part->name,
443                  ep->param1.description->state.name,
444                  ep->param1.description->state.value,
445                  image_num,
446                  image_count);
447           }
448         else
449           {
450              char buf[1024];
451
452              /* Replace snprint("edje/images/%i") == memcpy + itoa */
453 #define IMAGES "edje/images/"
454              memcpy(buf, IMAGES, strlen(IMAGES));
455              eina_convert_itoa(image_id, buf + strlen(IMAGES)); /* No need to check length as 2³² need only 10 characteres. */
456
457              evas_object_image_file_set(ep->object, ed->file->path, buf);
458              if (evas_object_image_load_error_get(ep->object) != EVAS_LOAD_ERROR_NONE)
459                {
460                   ERR("Error loading image collection \"%s\" from "
461                       "file \"%s\". Missing EET Evas loader module?",
462                       buf, ed->file->path);
463                   switch (evas_object_image_load_error_get(ep->object))
464                     {
465                      case EVAS_LOAD_ERROR_GENERIC:
466                         ERR("Error type: EVAS_LOAD_ERROR_GENERIC");
467                         break;
468                      case EVAS_LOAD_ERROR_DOES_NOT_EXIST:
469                         ERR("Error type: EVAS_LOAD_ERROR_DOES_NOT_EXIST");
470                         break;
471                      case EVAS_LOAD_ERROR_PERMISSION_DENIED:
472                         ERR("Error type: EVAS_LOAD_ERROR_PERMISSION_DENIED");
473                         break;
474                      case EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED:
475                         ERR("Error type: EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED");
476                         break;
477                      case EVAS_LOAD_ERROR_CORRUPT_FILE:
478                         ERR("Error type: EVAS_LOAD_ERROR_CORRUPT_FILE");
479                         break;
480                      case EVAS_LOAD_ERROR_UNKNOWN_FORMAT:
481                         ERR("Error type: EVAS_LOAD_ERROR_UNKNOWN_FORMAT");
482                         break;
483                      default:
484                         ERR("Error type: ???");
485                         break;
486                     }
487                }
488           }
489      }
490 }
491
492 static void
493 _edje_real_part_rel_to_apply(Edje *ed, Edje_Real_Part *ep, Edje_Real_Part_State *state)
494 {
495    state->rel1_to_x = state->rel1_to_y = NULL;
496    state->rel2_to_x = state->rel2_to_y = NULL;
497
498    if (state->description)
499      {
500         if (state->description->rel1.id_x >= 0)
501           state->rel1_to_x = ed->table_parts[state->description->rel1.id_x % ed->table_parts_size];
502         if (state->description->rel1.id_y >= 0)
503           state->rel1_to_y = ed->table_parts[state->description->rel1.id_y % ed->table_parts_size];
504         if (state->description->rel2.id_x >= 0)
505           state->rel2_to_x = ed->table_parts[state->description->rel2.id_x % ed->table_parts_size];
506         if (state->description->rel2.id_y >= 0)
507           state->rel2_to_y = ed->table_parts[state->description->rel2.id_y % ed->table_parts_size];
508
509         if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
510           {
511              Edje_Part_Description_External *external;
512
513              if ((ep->type != EDJE_RP_TYPE_SWALLOW) ||
514                  (!ep->typedata.swallow)) return;
515              
516              external = (Edje_Part_Description_External*)state->description;
517              
518              if (state->external_params)
519                _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object, state->external_params);
520              state->external_params = _edje_external_params_parse(ep->typedata.swallow->swallowed_object, external->external_params);
521           }
522      }
523 }
524
525 void
526 _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, double v1, const char *d2, double v2)
527 {
528    Edje_Part_Description_Common *epd1;
529    Edje_Part_Description_Common *epd2 = NULL;
530    Edje_Part_Description_Common *chosen_desc;
531
532    Edje_Part_Description_Image *epdi;
533
534    if (!d1) d1 = "default";
535
536    epd1 = _edje_part_description_find(ed, ep, d1, v1);
537    if (!epd1)
538      epd1 = ep->part->default_desc; /* never NULL */
539
540    if (d2)
541      epd2 = _edje_part_description_find(ed, ep, d2, v2);
542
543    epdi = (Edje_Part_Description_Image*) epd2;
544
545    /* There is an animation if both description are different or if description is an image with tweens */
546    if (epd2 && (epd1 != epd2 || (ep->part->type == EDJE_PART_TYPE_IMAGE && epdi->image.tweens_count)))
547      {
548         if (!ep->param2)
549           {
550              ep->param2 = eina_mempool_malloc(_edje_real_part_state_mp,
551                                               sizeof(Edje_Real_Part_State));
552              memset(ep->param2, 0, sizeof(Edje_Real_Part_State));
553           }
554         else if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
555           {
556              if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
557                  (ep->typedata.swallow))
558                _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object,
559                                                  ep->param2->external_params);
560           }
561         ep->param2->external_params = NULL;
562      }
563    else
564      if (ep->param2)
565        {
566           if (ep->part->type == EDJE_PART_TYPE_EXTERNAL)
567             {
568                if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
569                    (ep->typedata.swallow))
570                  _edje_external_parsed_params_free(ep->typedata.swallow->swallowed_object,
571                                                    ep->param2->external_params);
572             }
573           if (ep->param2)
574             free(ep->param2->set);
575           eina_mempool_free(_edje_real_part_state_mp, ep->param2);
576           ep->param2 = NULL;
577        }
578
579    chosen_desc = ep->chosen_description;
580    ep->param1.description = epd1;
581    ep->chosen_description = epd1;
582
583    _edje_real_part_rel_to_apply(ed, ep, &ep->param1);
584
585    if (ep->param2)
586      {
587         ep->param2->description = epd2;
588
589         _edje_real_part_rel_to_apply(ed, ep, ep->param2);
590
591         if (ep->description_pos > FROM_DOUBLE(0.0))
592           ep->chosen_description = epd2;
593      }
594
595    if (chosen_desc != ep->chosen_description &&
596        ep->part->type == EDJE_PART_TYPE_EXTERNAL)
597      _edje_external_recalc_apply(ed, ep, NULL, chosen_desc);
598
599    ed->recalc_hints = EINA_TRUE;
600    ed->dirty = EINA_TRUE;
601    ed->recalc_call = EINA_TRUE;
602 #ifdef EDJE_CALC_CACHE
603    ep->invalidate = 1;
604 #endif
605 }
606
607 void
608 _edje_recalc(Edje *ed)
609 {
610    if ((ed->freeze > 0) || (_edje_freeze_val > 0))
611      {
612         ed->recalc = EINA_TRUE;
613         if (!ed->calc_only)
614           {
615              if (_edje_freeze_val > 0)
616                {
617                   if (!ed->freeze_calc)
618                     {
619                        _edje_freeze_calc_count++;
620                        _edje_freeze_calc_list = eina_list_append(_edje_freeze_calc_list, ed);
621                        ed->freeze_calc = EINA_TRUE;
622                     }
623                }
624              return;
625           }
626      }
627 // XXX: dont need this with current smart calc infra. remove me later
628 //   if (ed->postponed) return;
629 //   if (!ed->calc_only)
630      evas_object_smart_changed(ed->obj);
631 // XXX: dont need this with current smart calc infra. remove me later
632 //   ed->postponed = EINA_TRUE;
633 }
634
635 void
636 _edje_recalc_do(Edje *ed)
637 {
638    unsigned int i;
639    Eina_Bool need_calc;
640
641 // XXX: dont need this with current smart calc infra. remove me later
642 //   ed->postponed = EINA_FALSE;
643    need_calc = evas_object_smart_need_recalculate_get(ed->obj);
644    evas_object_smart_need_recalculate_set(ed->obj, 0);
645    if (!ed->dirty) return;
646    ed->have_mapped_part = EINA_FALSE;
647    ed->dirty = EINA_FALSE;
648    ed->state++;
649    for (i = 0; i < ed->table_parts_size; i++)
650      {
651         Edje_Real_Part *ep;
652
653         ep = ed->table_parts[i];
654         ep->calculated = FLAG_NONE;
655         ep->calculating = FLAG_NONE;
656      }
657    for (i = 0; i < ed->table_parts_size; i++)
658      {
659         Edje_Real_Part *ep;
660
661         ep = ed->table_parts[i];
662         if (ep->calculated != FLAG_XY)
663           _edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY, NULL);
664      }
665    if (!ed->calc_only) ed->recalc = EINA_FALSE;
666 #ifdef EDJE_CALC_CACHE
667    ed->all_part_change = EINA_FALSE;
668    ed->text_part_change = EINA_FALSE;
669 #endif
670    if (!ed->calc_only)
671      {
672         if (ed->recalc_call)
673           evas_object_smart_callback_call(ed->obj, "recalc", NULL);
674      }
675    else
676      evas_object_smart_need_recalculate_set(ed->obj, need_calc);
677    ed->recalc_call = EINA_FALSE;
678
679    if (ed->update_hints && ed->recalc_hints && !ed->calc_only)
680      {
681         Evas_Coord w, h;
682
683         ed->recalc_hints = EINA_FALSE;
684
685         edje_object_size_min_calc(ed->obj, &w, &h);
686         evas_object_size_hint_min_set(ed->obj, w, h);
687      }
688
689    if (!ed->collection) return ;
690
691    for (i = 0; i < ed->collection->limits.parts_count; i++)
692      {
693         const char *name;
694         unsigned char limit;
695         int part;
696
697         part = ed->collection->limits.parts[i].part;
698         name = ed->collection->parts[part]->name;
699         limit = ed->table_parts[part]->chosen_description->limit;
700         switch (limit)
701           {
702            case 0:
703               ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_UNKNOWN;
704               ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_UNKNOWN;
705               break;
706            case 1:
707               ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_UNKNOWN;
708               break;
709            case 2:
710               ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_UNKNOWN;
711               break;
712            case 3:
713               break;
714           }
715
716         if ((limit & 1) == 1)
717           {
718              if (ed->table_parts[part]->w > 0 &&
719                  (ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_OVER))
720                {
721                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_OVER;
722                   _edje_emit(ed, "limit,width,over", name);
723                }
724              else if (ed->table_parts[part]->w < 0 &&
725                       ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_BELOW)
726                {
727                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_BELOW;
728                   _edje_emit(ed, "limit,width,below", name);
729                }
730              else if (ed->table_parts[part]->w == 0 &&
731                       ed->collection->limits.parts[i].width != EDJE_PART_LIMIT_ZERO)
732                {
733                   ed->collection->limits.parts[i].width = EDJE_PART_LIMIT_ZERO;
734                   _edje_emit(ed, "limit,width,zero", name);
735                }
736           }
737         if ((limit & 2) == 2)
738           {
739              if (ed->table_parts[part]->h > 0 &&
740                  (ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_OVER))
741                {
742                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_OVER;
743                   _edje_emit(ed, "limit,height,over", name);
744                }
745              else if (ed->table_parts[part]->h < 0 &&
746                       ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_BELOW)
747                {
748                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_BELOW;
749                   _edje_emit(ed, "limit,height,below", name);
750                }
751              else if (ed->table_parts[part]->h == 0 &&
752                       ed->collection->limits.parts[i].height != EDJE_PART_LIMIT_ZERO)
753                {
754                   ed->collection->limits.parts[i].height = EDJE_PART_LIMIT_ZERO;
755                   _edje_emit(ed, "limit,height,zero", name);
756                }
757           }
758      }
759 }
760
761 void
762 _edje_part_recalc_1(Edje *ed, Edje_Real_Part *ep)
763 {
764   _edje_part_recalc(ed, ep, FLAG_XY, NULL);
765 }
766
767 int
768 _edje_part_dragable_calc(Edje *ed __UNUSED__, Edje_Real_Part *ep, FLOAT_T *x, FLOAT_T *y)
769 {
770    if (ep->drag)
771      {
772         if (ep->drag->confine_to)
773           {
774              FLOAT_T dx, dy, dw, dh;
775              int ret = 0;
776
777              if ((ep->part->dragable.x != 0) &&
778                  (ep->part->dragable.y != 0 )) ret = 3;
779              else if (ep->part->dragable.x != 0) ret = 1;
780              else if (ep->part->dragable.y != 0) ret = 2;
781
782              dx = FROM_INT(ep->x - ep->drag->confine_to->x);
783              dw = FROM_INT(ep->drag->confine_to->w - ep->w);
784              if (dw != ZERO) dx = DIV(dx, dw);
785              else dx = ZERO;
786
787              dy = FROM_INT(ep->y - ep->drag->confine_to->y);
788              dh = FROM_INT(ep->drag->confine_to->h - ep->h);
789              if (dh != ZERO) dy = DIV(dy, dh);
790              else dy = ZERO;
791
792              if (x) *x = dx;
793              if (y) *y = dy;
794
795              return ret;
796           }
797         else
798           {
799              if (x) *x = ADD(FROM_INT(ep->drag->tmp.x), ep->drag->x);
800              if (y) *y = ADD(FROM_INT(ep->drag->tmp.y), ep->drag->y);
801              return 0;
802           }
803      }
804    if (x) *x = ZERO;
805    if (y) *y = ZERO;
806    return 0;
807 }
808
809 void
810 _edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, FLOAT_T x, FLOAT_T y)
811 {
812    /* check whether this part is dragable at all */
813    if (!ep->drag) return ;
814
815    /* instead of checking for equality, we really should check that
816     * the difference is greater than foo, but I have no idea what
817     * value we would set foo to, because it would depend on the
818     * size of the dragable...
819     */
820    if (ep->drag->x != x || ep->drag->tmp.x)
821      {
822         ep->drag->x = x;
823         ep->drag->tmp.x = 0;
824         ep->drag->need_reset = 0;
825         ed->dirty = EINA_TRUE;
826         ed->recalc_call = EINA_TRUE;
827      }
828
829    if (ep->drag->y != y || ep->drag->tmp.y)
830      {
831         ep->drag->y = y;
832         ep->drag->tmp.y = 0;
833         ep->drag->need_reset = 0;
834         ed->dirty = EINA_TRUE;
835         ed->recalc_call = EINA_TRUE;
836      }
837
838 #ifdef EDJE_CALC_CACHE
839    ep->invalidate = 1;
840 #endif
841    _edje_recalc(ed); /* won't do anything if dirty flag isn't set */
842 }
843
844 static void
845 _edje_part_recalc_single_rel(Edje *ed,
846                              Edje_Real_Part *ep __UNUSED__,
847                              Edje_Part_Description_Common *desc,
848                              Edje_Real_Part *rel1_to_x,
849                              Edje_Real_Part *rel1_to_y,
850                              Edje_Real_Part *rel2_to_x,
851                              Edje_Real_Part *rel2_to_y,
852                              Edje_Calc_Params *params)
853 {
854    FLOAT_T x, w;
855    FLOAT_T y, h;
856
857    if (rel1_to_x)
858      x = ADD(FROM_INT(desc->rel1.offset_x + rel1_to_x->x),
859              SCALE(desc->rel1.relative_x, rel1_to_x->w));
860    else
861      x = ADD(FROM_INT(desc->rel1.offset_x),
862              SCALE(desc->rel1.relative_x, ed->w));
863    params->x = TO_INT(x);
864
865    if (rel2_to_x)
866      w = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_x + rel2_to_x->x),
867                      SCALE(desc->rel2.relative_x, rel2_to_x->w)),
868                  x),
869              FROM_INT(1));
870    else
871      w = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_x),
872                      SCALE(desc->rel2.relative_x, ed->w)),
873                  x),
874              FROM_INT(1));
875    params->w = TO_INT(w);
876
877    if (rel1_to_y)
878      y = ADD(FROM_INT(desc->rel1.offset_y + rel1_to_y->y),
879              SCALE(desc->rel1.relative_y, rel1_to_y->h));
880    else
881      y = ADD(FROM_INT(desc->rel1.offset_y),
882              SCALE(desc->rel1.relative_y, ed->h));
883    params->y = TO_INT(y);
884
885    if (rel2_to_y)
886      h = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_y + rel2_to_y->y),
887                      SCALE(desc->rel2.relative_y, rel2_to_y->h)),
888                  y),
889              FROM_INT(1));
890    else
891      h = ADD(SUB(ADD(FROM_INT(desc->rel2.offset_y),
892                      SCALE(desc->rel2.relative_y, ed->h)),
893                  y),
894              FROM_INT(1));
895    params->h = TO_INT(h);
896 }
897
898 static Edje_Internal_Aspect
899 _edje_part_recalc_single_aspect(Edje *ed,
900                                 Edje_Real_Part *ep,
901                                 Edje_Part_Description_Common *desc,
902                                 Edje_Calc_Params *params,
903                                 int *minw, int *minh,
904                                 int *maxw, int *maxh,
905                                 FLOAT_T pos)
906 {
907    Edje_Internal_Aspect apref = EDJE_ASPECT_PREFER_NONE;
908    FLOAT_T aspect, amax, amin;
909    FLOAT_T new_w = ZERO, new_h = ZERO, want_x, want_y, want_w, want_h;
910
911    if (params->h <= ZERO) aspect = FROM_INT(999999);
912    else aspect = DIV(FROM_INT(params->w), FROM_INT(params->h));
913    amax = desc->aspect.max;
914    amin = desc->aspect.min;
915    if (desc->aspect.prefer == EDJE_ASPECT_PREFER_SOURCE &&
916        ep->part->type == EDJE_PART_TYPE_IMAGE)
917      {
918         Evas_Coord w, h;
919
920         /* We only need pose to find the right image that would be displayed,
921            and the right aspect ratio in that case */
922         _edje_real_part_image_set(ed, ep, pos);
923         evas_object_image_size_get(ep->object, &w, &h);
924         amin = amax = DIV(FROM_INT(w), FROM_INT(h));
925      }
926    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
927        (ep->typedata.swallow))
928      {
929         if ((ep->typedata.swallow->swallow_params.aspect.w > 0) &&
930             (ep->typedata.swallow->swallow_params.aspect.h > 0))
931           amin = amax =
932           DIV(FROM_INT(ep->typedata.swallow->swallow_params.aspect.w),
933               FROM_INT(ep->typedata.swallow->swallow_params.aspect.h));
934      }
935    want_x = FROM_INT(params->x);
936    want_w = new_w = FROM_INT(params->w);
937
938    want_y = FROM_INT(params->y);
939    want_h = new_h = FROM_INT(params->h);
940
941    if ((amin > ZERO) && (amax > ZERO))
942      {
943         apref = desc->aspect.prefer;
944         if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
945             (ep->typedata.swallow))
946           {
947              if (ep->typedata.swallow->swallow_params.aspect.mode > EDJE_ASPECT_CONTROL_NONE)
948                {
949                   switch (ep->typedata.swallow->swallow_params.aspect.mode)
950                     {
951                      case EDJE_ASPECT_CONTROL_NEITHER:
952                        apref = EDJE_ASPECT_PREFER_NONE;
953                        break;
954                      case EDJE_ASPECT_CONTROL_HORIZONTAL:
955                        apref = EDJE_ASPECT_PREFER_HORIZONTAL;
956                        break;
957                      case EDJE_ASPECT_CONTROL_VERTICAL:
958                        apref = EDJE_ASPECT_PREFER_VERTICAL;
959                        break;
960                      case EDJE_ASPECT_CONTROL_BOTH:
961                        apref = EDJE_ASPECT_PREFER_BOTH;
962                        break;
963                      default:
964                        break;
965                     }
966                }
967           }
968         switch (apref)
969           {
970            case EDJE_ASPECT_PREFER_NONE:
971               /* keep both dimensions in check */
972               /* adjust for min aspect (width / height) */
973               if ((amin > ZERO) && (aspect < amin))
974                 {
975                    new_h = DIV(FROM_INT(params->w), amin);
976                    new_w = SCALE(amin, params->h);
977                 }
978               /* adjust for max aspect (width / height) */
979               if ((amax > ZERO) && (aspect > amax))
980                 {
981                    new_h = DIV(FROM_INT(params->w), amax);
982                    new_w = SCALE(amax, params->h);
983                 }
984               if ((amax > ZERO) && (new_w < FROM_INT(params->w)))
985                 {
986                    new_w = FROM_INT(params->w);
987                    new_h = DIV(FROM_INT(params->w), amax);
988                 }
989               if ((amax > ZERO) && (new_h < FROM_INT(params->h)))
990                 {
991                    new_w = SCALE(amax, params->h);
992                    new_h = FROM_INT(params->h);
993                 }
994               break;
995               /* prefer vertical size as determiner */
996            case  EDJE_ASPECT_PREFER_VERTICAL:
997               /* keep both dimensions in check */
998               /* adjust for max aspect (width / height) */
999               if ((amax > ZERO) && (aspect > amax))
1000                 new_w = SCALE(amax, params->h);
1001               /* adjust for min aspect (width / height) */
1002               if ((amin > ZERO) && (aspect < amin))
1003                 new_w = SCALE(amin, params->h);
1004               break;
1005               /* prefer horizontal size as determiner */
1006            case EDJE_ASPECT_PREFER_HORIZONTAL:
1007               /* keep both dimensions in check */
1008               /* adjust for max aspect (width / height) */
1009               if ((amax > ZERO) && (aspect > amax))
1010                 new_h = DIV(FROM_INT(params->w), amax);
1011               /* adjust for min aspect (width / height) */
1012               if ((amin > ZERO) && (aspect < amin))
1013                 new_h = DIV(FROM_INT(params->w), amin);
1014               break;
1015            case EDJE_ASPECT_PREFER_SOURCE:
1016            case EDJE_ASPECT_PREFER_BOTH:
1017               /* keep both dimensions in check */
1018               /* adjust for max aspect (width / height) */
1019               if ((amax > ZERO) && (aspect > amax))
1020                 {
1021                    new_w = SCALE(amax, params->h);
1022                    new_h = DIV(FROM_INT(params->w), amax);
1023                 }
1024               /* adjust for min aspect (width / height) */
1025               if ((amin > ZERO) && (aspect < amin))
1026                 {
1027                    new_w = SCALE(amin, params->h);
1028                    new_h = DIV(FROM_INT(params->w), amin);
1029                 }
1030               break;
1031            default:
1032               break;
1033           }
1034
1035         if (!((amin > ZERO) && (amax > ZERO) &&
1036               (apref == EDJE_ASPECT_PREFER_NONE)))
1037           {
1038              if ((*maxw >= 0) && (new_w > FROM_INT(*maxw)))
1039                new_w = FROM_INT(*maxw);
1040              if (new_w < FROM_INT(*minw))
1041                new_w = FROM_INT(*minw);
1042
1043              if ((FROM_INT(*maxh) >= 0) && (new_h > FROM_INT(*maxh)))
1044                new_h = FROM_INT(*maxh);
1045              if (new_h < FROM_INT(*minh))
1046                new_h = FROM_INT(*minh);
1047           }
1048
1049         /* do real adjustment */
1050         if (apref == EDJE_ASPECT_PREFER_BOTH)
1051           {
1052              if (amin == ZERO) amin = amax;
1053              if (amin != ZERO)
1054                {
1055                   /* fix h and vary w */
1056                   if (new_w > FROM_INT(params->w))
1057                     {
1058                        //                 params->w = new_w;
1059                        // EXCEEDS BOUNDS in W
1060                        new_h = DIV(FROM_INT(params->w), amin);
1061                        new_w = FROM_INT(params->w);
1062                        if (new_h > FROM_INT(params->h))
1063                          {
1064                             new_h = FROM_INT(params->h);
1065                             new_w = SCALE(amin, params->h);
1066                          }
1067                     }
1068                   /* fix w and vary h */
1069                   else
1070                     {
1071                        //                 params->h = new_h;
1072                        // EXCEEDS BOUNDS in H
1073                        new_h = FROM_INT(params->h);
1074                        new_w = SCALE(amin, params->h);
1075                        if (new_w > FROM_INT(params->w))
1076                          {
1077                             new_h = DIV(FROM_INT(params->w), amin);
1078                             new_w = FROM_INT(params->w);
1079                          }
1080                     }
1081                   params->w = TO_INT(new_w);
1082                   params->h = TO_INT(new_h);
1083                }
1084           }
1085      }
1086    if (apref != EDJE_ASPECT_PREFER_BOTH)
1087      {
1088         if ((amin > 0.0) && (amax > ZERO) && (apref == EDJE_ASPECT_PREFER_NONE))
1089           {
1090              params->w = TO_INT(new_w);
1091              params->h = TO_INT(new_h);
1092           }
1093         else if ((FROM_INT(params->h) - new_h) > (FROM_INT(params->w) - new_w))
1094           {
1095              if (params->h < TO_INT(new_h))
1096                params->h = TO_INT(new_h);
1097              else if (params->h > TO_INT(new_h))
1098                params->h = TO_INT(new_h);
1099              if (apref == EDJE_ASPECT_PREFER_VERTICAL)
1100                params->w = TO_INT(new_w);
1101           }
1102         else
1103           {
1104              if (params->w < TO_INT(new_w))
1105                params->w = TO_INT(new_w);
1106              else if (params->w > TO_INT(new_w))
1107                params->w = TO_INT(new_w);
1108              if (apref == EDJE_ASPECT_PREFER_HORIZONTAL)
1109                params->h = TO_INT(new_h);
1110           }
1111      }
1112    params->x = TO_INT(ADD(want_x,
1113                           MUL(SUB(want_w, FROM_INT(params->w)),
1114                               desc->align.x)));
1115    params->y = TO_INT(ADD(want_y,
1116                           MUL(SUB(want_h, FROM_INT(params->h)),
1117                               desc->align.y)));
1118    return apref;
1119 }
1120
1121 static void
1122 _edje_part_recalc_single_step(Edje_Part_Description_Common *desc,
1123                               Edje_Calc_Params *params)
1124 {
1125    if (desc->step.x > 0)
1126      {
1127         int steps;
1128         int new_w;
1129
1130         steps = params->w / desc->step.x;
1131         new_w = desc->step.x * steps;
1132         if (params->w > new_w)
1133           {
1134              params->x += TO_INT(SCALE(desc->align.x, (params->w - new_w)));
1135              params->w = new_w;
1136           }
1137      }
1138
1139    if (desc->step.y > 0)
1140      {
1141         int steps;
1142         int new_h;
1143
1144         steps = params->h / desc->step.y;
1145         new_h = desc->step.y * steps;
1146         if (params->h > new_h)
1147           {
1148              params->y += TO_INT(SCALE(desc->align.y, (params->h - new_h)));
1149              params->h = new_h;
1150           }
1151      }
1152 }
1153
1154 static double
1155 _edje_part_recalc_single_textblock_scale_range_adjust(Edje_Part_Description_Text *chosen_desc, double base_scale, double scale)
1156 {
1157    double size, min, max;
1158
1159    if (chosen_desc->text.size == 0)
1160       return scale;
1161
1162    min = base_scale * chosen_desc->text.size_range_min;
1163    max = chosen_desc->text.size_range_max * base_scale;
1164    size = chosen_desc->text.size * scale;
1165
1166    if ((size > max) && (max > 0))
1167       scale = max / (double) chosen_desc->text.size;
1168    else if (size < min)
1169       scale = min / (double) chosen_desc->text.size;
1170
1171    return scale;
1172 }
1173
1174 static void
1175 _edje_part_recalc_single_textblock(FLOAT_T sc,
1176                                    Edje *ed,
1177                                    Edje_Real_Part *ep,
1178                                    Edje_Part_Description_Text *chosen_desc,
1179                                    Edje_Calc_Params *params,
1180                                    int *minw, int *minh,
1181                                    int *maxw, int *maxh)
1182 {
1183    if ((ep->type != EDJE_RP_TYPE_TEXT) ||
1184        (!ep->typedata.text))
1185      return;
1186    if (chosen_desc)
1187      {
1188         Evas_Coord tw, th, ins_l, ins_r, ins_t, ins_b;
1189         const char *text = "";
1190         const char *style = "";
1191         Edje_Style *stl  = NULL;
1192         const char *tmp;
1193         Eina_List *l;
1194
1195         if (chosen_desc->text.id_source >= 0)
1196           {
1197              ep->typedata.text->source = ed->table_parts[chosen_desc->text.id_source % ed->table_parts_size];
1198
1199              tmp = edje_string_get(&((Edje_Part_Description_Text *)ep->typedata.text->source->chosen_description)->text.style);
1200              if (tmp) style = tmp;
1201           }
1202         else
1203           {
1204              ep->typedata.text->source = NULL;
1205
1206              tmp = edje_string_get(&chosen_desc->text.style);
1207              if (tmp) style = tmp;
1208           }
1209
1210         if (chosen_desc->text.id_text_source >= 0)
1211           {
1212              ep->typedata.text->text_source = ed->table_parts[chosen_desc->text.id_text_source % ed->table_parts_size];
1213              text = edje_string_get(&((Edje_Part_Description_Text*)ep->typedata.text->text_source->chosen_description)->text.text);
1214
1215              if (ep->typedata.text->text_source->typedata.text->text) text = ep->typedata.text->text_source->typedata.text->text;
1216           }
1217         else
1218           {
1219              ep->typedata.text->text_source = NULL;
1220              text = edje_string_get(&chosen_desc->text.text);
1221              if (ep->typedata.text->text) text = ep->typedata.text->text;
1222           }
1223
1224         EINA_LIST_FOREACH(ed->file->styles, l, stl)
1225           {
1226              if ((stl->name) && (!strcmp(stl->name, style))) break;
1227              stl = NULL;
1228           }
1229
1230         if (ep->part->scale)
1231           evas_object_scale_set(ep->object, TO_DOUBLE(sc));
1232
1233         if ((chosen_desc->text.fit_x) || (chosen_desc->text.fit_y))
1234           {
1235              double base_s = 1.0;
1236              double orig_s;
1237              double s = base_s;
1238
1239              if (ep->part->scale) s = TO_DOUBLE(sc);
1240              if (ep->part->scale) base_s = TO_DOUBLE(sc);
1241              evas_object_scale_set(ep->object, base_s);
1242              evas_object_textblock_size_native_get(ep->object, &tw, &th);
1243
1244              orig_s = base_s;
1245              /* Now make it bigger so calculations will be more accurate
1246               * and less influenced by hinting... */
1247                {
1248                   orig_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s, orig_s * params->w / (double) tw);
1249                   evas_object_scale_set(ep->object, orig_s);
1250                   evas_object_textblock_size_native_get(ep->object, &tw, &th);
1251                }
1252              if (chosen_desc->text.fit_x)
1253                {
1254                   if (tw > 0)
1255                     {
1256                        s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s, orig_s * params->w / tw);
1257                        evas_object_scale_set(ep->object, s);
1258                        evas_object_textblock_size_native_get(ep->object, NULL, NULL);
1259                     }
1260                }
1261              if (chosen_desc->text.fit_y)
1262                {
1263                   if (th > 0)
1264                     {
1265                        double tmp_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s, orig_s * params->h / (double) th);
1266                        /* If we already have X fit, restrict Y to be no bigger
1267                         * than what we got with X. */
1268                        if (!((chosen_desc->text.fit_x) && (tmp_s > s)))
1269                          {
1270                             s = tmp_s;
1271                          }
1272
1273                        evas_object_scale_set(ep->object, s);
1274                        evas_object_textblock_size_native_get(ep->object, NULL, NULL);
1275                     }
1276                }
1277
1278              /* Final tuning, try going down 90% at a time, hoping it'll
1279               * actually end up being correct. */
1280                {
1281                   int i = 5; /* Tries before we give up. */
1282                   Evas_Coord fw, fh;
1283                   evas_object_textblock_size_native_get(ep->object, &fw, &fh);
1284
1285                   /* If we are still too big, try reducing the size to
1286                    * 95% each try. */
1287                   while ((i > 0) &&
1288                         ((chosen_desc->text.fit_x && (fw > params->w)) ||
1289                          (chosen_desc->text.fit_y && (fh > params->h))))
1290                     {
1291                        double tmp_s = _edje_part_recalc_single_textblock_scale_range_adjust(chosen_desc, base_s, s * 0.95);
1292
1293                        /* Break if we are not making any progress. */
1294                        if (tmp_s == s)
1295                           break;
1296                        s = tmp_s;
1297
1298                        evas_object_scale_set(ep->object, s);
1299                        evas_object_textblock_size_native_get(ep->object, &fw, &fh);
1300                        i--;
1301                     }
1302                }
1303
1304           }
1305
1306         if (stl)
1307           {
1308              const char *ptxt;
1309
1310              if (evas_object_textblock_style_get(ep->object) != stl->style)
1311                evas_object_textblock_style_set(ep->object, stl->style);
1312              // FIXME: need to account for editing
1313              if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1314                {
1315                   // do nothing - should be done elsewhere
1316                }
1317              else
1318                {
1319                   ptxt = evas_object_textblock_text_markup_get(ep->object);
1320                   if (((!ptxt) && (text)) ||
1321                       ((ptxt) && (text) && (strcmp(ptxt, text))) ||
1322                       ((ptxt) && (!text)))
1323                     evas_object_textblock_text_markup_set(ep->object, text);
1324                }
1325              if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y))
1326                {
1327                   int mw = 0, mh = 0;
1328
1329                   tw = th = 0;
1330                   if (!chosen_desc->text.min_x)
1331                     {
1332                        evas_object_resize(ep->object, params->w, params->h);
1333                        evas_object_textblock_size_formatted_get(ep->object, &tw,
1334                                                                 &th);
1335                     }
1336                   else
1337                     evas_object_textblock_size_native_get(ep->object, &tw, &th);
1338                   evas_object_textblock_style_insets_get(ep->object, &ins_l,
1339                                                          &ins_r, &ins_t, &ins_b);
1340                   mw = ins_l + tw + ins_r;
1341                   mh = ins_t + th + ins_b;
1342                   if (minw && chosen_desc->text.min_x)
1343                     {
1344                        if (mw > *minw) *minw = mw;
1345                     }
1346                   if (minh && chosen_desc->text.min_y)
1347                     {
1348                        if (mh > *minh) *minh = mh;
1349                     }
1350                }
1351           }
1352
1353         if ((chosen_desc->text.max_x) || (chosen_desc->text.max_y))
1354           {
1355              int mw = 0, mh = 0;
1356
1357              tw = th = 0;
1358              if (!chosen_desc->text.max_x)
1359                {
1360                   evas_object_resize(ep->object, params->w, params->h);
1361                   evas_object_textblock_size_formatted_get(ep->object, &tw, &th);
1362                }
1363              else
1364                evas_object_textblock_size_native_get(ep->object, &tw, &th);
1365              evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r,
1366                                                     &ins_t, &ins_b);
1367              mw = ins_l + tw + ins_r;
1368              mh = ins_t + th + ins_b;
1369              if (maxw && chosen_desc->text.max_x)
1370                {
1371                   if (mw > *maxw) *maxw = mw;
1372                   if (minw && (*maxw < *minw)) *maxw = *minw;
1373                }
1374              if (maxh && chosen_desc->text.max_y)
1375                {
1376                   if (mh > *maxh) *maxh = mh;
1377                   if (minh && (*maxh < *minh)) *maxh = *minh;
1378                }
1379           }
1380
1381         evas_object_textblock_valign_set(ep->object, TO_DOUBLE(chosen_desc->text.align.y));
1382      }
1383 }
1384
1385 static void
1386 _edje_textblock_recalc_apply(Edje *ed, Edje_Real_Part *ep,
1387                         Edje_Calc_Params *params,
1388                         Edje_Part_Description_Text *chosen_desc)
1389 {
1390    /* FIXME: this is just an hack. */
1391    FLOAT_T sc;
1392    sc = ed->scale;
1393    if (sc == ZERO) sc = _edje_scale;
1394    if (chosen_desc->text.fit_x || chosen_desc->text.fit_y)
1395      {
1396         _edje_part_recalc_single_textblock(sc, ed, ep, chosen_desc, params,
1397               NULL, NULL, NULL, NULL);
1398      }
1399 }
1400
1401 static void
1402 _edje_part_recalc_single_text(FLOAT_T sc __UNUSED__,
1403                               Edje *ed,
1404                               Edje_Real_Part *ep,
1405                               Edje_Part_Description_Text *desc,
1406                               Edje_Part_Description_Text *chosen_desc,
1407                               Edje_Calc_Params *params,
1408                               int *minw, int *minh,
1409                               int *maxw, int *maxh)
1410 #define RECALC_SINGLE_TEXT_USING_APPLY 1
1411 #if RECALC_SINGLE_TEXT_USING_APPLY
1412 /*
1413  * XXX TODO NOTE:
1414  *
1415  * Original _edje_part_recalc_single_text() was not working as
1416  * expected since it was not doing size fit, range, ellipsis and so
1417  * on.
1418  *
1419  * The purpose of this function compared with
1420  * _edje_text_recalc_apply() is to be faster, not calling Evas update
1421  * functions. However for text this is quite difficult given that to
1422  * fit we need to set the font, size, style, etc. If it was done
1423  * correctly, we'd save some calls to move and some color sets,
1424  * however those shouldn't matter much in the overall picture.
1425  *
1426  * I've changed this to force applying the value, it should be more
1427  * correct and not so slow. The previous code is kept below for
1428  * reference but should be removed before next release!
1429  *
1430  * -- Gustavo Barbieri at 20-Aug-2011
1431  */
1432 {
1433    int tw, th, mw, mh, l, r, t, b, size;
1434    char *sfont = NULL;
1435
1436    _edje_text_class_font_get(ed, desc, &size, &sfont);
1437    free(sfont);
1438    params->type.text.size = size; /* XXX TODO used by further calcs, go inside recalc_apply? */
1439
1440    _edje_text_recalc_apply(ed, ep, params, chosen_desc);
1441
1442    evas_object_geometry_get(ep->object, NULL, NULL, &tw, &th);
1443
1444    if ((!chosen_desc) ||
1445        ((!chosen_desc->text.min_x) && (!chosen_desc->text.min_y) &&
1446         (!chosen_desc->text.max_x) && (!chosen_desc->text.max_y)))
1447      return;
1448
1449    evas_object_geometry_get(ep->object, NULL, NULL, &tw, &th);
1450    evas_object_text_style_pad_get(ep->object, &l, &r, &t, &b);
1451
1452    mw = tw + l + r;
1453    mh = th + t + b;
1454
1455    if (chosen_desc->text.max_x)
1456      {
1457         if ((*maxw < 0) || (mw < *maxw)) *maxw = mw;
1458      }
1459    if (chosen_desc->text.max_y)
1460      {
1461         if ((*maxh < 0) || (mh < *maxh)) *maxh = mh;
1462      }
1463    if (chosen_desc->text.min_x)
1464      {
1465         if (mw > *minw) *minw = mw;
1466      }
1467    if (chosen_desc->text.min_y)
1468      {
1469         if (mh > *minh) *minh = mh;
1470      }
1471 }
1472 #else
1473 {
1474    char *sfont = NULL;
1475    int size;
1476
1477    if (chosen_desc)
1478      {
1479         const char *text;
1480         const char *font;
1481         Evas_Coord tw, th;
1482         int inlined_font = 0;
1483
1484         /* Update a object_text part */
1485
1486         if (chosen_desc->text.id_source >= 0)
1487           ep->text.source = ed->table_parts[chosen_desc->text.id_source % ed->table_parts_size];
1488         else
1489           ep->text.source = NULL;
1490
1491         if (chosen_desc->text.id_text_source >= 0)
1492           ep->text.text_source = ed->table_parts[chosen_desc->text.id_text_source % ed->table_parts_size];
1493         else
1494           ep->text.text_source = NULL;
1495
1496         if (ep->text.text_source)
1497           text = edje_string_get(&(((Edje_Part_Description_Text*)ep->text.text_source->chosen_description)->text.text));
1498         else
1499           text = edje_string_get(&chosen_desc->text.text);
1500
1501         if (ep->text.source)
1502           font = _edje_text_class_font_get(ed, ((Edje_Part_Description_Text*)ep->text.source->chosen_description), &size, &sfont);
1503         else
1504           font = _edje_text_class_font_get(ed, chosen_desc, &size, &sfont);
1505
1506         if (!font) font = "";
1507
1508         if (ep->text.text_source)
1509           {
1510              if (ep->text.text_source->text.text) text = ep->text.text_source->text.text;
1511           }
1512         else
1513           {
1514              if (ep->text.text) text = ep->text.text;
1515           }
1516
1517         if (ep->text.source)
1518           {
1519              if (ep->text.source->text.font) font = ep->text.source->text.font;
1520              if (ep->text.source->text.size > 0) size = ep->text.source->text.size;
1521           }
1522         else
1523           {
1524              if (ep->text.font) font = ep->text.font;
1525              if (ep->text.size > 0) size = ep->text.size;
1526           }
1527         if (!text) text = "";
1528
1529         /* check if the font is embedded in the .eet */
1530         if (ed->file->fonts)
1531           {
1532              Edje_Font_Directory_Entry *fnt;
1533
1534              fnt = eina_hash_find(ed->file->fonts, font);
1535
1536              if (fnt)
1537                {
1538                   char *font2;
1539
1540                   size_t len = strlen(font) + sizeof("edje/fonts/") + 1;
1541                   font2 = alloca(len);
1542                   sprintf(font2, "edje/fonts/%s", font);
1543                   font = font2;
1544                   inlined_font = 1;
1545                }
1546           }
1547         if (ep->part->scale)
1548           evas_object_scale_set(ep->object, TO_DOUBLE(sc));
1549         if (inlined_font)
1550           {
1551              evas_object_text_font_source_set(ep->object, ed->path);
1552           }
1553         else evas_object_text_font_source_set(ep->object, NULL);
1554
1555         if ((_edje_fontset_append) && (font))
1556           {
1557              char *font2;
1558
1559              font2 = malloc(strlen(font) + 1 + strlen(_edje_fontset_append) + 1);
1560              if (font2)
1561                {
1562                   strcpy(font2, font);
1563                   strcat(font2, ",");
1564                   strcat(font2, _edje_fontset_append);
1565                   evas_object_text_font_set(ep->object, font2, size);
1566                   free(font2);
1567                }
1568           }
1569         else
1570           evas_object_text_font_set(ep->object, font, size);
1571         if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y) ||
1572             (chosen_desc->text.max_x) || (chosen_desc->text.max_y))
1573           {
1574              int mw, mh;
1575              Evas_Text_Style_Type
1576                 style = EVAS_TEXT_STYLE_PLAIN,
1577                       shadow = EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT;
1578              const Evas_Text_Style_Type styles[] = {
1579                   EVAS_TEXT_STYLE_PLAIN,
1580                   EVAS_TEXT_STYLE_PLAIN,
1581                   EVAS_TEXT_STYLE_OUTLINE,
1582                   EVAS_TEXT_STYLE_SOFT_OUTLINE,
1583                   EVAS_TEXT_STYLE_SHADOW,
1584                   EVAS_TEXT_STYLE_SOFT_SHADOW,
1585                   EVAS_TEXT_STYLE_OUTLINE_SHADOW,
1586                   EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW,
1587                   EVAS_TEXT_STYLE_FAR_SHADOW,
1588                   EVAS_TEXT_STYLE_FAR_SOFT_SHADOW,
1589                   EVAS_TEXT_STYLE_GLOW
1590              };
1591              const Evas_Text_Style_Type shadows[] = {
1592                   EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT,
1593                   EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM,
1594                   EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT,
1595                   EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT,
1596                   EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT,
1597                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP,
1598                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT,
1599                 EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT
1600              };
1601
1602              if ((ep->part->effect & EVAS_TEXT_STYLE_MASK_BASIC)
1603                  < EDJE_TEXT_EFFECT_LAST)
1604                style = styles[ep->part->effect];
1605              shadow = shadows
1606                 [(ep->part->effect & EDJE_TEXT_EFFECT_MASK_SHADOW_DIRECTION) >> 4];
1607              EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(style, shadow);
1608
1609              evas_object_text_style_set(ep->object, style);
1610              evas_object_text_text_set(ep->object, text);
1611              evas_object_geometry_get(ep->object, NULL, NULL, &tw, &th);
1612              if (chosen_desc->text.max_x)
1613                {
1614                   int l, r;
1615                   evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
1616                   mw = tw + l + r;
1617                   if ((*maxw < 0) || (mw < *maxw)) *maxw = mw;
1618                }
1619              if (chosen_desc->text.max_y)
1620                {
1621                   int t, b;
1622                   evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
1623                   mh = th + t + b;
1624                   if ((*maxh < 0) || (mh < *maxh)) *maxh = mh;
1625                }
1626              if (chosen_desc->text.min_x)
1627                {
1628                   int l, r;
1629                   evas_object_text_style_pad_get(ep->object, &l, &r, NULL, NULL);
1630                   mw = tw + l + r;
1631                   if (mw > *minw) *minw = mw;
1632                }
1633              if (chosen_desc->text.min_y)
1634                {
1635                   int t, b;
1636                   evas_object_text_style_pad_get(ep->object, NULL, NULL, &t, &b);
1637                   mh = th + t + b;
1638                   if (mh > *minh) *minh = mh;
1639                }
1640           }
1641         if (sfont) free(sfont);
1642      }
1643
1644    /* FIXME: Do we really need to call it twice if chosen_desc ? */
1645    sfont = NULL;
1646    _edje_text_class_font_get(ed, desc, &size, &sfont);
1647    free(sfont);
1648    params->type.text.size = size;
1649 }
1650 #endif
1651
1652 static void
1653 _edje_part_recalc_single_min_length(FLOAT_T align, int *start, int *length, int min)
1654 {
1655    if (min >= 0)
1656      {
1657         if (*length < min)
1658           {
1659              *start += TO_INT(SCALE(align, (*length - min)));
1660              *length = min;
1661           }
1662      }
1663 }
1664
1665 static void
1666 _edje_part_recalc_single_min(Edje_Part_Description_Common *desc,
1667                              Edje_Calc_Params *params,
1668                              int minw, int minh,
1669                              Edje_Internal_Aspect aspect)
1670 {
1671    int tmp;
1672    int w;
1673    int h;
1674
1675    w = params->w ? params->w : 99999;
1676    h = params->h ? params->h : 99999;
1677
1678    switch (aspect)
1679      {
1680       case EDJE_ASPECT_PREFER_NONE:
1681          break;
1682       case EDJE_ASPECT_PREFER_VERTICAL:
1683          tmp = minh * params->w / h;
1684          if (tmp >= minw)
1685            {
1686               minw = tmp;
1687               break;
1688            }
1689       case EDJE_ASPECT_PREFER_HORIZONTAL:
1690          tmp = minw * params->h / w;
1691          if (tmp >= minh)
1692            {
1693               minh = tmp;
1694               break;
1695            }
1696       case EDJE_ASPECT_PREFER_SOURCE:
1697       case EDJE_ASPECT_PREFER_BOTH:
1698          tmp = minh * params->w / h;
1699          if (tmp >= minw)
1700            {
1701               minw = tmp;
1702               break;
1703            }
1704
1705          tmp = minw * params->h / w;
1706          if (tmp >= minh)
1707            {
1708               minh = tmp;
1709               break;
1710            }
1711
1712          break;
1713      }
1714
1715    _edje_part_recalc_single_min_length(desc->align.x, &params->x, &params->w, minw);
1716    _edje_part_recalc_single_min_length(desc->align.y, &params->y, &params->h, minh);
1717 }
1718
1719 static void
1720 _edje_part_recalc_single_max_length(FLOAT_T align, int *start, int *length, int max)
1721 {
1722    if (max >= 0)
1723      {
1724         if (*length > max)
1725           {
1726              *start += TO_INT(SCALE(align, (*length - max)));
1727              *length = max;
1728           }
1729      }
1730 }
1731
1732 static void
1733 _edje_part_recalc_single_max(Edje_Part_Description_Common *desc,
1734                              Edje_Calc_Params *params,
1735                              int maxw, int maxh,
1736                              Edje_Internal_Aspect aspect)
1737 {
1738    int tmp;
1739    int w;
1740    int h;
1741
1742    w = params->w ? params->w : 99999;
1743    h = params->h ? params->h : 99999;
1744
1745    switch (aspect)
1746      {
1747       case EDJE_ASPECT_PREFER_NONE:
1748          break;
1749       case EDJE_ASPECT_PREFER_VERTICAL:
1750          tmp = maxh * params->w / h;
1751          if (tmp <= maxw)
1752            {
1753               maxw = tmp;
1754               break;
1755            }
1756       case EDJE_ASPECT_PREFER_HORIZONTAL:
1757          tmp = maxw * params->h / w;
1758          if (tmp <= maxh)
1759            {
1760               maxh = tmp;
1761               break;
1762            }
1763       case EDJE_ASPECT_PREFER_SOURCE:
1764       case EDJE_ASPECT_PREFER_BOTH:
1765          tmp = maxh * params->w / h;
1766          if (tmp <= maxw)
1767            {
1768               maxw = tmp;
1769               break;
1770            }
1771
1772          tmp = maxw * params->h / w;
1773          if (tmp <= maxh)
1774            {
1775               maxh = tmp;
1776               break;
1777            }
1778
1779          break;
1780      }
1781
1782    _edje_part_recalc_single_max_length(desc->align.x, &params->x, &params->w, maxw);
1783    _edje_part_recalc_single_max_length(desc->align.y, &params->y, &params->h, maxh);
1784 }
1785
1786 static void
1787 _edje_part_recalc_single_drag(Edje_Real_Part *ep,
1788                               Edje_Real_Part *confine_to,
1789                               Edje_Calc_Params *params,
1790                               int minw, int minh,
1791                               int maxw, int maxh)
1792 {
1793    /* confine */
1794    if (confine_to)
1795      {
1796         int offset;
1797         int step;
1798         FLOAT_T v;
1799
1800         /* complex dragable params */
1801         v = SCALE(ep->drag->size.x, confine_to->w);
1802
1803         if ((minw > 0) && (TO_INT(v) < minw)) params->w = minw;
1804         else if ((maxw >= 0) && (TO_INT(v) > maxw)) params->w = maxw;
1805         else params->w = TO_INT(v);
1806
1807         offset = TO_INT(SCALE(ep->drag->x, (confine_to->w - params->w)))
1808            + ep->drag->tmp.x;
1809         if (ep->part->dragable.step_x > 0)
1810           {
1811              params->x = confine_to->x +
1812                 ((offset / ep->part->dragable.step_x) * ep->part->dragable.step_x);
1813           }
1814         else if (ep->part->dragable.count_x > 0)
1815           {
1816              step = (confine_to->w - params->w) / ep->part->dragable.count_x;
1817              if (step < 1) step = 1;
1818              params->x = confine_to->x +
1819                 ((offset / step) * step);
1820           }
1821         params->req_drag.x = params->x;
1822         params->req_drag.w = params->w;
1823
1824         v = SCALE(ep->drag->size.y, confine_to->h);
1825
1826         if ((minh > 0) && (TO_INT(v) < minh)) params->h = minh;
1827         else if ((maxh >= 0) && (TO_INT(v) > maxh)) params->h = maxh;
1828         else params->h = TO_INT(v);
1829
1830         offset = TO_INT(SCALE(ep->drag->y, (confine_to->h - params->h)))
1831            + ep->drag->tmp.y;
1832         if (ep->part->dragable.step_y > 0)
1833           {
1834              params->y = confine_to->y +
1835                 ((offset / ep->part->dragable.step_y) * ep->part->dragable.step_y);
1836           }
1837         else if (ep->part->dragable.count_y > 0)
1838           {
1839              step = (confine_to->h - params->h) / ep->part->dragable.count_y;
1840              if (step < 1) step = 1;
1841              params->y = confine_to->y +
1842                 ((offset / step) * step);
1843           }
1844         params->req_drag.y = params->y;
1845         params->req_drag.h = params->h;
1846
1847         /* limit to confine */
1848         if (params->x < confine_to->x)
1849           {
1850              params->x = confine_to->x;
1851           }
1852         if ((params->x + params->w) > (confine_to->x + confine_to->w))
1853           {
1854              params->x = confine_to->x + confine_to->w - params->w;
1855           }
1856         if (params->y < confine_to->y)
1857           {
1858              params->y = confine_to->y;
1859           }
1860         if ((params->y + params->h) > (confine_to->y + confine_to->h))
1861           {
1862              params->y = confine_to->y + confine_to->h - params->h;
1863           }
1864      }
1865    else
1866      {
1867         /* simple dragable params */
1868         params->x += TO_INT(ep->drag->x) + ep->drag->tmp.x;
1869         params->req_drag.x = params->x;
1870         params->req_drag.w = params->w;
1871
1872         params->y += TO_INT(ep->drag->y) + ep->drag->tmp.y;
1873         params->req_drag.y = params->y;
1874         params->req_drag.h = params->h;
1875      }
1876 }
1877
1878 static void
1879 _edje_part_recalc_single_fill(Edje_Real_Part *ep,
1880                               Edje_Part_Description_Spec_Fill *fill,
1881                               Edje_Calc_Params *params)
1882 {
1883    int fw;
1884    int fh;
1885
1886    params->smooth = fill->smooth;
1887
1888    if (fill->type == EDJE_FILL_TYPE_TILE)
1889      evas_object_image_size_get(ep->object, &fw, NULL);
1890    else
1891      fw = params->w;
1892
1893    params->type.common.fill.x = fill->pos_abs_x
1894       + TO_INT(SCALE(fill->pos_rel_x, fw));
1895    params->type.common.fill.w = fill->abs_x
1896       + TO_INT(SCALE(fill->rel_x, fw));
1897
1898    if (fill->type == EDJE_FILL_TYPE_TILE)
1899      evas_object_image_size_get(ep->object, NULL, &fh);
1900    else
1901      fh = params->h;
1902
1903    params->type.common.fill.y = fill->pos_abs_y
1904       + TO_INT(SCALE(fill->pos_rel_y, fh));
1905    params->type.common.fill.h = fill->abs_y
1906       + TO_INT(SCALE(fill->rel_y, fh));
1907
1908    params->type.common.fill.angle = fill->angle;
1909    params->type.common.fill.spread = fill->spread;
1910 }
1911
1912 static void
1913 _edje_part_recalc_single_min_max(FLOAT_T sc,
1914                                  Edje_Real_Part *ep,
1915                                  Edje_Part_Description_Common *desc,
1916                                  int *minw, int *minh,
1917                                  int *maxw, int *maxh)
1918 {
1919    *minw = desc->min.w;
1920    if (ep->part->scale) *minw = TO_INT(SCALE(sc, *minw));
1921    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
1922        (ep->typedata.swallow))
1923      {
1924         if (ep->typedata.swallow->swallow_params.min.w > desc->min.w)
1925           *minw = ep->typedata.swallow->swallow_params.min.w;
1926      }
1927
1928    if (ep->edje->calc_only)
1929      {
1930         if (desc->minmul.have)
1931           {
1932              FLOAT_T mmw = desc->minmul.w;
1933              if (mmw != FROM_INT(1)) *minw = TO_INT(SCALE(mmw, *minw));
1934           }
1935      }
1936
1937    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
1938        (ep->typedata.swallow))
1939      {
1940         /* XXX TODO: remove need of EDJE_INF_MAX_W, see edje_util.c */
1941         if ((ep->typedata.swallow->swallow_params.max.w <= 0) ||
1942             (ep->typedata.swallow->swallow_params.max.w == EDJE_INF_MAX_W))
1943           {
1944              *maxw = desc->max.w;
1945              if (*maxw > 0)
1946                {
1947                   if (ep->part->scale) *maxw = TO_INT(SCALE(sc, *maxw));
1948                   if (*maxw < 1) *maxw = 1;
1949                }
1950           }
1951         else
1952           {
1953              if (desc->max.w <= 0)
1954                *maxw = ep->typedata.swallow->swallow_params.max.w;
1955              else
1956                {
1957                   *maxw = desc->max.w;
1958                   if (*maxw > 0)
1959                     {
1960                        if (ep->part->scale) *maxw = TO_INT(SCALE(sc, *maxw));
1961                        if (*maxw < 1) *maxw = 1;
1962                     }
1963                   if (ep->typedata.swallow->swallow_params.max.w < *maxw)
1964                     *maxw = ep->typedata.swallow->swallow_params.max.w;
1965                }
1966           }
1967      }
1968    else
1969      {
1970         *maxw = desc->max.w;
1971         if (*maxw > 0)
1972           {
1973              if (ep->part->scale) *maxw = TO_INT(SCALE(sc, *maxw));
1974              if (*maxw < 1) *maxw = 1;
1975           }
1976      }
1977    if ((ep->edje->calc_only) && (desc->minmul.have) &&
1978        (desc->minmul.w != FROM_INT(1))) *maxw = *minw;
1979    if (*maxw >= 0)
1980      {
1981         if (*maxw < *minw) *maxw = *minw;
1982      }
1983
1984    *minh = desc->min.h;
1985    if (ep->part->scale) *minh = TO_INT(SCALE(sc, *minh));
1986    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
1987        (ep->typedata.swallow))
1988      {
1989         if (ep->typedata.swallow->swallow_params.min.h > desc->min.h)
1990           *minh = ep->typedata.swallow->swallow_params.min.h;
1991      }
1992
1993    if (ep->edje->calc_only)
1994      {
1995         if (desc->minmul.have)
1996           {
1997              FLOAT_T mmh = desc->minmul.h;
1998              if (mmh != FROM_INT(1)) *minh = TO_INT(SCALE(mmh, *minh));
1999           }
2000      }
2001
2002    if ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2003        (ep->typedata.swallow))
2004      {
2005         /* XXX TODO: remove need of EDJE_INF_MAX_H, see edje_util.c */
2006         if ((ep->typedata.swallow->swallow_params.max.h <= 0) ||
2007             (ep->typedata.swallow->swallow_params.max.h == EDJE_INF_MAX_H))
2008           {
2009              *maxh = desc->max.h;
2010              if (*maxh > 0)
2011                {
2012                   if (ep->part->scale) *maxh = TO_INT(SCALE(sc, *maxh));
2013                   if (*maxh < 1) *maxh = 1;
2014                }
2015           }
2016         else
2017           {
2018              if (desc->max.h <= 0)
2019                *maxh = ep->typedata.swallow->swallow_params.max.h;
2020              else
2021                {
2022                   *maxh = desc->max.h;
2023                   if (*maxh > 0)
2024                     {
2025                        if (ep->part->scale) *maxh = TO_INT(SCALE(sc, *maxh));
2026                        if (*maxh < 1) *maxh = 1;
2027                     }
2028                   if (ep->typedata.swallow->swallow_params.max.h < *maxh)
2029                     *maxh = ep->typedata.swallow->swallow_params.max.h;
2030                }
2031           }
2032      }
2033    else
2034      {
2035         *maxh = desc->max.h;
2036         if (*maxh > 0)
2037           {
2038              if (ep->part->scale) *maxh = TO_INT(SCALE(sc, *maxh));
2039              if (*maxh < 1) *maxh = 1;
2040           }
2041      }
2042    if ((ep->edje->calc_only) && (desc->minmul.have) &&
2043        (desc->minmul.h != FROM_INT(1))) *maxh = *minh;
2044    if (*maxh >= 0)
2045      {
2046         if (*maxh < *minh) *maxh = *minh;
2047      }
2048 }
2049
2050 static void
2051 _edje_part_recalc_single_map(Edje *ed,
2052                              Edje_Real_Part *ep __UNUSED__,
2053                              Edje_Real_Part *center,
2054                              Edje_Real_Part *light,
2055                              Edje_Real_Part *persp,
2056                              Edje_Part_Description_Common *desc,
2057                              Edje_Part_Description_Common *chosen_desc,
2058                              Edje_Calc_Params *params)
2059 {
2060    params->mapped = chosen_desc->map.on;
2061    params->lighted = params->mapped ? !!light : 0;
2062    params->persp_on = params->mapped ? !!persp : 0;
2063
2064    if (!params->mapped) return ;
2065
2066    if (center)
2067      {
2068         params->map.center.x = ed->x + center->x + (center->w / 2);
2069         params->map.center.y = ed->y + center->y + (center->h / 2);
2070      }
2071    else
2072      {
2073         params->map.center.x = ed->x + params->x + (params->w / 2);
2074         params->map.center.y = ed->y + params->y + (params->h / 2);
2075      }
2076    params->map.center.z = 0;
2077
2078    params->map.rotation.x = desc->map.rot.x;
2079    params->map.rotation.y = desc->map.rot.y;
2080    params->map.rotation.z = desc->map.rot.z;
2081
2082    if (light)
2083      {
2084         Edje_Part_Description_Common *light_desc2;
2085         FLOAT_T pos, pos2;
2086
2087         params->map.light.x = ed->x + light->x + (light->w / 2);
2088         params->map.light.y = ed->y + light->y + (light->h / 2);
2089
2090         pos = light->description_pos;
2091         pos2 = (pos < ZERO) ? ZERO : ((pos > FROM_INT(1)) ? FROM_INT(1) : pos);
2092
2093         light_desc2 = light->param2 ? light->param2->description : NULL;
2094
2095         /* take into account CURRENT state also */
2096         if (pos != ZERO && light_desc2)
2097           {
2098              params->map.light.z = light->param1.description->persp.zplane +
2099                TO_INT(SCALE(pos, light_desc2->persp.zplane - light->param1.description->persp.zplane));
2100              params->map.light.r = light->param1.description->color.r +
2101                TO_INT(SCALE(pos2, light_desc2->color.r - light->param1.description->color.r));
2102              params->map.light.g = light->param1.description->color.g +
2103                TO_INT(SCALE(pos2, light_desc2->color.g - light->param1.description->color.g));
2104              params->map.light.b = light->param1.description->color.b +
2105                TO_INT(SCALE(pos2, light_desc2->color.b - light->param1.description->color.b));
2106              params->map.light.ar = light->param1.description->color2.r +
2107                TO_INT(SCALE(pos2, light_desc2->color2.r - light->param1.description->color2.r));
2108              params->map.light.ag = light->param1.description->color2.g +
2109                TO_INT(SCALE(pos2, light_desc2->color2.g - light->param1.description->color2.g));
2110              params->map.light.ab = light->param1.description->color2.b +
2111                TO_INT(SCALE(pos2, light_desc2->color2.b - light->param1.description->color2.b));
2112           }
2113         else
2114           {
2115              params->map.light.z = light->param1.description->persp.zplane;
2116              params->map.light.r = light->param1.description->color.r;
2117              params->map.light.g = light->param1.description->color.g;
2118              params->map.light.b = light->param1.description->color.b;
2119              params->map.light.ar = light->param1.description->color2.r;
2120              params->map.light.ag = light->param1.description->color2.g;
2121              params->map.light.ab = light->param1.description->color2.b;
2122           }
2123      }
2124
2125    if (persp)
2126      {
2127         FLOAT_T pos;
2128
2129         params->map.persp.x = ed->x + persp->x + (persp->w / 2);
2130         params->map.persp.y = ed->y + persp->y + (persp->h / 2);
2131
2132         pos = persp->description_pos;
2133
2134         if (pos != 0 && persp->param2)
2135           {
2136              params->map.persp.z = persp->param1.description->persp.zplane +
2137                TO_INT(SCALE(pos, persp->param2->description->persp.zplane -
2138                             persp->param1.description->persp.zplane));
2139              params->map.persp.focal = persp->param1.description->persp.focal +
2140                TO_INT(SCALE(pos, persp->param2->description->persp.focal -
2141                             persp->param1.description->persp.focal));
2142           }
2143         else
2144           {
2145              params->map.persp.z = persp->param1.description->persp.zplane;
2146              params->map.persp.focal = persp->param1.description->persp.focal;
2147           }
2148      }
2149 }
2150
2151 static void
2152 _edje_part_recalc_single(Edje *ed,
2153                          Edje_Real_Part *ep,
2154                          Edje_Part_Description_Common *desc,
2155                          Edje_Part_Description_Common *chosen_desc,
2156                          Edje_Real_Part *center,
2157                          Edje_Real_Part *light,
2158                          Edje_Real_Part *persp,
2159                          Edje_Real_Part *rel1_to_x,
2160                          Edje_Real_Part *rel1_to_y,
2161                          Edje_Real_Part *rel2_to_x,
2162                          Edje_Real_Part *rel2_to_y,
2163                          Edje_Real_Part *confine_to,
2164                          Edje_Calc_Params *params,
2165                          FLOAT_T pos)
2166 {
2167    Edje_Color_Class *cc = NULL;
2168    Edje_Internal_Aspect apref;
2169    int minw = 0, minh = 0, maxw = 0, maxh = 0;
2170    FLOAT_T sc;
2171
2172    sc = ed->scale;
2173    if (sc == ZERO) sc = _edje_scale;
2174    _edje_part_recalc_single_min_max(sc, ep, desc, &minw, &minh, &maxw, &maxh);
2175
2176    /* relative coords of top left & bottom right */
2177    _edje_part_recalc_single_rel(ed, ep, desc, rel1_to_x, rel1_to_y, rel2_to_x, rel2_to_y, params);
2178
2179    /* aspect */
2180    apref = _edje_part_recalc_single_aspect(ed, ep, desc, params, &minw, &minh, &maxw, &maxh, pos);
2181
2182    /* size step */
2183    _edje_part_recalc_single_step(desc, params);
2184
2185    /* if we have text that wants to make the min size the text size... */
2186    if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
2187      _edje_part_recalc_single_textblock(sc, ed, ep, (Edje_Part_Description_Text*) chosen_desc, params, &minw, &minh, &maxw, &maxh);
2188    else if (ep->part->type == EDJE_PART_TYPE_TEXT)
2189      _edje_part_recalc_single_text(sc, ed, ep, (Edje_Part_Description_Text*) desc, (Edje_Part_Description_Text*) chosen_desc, params, &minw, &minh, &maxw, &maxh);
2190
2191    if ((ep->part->type == EDJE_PART_TYPE_TABLE) &&
2192        (((((Edje_Part_Description_Table *)chosen_desc)->table.min.h) ||
2193          (((Edje_Part_Description_Table *)chosen_desc)->table.min.v))))
2194      {
2195         Evas_Coord lminw = 0, lminh = 0;
2196
2197         evas_object_smart_need_recalculate_set(ep->object, 1);
2198         evas_object_smart_calculate(ep->object);
2199         evas_object_size_hint_min_get(ep->object, &lminw, &lminh);
2200         if (((Edje_Part_Description_Table *)chosen_desc)->table.min.h)
2201           {
2202              if (lminw > minw) minw = lminw;
2203           }
2204         if (((Edje_Part_Description_Table *)chosen_desc)->table.min.v)
2205           {
2206              if (lminh > minh) minh = lminh;
2207           }
2208      }
2209    else if ((ep->part->type == EDJE_PART_TYPE_BOX) &&
2210             ((((Edje_Part_Description_Box *)chosen_desc)->box.min.h) ||
2211              (((Edje_Part_Description_Box *)chosen_desc)->box.min.v)))
2212      {
2213         Evas_Coord lminw = 0, lminh = 0;
2214
2215         evas_object_smart_need_recalculate_set(ep->object, 1);
2216         evas_object_smart_calculate(ep->object);
2217         evas_object_size_hint_min_get(ep->object, &lminw, &lminh);
2218         if (((Edje_Part_Description_Box *)chosen_desc)->box.min.h)
2219           {
2220              if (lminw > minw) minw = lminw;
2221           }
2222         if (((Edje_Part_Description_Box *)chosen_desc)->box.min.v)
2223           {
2224              if (lminh > minh) minh = lminh;
2225           }
2226      }
2227    else if ((ep->part->type == EDJE_PART_TYPE_IMAGE) &&
2228             (chosen_desc->min.limit || chosen_desc->max.limit))
2229      {
2230         Evas_Coord w, h;
2231
2232         /* We only need pos to find the right image that would be displayed */
2233         /* Yes, if someone set aspect preference to SOURCE and also max,min
2234            to SOURCE, it will be under efficient, but who cares at the
2235            moment. */
2236         _edje_real_part_image_set(ed, ep, pos);
2237         evas_object_image_size_get(ep->object, &w, &h);
2238
2239         if (chosen_desc->min.limit)
2240           {
2241              if (w > minw) minw = w;
2242              if (h > minh) minh = h;
2243           }
2244         if (chosen_desc->max.limit)
2245           {
2246              if ((maxw <= 0) || (w < maxw)) maxw = w;
2247              if ((maxh <= 0) || (h < maxh)) maxh = h;
2248           }
2249      }
2250
2251    /* remember what our size is BEFORE we go limit it */
2252    params->req.x = params->x;
2253    params->req.y = params->y;
2254    params->req.w = params->w;
2255    params->req.h = params->h;
2256
2257    /* adjust for min size */
2258    _edje_part_recalc_single_min(desc, params, minw, minh, apref);
2259
2260    /* adjust for max size */
2261    _edje_part_recalc_single_max(desc, params, maxw, maxh, apref);
2262
2263    /* take care of dragable part */
2264    if (ep->drag)
2265      _edje_part_recalc_single_drag(ep, confine_to, params, minw, minh, maxw, maxh);
2266
2267    /* fill */
2268    if (ep->part->type == EDJE_PART_TYPE_IMAGE)
2269      _edje_part_recalc_single_fill(ep, &((Edje_Part_Description_Image *)desc)->image.fill, params);
2270    else if (ep->part->type == EDJE_PART_TYPE_PROXY)
2271      _edje_part_recalc_single_fill(ep, &((Edje_Part_Description_Proxy *)desc)->proxy.fill, params);
2272
2273    if (ep->part->type != EDJE_PART_TYPE_SPACER)
2274      {
2275         /* colors */
2276         if ((desc->color_class) && (*desc->color_class))
2277           cc = _edje_color_class_find(ed, desc->color_class);
2278
2279         if (cc)
2280           {
2281              params->color.r = (((int)cc->r + 1) * desc->color.r) >> 8;
2282              params->color.g = (((int)cc->g + 1) * desc->color.g) >> 8;
2283              params->color.b = (((int)cc->b + 1) * desc->color.b) >> 8;
2284              params->color.a = (((int)cc->a + 1) * desc->color.a) >> 8;
2285           }
2286         else
2287           {
2288              params->color.r = desc->color.r;
2289              params->color.g = desc->color.g;
2290              params->color.b = desc->color.b;
2291              params->color.a = desc->color.a;
2292           }
2293      }
2294
2295    /* visible */
2296    params->visible = desc->visible;
2297
2298    switch (ep->part->type)
2299      {
2300       case EDJE_PART_TYPE_IMAGE:
2301            {
2302               Edje_Part_Description_Image *img_desc = (Edje_Part_Description_Image*) desc;
2303
2304               /* border */
2305               params->type.common.spec.image.l = img_desc->image.border.l;
2306               params->type.common.spec.image.r = img_desc->image.border.r;
2307
2308               params->type.common.spec.image.t = img_desc->image.border.t;
2309               params->type.common.spec.image.b = img_desc->image.border.b;
2310
2311               params->type.common.spec.image.border_scale_by = img_desc->image.border.scale_by;
2312               break;
2313            }
2314       case EDJE_PART_TYPE_TEXT:
2315       case EDJE_PART_TYPE_TEXTBLOCK:
2316            {
2317               Edje_Part_Description_Text *text_desc = (Edje_Part_Description_Text*) desc;
2318
2319               /* text.align */
2320               params->type.text.align.x = text_desc->text.align.x;
2321               params->type.text.align.y = text_desc->text.align.y;
2322               params->type.text.elipsis = text_desc->text.elipsis;
2323
2324               /* text colors */
2325               if (cc)
2326                 {
2327                    params->type.text.color2.r = (((int)cc->r2 + 1) * text_desc->common.color2.r) >> 8;
2328                    params->type.text.color2.g = (((int)cc->g2 + 1) * text_desc->common.color2.g) >> 8;
2329                    params->type.text.color2.b = (((int)cc->b2 + 1) * text_desc->common.color2.b) >> 8;
2330                    params->type.text.color2.a = (((int)cc->a2 + 1) * text_desc->common.color2.a) >> 8;
2331                    params->type.text.color3.r = (((int)cc->r3 + 1) * text_desc->text.color3.r) >> 8;
2332                    params->type.text.color3.g = (((int)cc->g3 + 1) * text_desc->text.color3.g) >> 8;
2333                    params->type.text.color3.b = (((int)cc->b3 + 1) * text_desc->text.color3.b) >> 8;
2334                    params->type.text.color3.a = (((int)cc->a3 + 1) * text_desc->text.color3.a) >> 8;
2335                 }
2336               else
2337                 {
2338                    params->type.text.color2.r = text_desc->common.color2.r;
2339                    params->type.text.color2.g = text_desc->common.color2.g;
2340                    params->type.text.color2.b = text_desc->common.color2.b;
2341                    params->type.text.color2.a = text_desc->common.color2.a;
2342                    params->type.text.color3.r = text_desc->text.color3.r;
2343                    params->type.text.color3.g = text_desc->text.color3.g;
2344                    params->type.text.color3.b = text_desc->text.color3.b;
2345                    params->type.text.color3.a = text_desc->text.color3.a;
2346                 }
2347
2348               break;
2349            }
2350       case EDJE_PART_TYPE_SPACER:
2351       case EDJE_PART_TYPE_RECTANGLE:
2352       case EDJE_PART_TYPE_BOX:
2353       case EDJE_PART_TYPE_TABLE:
2354       case EDJE_PART_TYPE_SWALLOW:
2355       case EDJE_PART_TYPE_GROUP:
2356       case EDJE_PART_TYPE_PROXY:
2357          break;
2358       case EDJE_PART_TYPE_GRADIENT:
2359          /* FIXME: THIS ONE SHOULD NEVER BE TRIGGERED. */
2360          break;
2361       default:
2362          break;
2363      }
2364
2365    _edje_part_recalc_single_map(ed, ep, center, light, persp, desc, chosen_desc, params);
2366 }
2367
2368 static void
2369 _edje_table_recalc_apply(Edje *ed __UNUSED__,
2370                          Edje_Real_Part *ep,
2371                          Edje_Calc_Params *p3 __UNUSED__,
2372                          Edje_Part_Description_Table *chosen_desc)
2373 {
2374    evas_object_table_homogeneous_set(ep->object, chosen_desc->table.homogeneous);
2375    evas_object_table_align_set(ep->object, TO_DOUBLE(chosen_desc->table.align.x), TO_DOUBLE(chosen_desc->table.align.y));
2376    evas_object_table_padding_set(ep->object, chosen_desc->table.padding.x, chosen_desc->table.padding.y);
2377    if (evas_object_smart_need_recalculate_get(ep->object))
2378      {
2379         evas_object_smart_need_recalculate_set(ep->object, 0);
2380         evas_object_smart_calculate(ep->object);
2381      }
2382 }
2383
2384 static void
2385 _edje_proxy_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Proxy *chosen_desc, FLOAT_T pos)
2386 {
2387    Edje_Real_Part *pp;
2388    int part_id = -1;
2389
2390    if (pos >= FROM_DOUBLE(0.5))
2391      part_id = ((Edje_Part_Description_Proxy*) ep->param2->description)->proxy.id;
2392    else
2393      part_id = chosen_desc->proxy.id;
2394
2395    if ((p3->type.common.fill.w == 0) || (p3->type.common.fill.h == 0) ||
2396        (part_id < 0))
2397      {
2398         evas_object_image_source_set(ep->object, NULL);
2399         return;
2400      }
2401    pp = ed->table_parts[part_id % ed->table_parts_size];
2402
2403    if (pp->nested_smart)  /* using nested_smart for nested parts */
2404      {
2405         evas_object_image_source_set(ep->object, pp->nested_smart);
2406      }
2407    else
2408      {
2409         switch (pp->part->type)
2410           {
2411            case EDJE_PART_TYPE_IMAGE:
2412            case EDJE_PART_TYPE_TEXT:
2413            case EDJE_PART_TYPE_TEXTBLOCK:
2414            case EDJE_PART_TYPE_RECTANGLE:
2415            case EDJE_PART_TYPE_BOX:
2416            case EDJE_PART_TYPE_TABLE:
2417            case EDJE_PART_TYPE_PROXY:
2418               evas_object_image_source_set(ep->object, pp->object);
2419               break;
2420            case EDJE_PART_TYPE_GRADIENT:
2421               /* FIXME: THIS ONE SHOULD NEVER BE TRIGGERED. */
2422               break;
2423            case EDJE_PART_TYPE_GROUP:
2424            case EDJE_PART_TYPE_SWALLOW:
2425            case EDJE_PART_TYPE_EXTERNAL:
2426              if ((pp->type == EDJE_RP_TYPE_SWALLOW) &&
2427                  (pp->typedata.swallow))
2428                {
2429                   evas_object_image_source_set(ep->object, pp->typedata.swallow->swallowed_object);
2430                }
2431               break;
2432            case EDJE_PART_TYPE_SPACER:
2433               /* FIXME: detect that at compile time and prevent it */
2434               break;
2435           }
2436      }
2437
2438    evas_object_image_fill_set(ep->object, p3->type.common.fill.x, p3->type.common.fill.y,
2439                               p3->type.common.fill.w, p3->type.common.fill.h);
2440    evas_object_image_smooth_scale_set(ep->object, p3->smooth);
2441 }
2442
2443 static void
2444 _edje_image_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Image *chosen_desc, FLOAT_T pos)
2445 {
2446    FLOAT_T sc;
2447
2448    sc = ed->scale;
2449    if (sc == 0.0) sc = _edje_scale;
2450    evas_object_image_fill_set(ep->object, p3->type.common.fill.x, p3->type.common.fill.y,
2451                               p3->type.common.fill.w, p3->type.common.fill.h);
2452    evas_object_image_smooth_scale_set(ep->object, p3->smooth);
2453    if (chosen_desc->image.border.scale)
2454      {
2455         if (p3->type.common.spec.image.border_scale_by > FROM_DOUBLE(0.0))
2456           {
2457              FLOAT_T sc2 = MUL(sc, p3->type.common.spec.image.border_scale_by);
2458              evas_object_image_border_scale_set(ep->object, TO_DOUBLE(sc2));
2459           }
2460         else
2461            evas_object_image_border_scale_set(ep->object, TO_DOUBLE(sc));
2462      }
2463    else
2464      {
2465         if (p3->type.common.spec.image.border_scale_by > FROM_DOUBLE(0.0))
2466            evas_object_image_border_scale_set
2467            (ep->object, TO_DOUBLE(p3->type.common.spec.image.border_scale_by));
2468         else
2469           evas_object_image_border_scale_set(ep->object, 1.0);
2470      }
2471    evas_object_image_border_set(ep->object, p3->type.common.spec.image.l, p3->type.common.spec.image.r,
2472                                 p3->type.common.spec.image.t, p3->type.common.spec.image.b);
2473    if (chosen_desc->image.border.no_fill == 0)
2474      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_DEFAULT);
2475    else if (chosen_desc->image.border.no_fill == 1)
2476      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_NONE);
2477    else if (chosen_desc->image.border.no_fill == 2)
2478      evas_object_image_border_center_fill_set(ep->object, EVAS_BORDER_FILL_SOLID);
2479
2480    _edje_real_part_image_set(ed, ep, pos);
2481 }
2482
2483 static Edje_Real_Part *
2484 _edje_real_part_state_get(Edje *ed, Edje_Real_Part *ep, int flags, int id, int *state)
2485 {
2486    Edje_Real_Part *result = NULL;
2487
2488    if (id >= 0 && id != ep->part->id)
2489      {
2490         result = ed->table_parts[id % ed->table_parts_size];
2491         if (result)
2492           {
2493              if (!result->calculated) _edje_part_recalc(ed, result, flags, NULL);
2494 #ifdef EDJE_CALC_CACHE
2495              if (state) *state = result->state;
2496 #else
2497              (void) state;
2498 #endif
2499           }
2500      }
2501    return result;
2502 }
2503
2504 void
2505 _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state)
2506 {
2507 #ifdef EDJE_CALC_CACHE
2508    Eina_Bool proxy_invalidate = EINA_FALSE;
2509    int state1 = -1;
2510    int state2 = -1;
2511    int statec = -1;
2512 #else
2513    Edje_Calc_Params lp1, lp2;
2514 #endif
2515    int statec1 = -1;
2516    int statec2 = -1;
2517    int statel1 = -1;
2518    int statel2 = -1;
2519    int statep1 = -1;
2520    int statep2 = -1;
2521    Edje_Real_Part *center[2] = { NULL, NULL };
2522    Edje_Real_Part *light[2] = { NULL, NULL };
2523    Edje_Real_Part *persp[2] = { NULL, NULL };
2524    Edje_Calc_Params *p1, *pf;
2525    Edje_Part_Description_Common *chosen_desc;
2526    Edje_Real_Part *confine_to = NULL;
2527    FLOAT_T pos = ZERO, pos2;
2528    Edje_Calc_Params lp3;
2529
2530    /* GRADIENT ARE GONE, WE MUST IGNORE IT FROM OLD FILE. */
2531    if (ep->part->type == EDJE_PART_TYPE_GRADIENT)
2532      {
2533         ERR("GRADIENT spotted during recalc ! That should never happen ! Send your edje file to devel ml.");
2534         return;
2535      }
2536
2537    if ((ep->calculated & FLAG_XY) == FLAG_XY && !state)
2538      {
2539         return;
2540      }
2541    if (ep->calculating & flags)
2542      {
2543 #if 1
2544         const char *axes = "NONE", *faxes = "NONE";
2545
2546         if ((ep->calculating & FLAG_X) &&
2547             (ep->calculating & FLAG_Y))
2548           axes = "XY";
2549         else if ((ep->calculating & FLAG_X))
2550           axes = "X";
2551         else if ((ep->calculating & FLAG_Y))
2552           axes = "Y";
2553
2554         if ((flags & FLAG_X) &&
2555             (flags & FLAG_Y))
2556           faxes = "XY";
2557         else if ((flags & FLAG_X))
2558           faxes = "X";
2559         else if ((flags & FLAG_Y))
2560           faxes = "Y";
2561         ERR("Circular dependency when calculating part \"%s\". "
2562             "Already calculating %s [%02x] axes. "
2563             "Need to calculate %s [%02x] axes",
2564             ep->part->name,
2565             axes, ep->calculating,
2566             faxes, flags);
2567 #endif
2568         return;
2569      }
2570
2571    if (ep->part->scale &&
2572        ep->part->type == EDJE_PART_TYPE_GROUP &&
2573        ((ep->type == EDJE_RP_TYPE_SWALLOW) &&
2574            (ep->typedata.swallow)) &&
2575        ep->typedata.swallow->swallowed_object)
2576      {
2577         edje_object_scale_set(ep->typedata.swallow->swallowed_object, TO_DOUBLE(ed->scale));
2578
2579         if (ep->description_pos > FROM_DOUBLE(0.5) && ep->param2)
2580           {
2581              edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param2->description->min.limit);
2582           }
2583         else
2584           {
2585              edje_object_update_hints_set(ep->typedata.swallow->swallowed_object, ep->param1.description->min.limit);
2586           }
2587         if (edje_object_update_hints_get(ep->typedata.swallow->swallowed_object))
2588           {
2589              Edje *ted;
2590
2591              ted = _edje_fetch(ep->typedata.swallow->swallowed_object);
2592              _edje_recalc_do(ted);
2593           }
2594      }
2595
2596 #ifdef EDJE_CALC_CACHE
2597    if (ep->state == ed->state && !state)
2598      return ;
2599 #endif
2600
2601    if (flags & FLAG_X)
2602      {
2603         ep->calculating |= flags & FLAG_X;
2604         if (ep->param1.rel1_to_x)
2605           {
2606              _edje_part_recalc(ed, ep->param1.rel1_to_x, FLAG_X, NULL);
2607 #ifdef EDJE_CALC_CACHE
2608              state1 = ep->param1.rel1_to_x->state;
2609 #endif
2610           }
2611         if (ep->param1.rel2_to_x)
2612           {
2613              _edje_part_recalc(ed, ep->param1.rel2_to_x, FLAG_X, NULL);
2614 #ifdef EDJE_CALC_CACHE
2615              if (state1 < ep->param1.rel2_to_x->state)
2616                state1 = ep->param1.rel2_to_x->state;
2617 #endif
2618           }
2619         if (ep->param2)
2620           {
2621              if (ep->param2->rel1_to_x)
2622                {
2623                   _edje_part_recalc(ed, ep->param2->rel1_to_x, FLAG_X, NULL);
2624 #ifdef EDJE_CALC_CACHE
2625                   state2 = ep->param2->rel1_to_x->state;
2626 #endif
2627                }
2628              if (ep->param2->rel2_to_x)
2629                {
2630                   _edje_part_recalc(ed, ep->param2->rel2_to_x, FLAG_X, NULL);
2631 #ifdef EDJE_CALC_CACHE
2632                   if (state2 < ep->param2->rel2_to_x->state)
2633                     state2 = ep->param2->rel2_to_x->state;
2634 #endif
2635                }
2636           }
2637      }
2638    if (flags & FLAG_Y)
2639      {
2640         ep->calculating |= flags & FLAG_Y;
2641         if (ep->param1.rel1_to_y)
2642           {
2643              _edje_part_recalc(ed, ep->param1.rel1_to_y, FLAG_Y, NULL);
2644 #ifdef EDJE_CALC_CACHE
2645              if (state1 < ep->param1.rel1_to_y->state)
2646                state1 = ep->param1.rel1_to_y->state;
2647 #endif
2648           }
2649         if (ep->param1.rel2_to_y)
2650           {
2651              _edje_part_recalc(ed, ep->param1.rel2_to_y, FLAG_Y, NULL);
2652 #ifdef EDJE_CALC_CACHE
2653              if (state1 < ep->param1.rel2_to_y->state)
2654                state1 = ep->param1.rel2_to_y->state;
2655 #endif
2656           }
2657         if (ep->param2)
2658           {
2659              if (ep->param2->rel1_to_y)
2660                {
2661                   _edje_part_recalc(ed, ep->param2->rel1_to_y, FLAG_Y, NULL);
2662 #ifdef EDJE_CALC_CACHE
2663                   if (state2 < ep->param2->rel1_to_y->state)
2664                     state2 = ep->param2->rel1_to_y->state;
2665 #endif
2666                }
2667              if (ep->param2->rel2_to_y)
2668                {
2669                   _edje_part_recalc(ed, ep->param2->rel2_to_y, FLAG_Y, NULL);
2670 #ifdef EDJE_CALC_CACHE
2671                   if (state2 < ep->param2->rel2_to_y->state)
2672                     state2 = ep->param2->rel2_to_y->state;
2673 #endif
2674                }
2675           }
2676      }
2677    if (ep->drag && ep->drag->confine_to)
2678      {
2679         confine_to = ep->drag->confine_to;
2680         _edje_part_recalc(ed, confine_to, flags, NULL);
2681 #ifdef EDJE_CALC_CACHE
2682         statec = confine_to->state;
2683 #endif
2684      }
2685    //   if (ep->text.source)       _edje_part_recalc(ed, ep->text.source, flags);
2686    //   if (ep->text.text_source)  _edje_part_recalc(ed, ep->text.text_source, flags);
2687
2688    /* actually calculate now */
2689    chosen_desc = ep->chosen_description;
2690    if (!chosen_desc)
2691      {
2692         ep->calculating = FLAG_NONE;
2693         ep->calculated |= flags;
2694         return;
2695      }
2696
2697    pos = ep->description_pos;
2698
2699    if (ep->part->type == EDJE_PART_TYPE_PROXY)
2700      {
2701         Edje_Real_Part *pp;
2702         int part_id = -1;
2703
2704         if (pos >= FROM_DOUBLE(0.5))
2705           part_id = ((Edje_Part_Description_Proxy*) ep->param2->description)->proxy.id;
2706         else
2707           part_id = ((Edje_Part_Description_Proxy*) chosen_desc)->proxy.id;
2708
2709         pp = _edje_real_part_state_get(ed, ep, flags, part_id, NULL);
2710 #ifdef EDJE_CALC_CACHE
2711         if (pp && pp->invalidate) proxy_invalidate = EINA_TRUE;
2712 #endif
2713      }
2714
2715    /* Recalc if needed the map center && light source */
2716    if (ep->param1.description->map.on)
2717      {
2718         center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.rot.id_center, &statec1);
2719         light[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_light, &statel1);
2720
2721         if (chosen_desc->map.persp_on)
2722           {
2723              persp[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_persp, &statep1);
2724           }
2725      }
2726
2727    if (ep->param2 && ep->param2->description->map.on)
2728      {
2729         center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.rot.id_center, &statec2);
2730         light[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_light, &statel2);
2731
2732         if (chosen_desc->map.persp_on)
2733           {
2734              persp[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_persp, &statep2);
2735           }
2736      }
2737
2738 #ifndef EDJE_CALC_CACHE
2739    p1 = &lp1;
2740 #else
2741    p1 = &ep->param1.p;
2742 #endif
2743
2744    if (ep->param1.description)
2745      {
2746 #ifdef EDJE_CALC_CACHE
2747         if (ed->all_part_change ||
2748             ep->invalidate ||
2749             state1 >= ep->param1.state ||
2750             statec >= ep->param1.state ||
2751             statec1 >= ep->param1.state ||
2752             statel1 >= ep->param1.state ||
2753             statep1 >= ep->param1.state ||
2754             proxy_invalidate ||
2755             state ||
2756             ((ep->part->type == EDJE_PART_TYPE_TEXT || ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && ed->text_part_change))
2757 #endif
2758           {
2759              _edje_part_recalc_single(ed, ep, ep->param1.description, chosen_desc, center[0], light[0], persp[0],
2760                                       ep->param1.rel1_to_x, ep->param1.rel1_to_y, ep->param1.rel2_to_x, ep->param1.rel2_to_y,
2761                                       confine_to,
2762                                       p1, pos);
2763 #ifdef EDJE_CALC_CACHE
2764              if (flags == FLAG_XY)
2765                ep->param1.state = ed->state;
2766 #endif
2767           }
2768      }
2769    if (ep->param2)
2770      {
2771         int beginning_pos, part_type;
2772         Edje_Calc_Params *p2, *p3;
2773
2774         if (ep->current)
2775           {
2776              /* FIXME: except for text, we don't need in that case to recalc p1 at all*/
2777              memcpy(p1, ep->current, sizeof (Edje_Calc_Params));
2778              p1->x += ed->x;
2779              p1->y += ed->y;
2780              p1->map.center.x += ed->x;
2781              p1->map.center.y += ed->y;
2782              p1->map.light.x += ed->x;
2783              p1->map.light.y += ed->y;
2784              p1->map.persp.x += ed->x;
2785              p1->map.persp.y += ed->y;
2786           }
2787
2788         p3 = &lp3;
2789
2790 #ifndef EDJE_CALC_CACHE
2791         p2 = &lp2;
2792 #else
2793         p2 = &ep->param2->p;
2794
2795         if (ed->all_part_change ||
2796             ep->invalidate ||
2797             state2 >= ep->param2->state ||
2798             statec >= ep->param2->state ||
2799             statec2 >= ep->param2->state ||
2800             statel2 >= ep->param2->state ||
2801             statep2 >= ep->param2->state ||
2802             proxy_invalidate ||
2803             state ||
2804             ((ep->part->type == EDJE_PART_TYPE_TEXT || ep->part->type == EDJE_PART_TYPE_TEXTBLOCK) && ed->text_part_change))
2805 #endif
2806           {
2807              _edje_part_recalc_single(ed, ep, ep->param2->description,
2808                                       chosen_desc,
2809                                       center[1], light[1], persp[1],
2810                                       ep->param2->rel1_to_x,
2811                                       ep->param2->rel1_to_y,
2812                                       ep->param2->rel2_to_x,
2813                                       ep->param2->rel2_to_y,
2814                                       confine_to,
2815                                       p2, pos);
2816 #ifdef EDJE_CALC_CACHE
2817              if (flags == FLAG_XY)
2818                ep->param2->state = ed->state;
2819 #endif
2820           }
2821
2822         pos2 = pos;
2823         if (pos2 < ZERO) pos2 = ZERO;
2824         else if (pos2 > FROM_INT(1)) pos2 = FROM_INT(1);
2825         beginning_pos = (pos < FROM_DOUBLE(0.5));
2826         part_type = ep->part->type;
2827
2828         /* visible is special */
2829         if ((p1->visible) && (!p2->visible))
2830           p3->visible = (pos != FROM_INT(1));
2831         else if ((!p1->visible) && (p2->visible))
2832           p3->visible = (pos != ZERO);
2833         else
2834           p3->visible = p1->visible;
2835
2836         p3->smooth = (beginning_pos) ? p1->smooth : p2->smooth;
2837
2838         /* FIXME: do x and y separately base on flag */
2839 #define FINTP(_x1, _x2, _p)                     \
2840         (((_x1) == (_x2))                       \
2841          ? FROM_INT((_x1))                      \
2842          : ADD(FROM_INT(_x1),                   \
2843                SCALE((_p), (_x2) - (_x1))))
2844
2845 #define FFP(_x1, _x2, _p)                       \
2846         (((_x1) == (_x2))                       \
2847          ? (_x1)                                \
2848          : ADD(_x1, MUL(_p, SUB(_x2, _x1))));
2849
2850 #define INTP(_x1, _x2, _p) TO_INT(FINTP(_x1, _x2, _p))
2851
2852         p3->x = INTP(p1->x, p2->x, pos);
2853         p3->y = INTP(p1->y, p2->y, pos);
2854         p3->w = INTP(p1->w, p2->w, pos);
2855         p3->h = INTP(p1->h, p2->h, pos);
2856
2857         p3->req.x = INTP(p1->req.x, p2->req.x, pos);
2858         p3->req.y = INTP(p1->req.y, p2->req.y, pos);
2859         p3->req.w = INTP(p1->req.w, p2->req.w, pos);
2860         p3->req.h = INTP(p1->req.h, p2->req.h, pos);
2861
2862         if (ep->part->dragable.x)
2863           {
2864              p3->req_drag.x = INTP(p1->req_drag.x, p2->req_drag.x, pos);
2865              p3->req_drag.w = INTP(p1->req_drag.w, p2->req_drag.w, pos);
2866           }
2867         if (ep->part->dragable.y)
2868           {
2869              p3->req_drag.y = INTP(p1->req_drag.y, p2->req_drag.y, pos);
2870              p3->req_drag.h = INTP(p1->req_drag.h, p2->req_drag.h, pos);
2871           }
2872
2873         p3->color.r = INTP(p1->color.r, p2->color.r, pos2);
2874         p3->color.g = INTP(p1->color.g, p2->color.g, pos2);
2875         p3->color.b = INTP(p1->color.b, p2->color.b, pos2);
2876         p3->color.a = INTP(p1->color.a, p2->color.a, pos2);
2877
2878         switch (part_type)
2879           {
2880            case EDJE_PART_TYPE_IMAGE:
2881               p3->type.common.spec.image.l = INTP(p1->type.common.spec.image.l, p2->type.common.spec.image.l, pos);
2882               p3->type.common.spec.image.r = INTP(p1->type.common.spec.image.r, p2->type.common.spec.image.r, pos);
2883               p3->type.common.spec.image.t = INTP(p1->type.common.spec.image.t, p2->type.common.spec.image.t, pos);
2884               p3->type.common.spec.image.b = INTP(p1->type.common.spec.image.b, p2->type.common.spec.image.b, pos);
2885               p3->type.common.spec.image.border_scale_by = INTP(p1->type.common.spec.image.border_scale_by, p2->type.common.spec.image.border_scale_by, pos);
2886            case EDJE_PART_TYPE_PROXY:
2887               p3->type.common.fill.x = INTP(p1->type.common.fill.x, p2->type.common.fill.x, pos);
2888               p3->type.common.fill.y = INTP(p1->type.common.fill.y, p2->type.common.fill.y, pos);
2889               p3->type.common.fill.w = INTP(p1->type.common.fill.w, p2->type.common.fill.w, pos);
2890               p3->type.common.fill.h = INTP(p1->type.common.fill.h, p2->type.common.fill.h, pos);
2891               break;
2892            case EDJE_PART_TYPE_TEXT:
2893               p3->type.text.size = INTP(p1->type.text.size, p2->type.text.size, pos);
2894            case EDJE_PART_TYPE_TEXTBLOCK:
2895               p3->type.text.color2.r = INTP(p1->type.text.color2.r, p2->type.text.color2.r, pos2);
2896               p3->type.text.color2.g = INTP(p1->type.text.color2.g, p2->type.text.color2.g, pos2);
2897               p3->type.text.color2.b = INTP(p1->type.text.color2.b, p2->type.text.color2.b, pos2);
2898               p3->type.text.color2.a = INTP(p1->type.text.color2.a, p2->type.text.color2.a, pos2);
2899
2900               p3->type.text.color3.r = INTP(p1->type.text.color3.r, p2->type.text.color3.r, pos2);
2901               p3->type.text.color3.g = INTP(p1->type.text.color3.g, p2->type.text.color3.g, pos2);
2902               p3->type.text.color3.b = INTP(p1->type.text.color3.b, p2->type.text.color3.b, pos2);
2903               p3->type.text.color3.a = INTP(p1->type.text.color3.a, p2->type.text.color3.a, pos2);
2904
2905               p3->type.text.align.x = FFP(p1->type.text.align.x, p2->type.text.align.x, pos);
2906               p3->type.text.align.y = FFP(p1->type.text.align.y, p2->type.text.align.y, pos);
2907               p3->type.text.elipsis = TO_DOUBLE(FINTP(p1->type.text.elipsis, p2->type.text.elipsis, pos2));
2908               break;
2909           }
2910
2911         p3->mapped = p1->mapped;
2912         p3->persp_on = p3->mapped ? p1->persp_on | p2->persp_on : 0;
2913         p3->lighted = p3->mapped ? p1->lighted | p2->lighted : 0;
2914         if (p1->mapped)
2915           {
2916              p3->map.center.x = INTP(p1->map.center.x, p2->map.center.x, pos);
2917              p3->map.center.y = INTP(p1->map.center.y, p2->map.center.y, pos);
2918              p3->map.center.z = INTP(p1->map.center.z, p2->map.center.z, pos);
2919              p3->map.rotation.x = FFP(p1->map.rotation.x, p2->map.rotation.x, pos);
2920              p3->map.rotation.y = FFP(p1->map.rotation.y, p2->map.rotation.y, pos);
2921              p3->map.rotation.z = FFP(p1->map.rotation.z, p2->map.rotation.z, pos);
2922
2923 #define MIX(P1, P2, P3, pos, info)              \
2924              P3->info = P1->info + TO_INT(SCALE(pos, P2->info - P1->info));
2925
2926              if (p1->lighted && p2->lighted)
2927                {
2928                   MIX(p1, p2, p3, pos, map.light.x);
2929                   MIX(p1, p2, p3, pos, map.light.y);
2930                   MIX(p1, p2, p3, pos, map.light.z);
2931                   MIX(p1, p2, p3, pos, map.light.r);
2932                   MIX(p1, p2, p3, pos, map.light.g);
2933                   MIX(p1, p2, p3, pos, map.light.b);
2934                   MIX(p1, p2, p3, pos, map.light.ar);
2935                   MIX(p1, p2, p3, pos, map.light.ag);
2936                   MIX(p1, p2, p3, pos, map.light.ab);
2937                }
2938              else if (p1->lighted)
2939                {
2940                   memcpy(&p3->map.light, &p1->map.light, sizeof (p1->map.light));
2941                }
2942              else if (p2->lighted)
2943                {
2944                   memcpy(&p3->map.light, &p2->map.light, sizeof (p2->map.light));
2945                }
2946
2947              if (p1->persp_on && p2->persp_on)
2948                {
2949                   MIX(p1, p2, p3, pos, map.persp.x);
2950                   MIX(p1, p2, p3, pos, map.persp.y);
2951                   MIX(p1, p2, p3, pos, map.persp.z);
2952                   MIX(p1, p2, p3, pos, map.persp.focal);
2953                }
2954              else if (p1->persp_on)
2955                {
2956                   memcpy(&p3->map.persp, &p1->map.persp, sizeof (p1->map.persp));
2957                }
2958              else if (p2->persp_on)
2959                {
2960                   memcpy(&p3->map.persp, &p2->map.persp, sizeof (p2->map.persp));
2961                }
2962           }
2963
2964         pf = p3;
2965      }
2966    else
2967      {
2968         pf = p1;
2969      }
2970
2971    if (!pf->persp_on && chosen_desc->map.persp_on)
2972      {
2973         if (ed->persp)
2974           {
2975              pf->map.persp.x = ed->persp->px;
2976              pf->map.persp.y = ed->persp->py;
2977              pf->map.persp.z = ed->persp->z0;
2978              pf->map.persp.focal = ed->persp->foc;
2979           }
2980         else
2981           {
2982              const Edje_Perspective *ps;
2983
2984              // fixme: a tad inefficient as this is a has lookup
2985              ps = edje_object_perspective_get(ed->obj);
2986              if (!ps)
2987                ps = edje_evas_global_perspective_get(evas_object_evas_get(ed->obj));
2988              if (ps)
2989                {
2990                   pf->map.persp.x = ps->px;
2991                   pf->map.persp.y = ps->py;
2992                   pf->map.persp.z = ps->z0;
2993                   pf->map.persp.focal = ps->foc;
2994                }
2995              else
2996                {
2997                   pf->map.persp.x = ed->x + (ed->w / 2);
2998                   pf->map.persp.y = ed->y + (ed->h / 2);
2999                   pf->map.persp.z = 0;
3000                   pf->map.persp.focal = 1000;
3001                }
3002           }
3003      }
3004
3005    if (state)
3006      {
3007         memcpy(state, pf, sizeof (Edje_Calc_Params));
3008      }
3009
3010    ep->req = pf->req;
3011
3012    if (ep->drag && ep->drag->need_reset)
3013      {
3014         FLOAT_T dx, dy;
3015
3016         dx = ZERO;
3017         dy = ZERO;
3018         _edje_part_dragable_calc(ed, ep, &dx, &dy);
3019         ep->drag->x = dx;
3020         ep->drag->y = dy;
3021         ep->drag->tmp.x = 0;
3022         ep->drag->tmp.y = 0;
3023         ep->drag->need_reset = 0;
3024      }
3025    if (!ed->calc_only)
3026      {
3027         Evas_Object *mo;
3028
3029         /* Common move, resize and color_set for all part. */
3030         switch (ep->part->type)
3031           {
3032            case EDJE_PART_TYPE_IMAGE:
3033                 {
3034                    Edje_Part_Description_Image *img_desc = (Edje_Part_Description_Image*) chosen_desc;
3035
3036                    evas_object_image_scale_hint_set(ep->object,
3037                                                     img_desc->image.scale_hint);
3038                 }
3039            case EDJE_PART_TYPE_PROXY:
3040            case EDJE_PART_TYPE_RECTANGLE:
3041            case EDJE_PART_TYPE_TEXTBLOCK:
3042            case EDJE_PART_TYPE_BOX:
3043            case EDJE_PART_TYPE_TABLE:
3044               evas_object_color_set(ep->object,
3045                                     (pf->color.r * pf->color.a) / 255,
3046                                     (pf->color.g * pf->color.a) / 255,
3047                                     (pf->color.b * pf->color.a) / 255,
3048                                     pf->color.a);
3049               if (!pf->visible)
3050                 {
3051                    evas_object_hide(ep->object);
3052                    break;
3053                 }
3054               evas_object_show(ep->object);
3055               /* move and resize are needed for all previous object => no break here. */
3056            case EDJE_PART_TYPE_SWALLOW:
3057            case EDJE_PART_TYPE_GROUP:
3058            case EDJE_PART_TYPE_EXTERNAL:
3059               /* visibility and color have no meaning on SWALLOW and GROUP part. */
3060               evas_object_move(ep->object, ed->x + pf->x, ed->y + pf->y);
3061               evas_object_resize(ep->object, pf->w, pf->h);
3062              
3063               if (ep->nested_smart)
3064                 {  /* Move, Resize all nested parts */
3065                    /* Not really needed but will improve the bounding box evaluation done by Evas */
3066                    evas_object_move(ep->nested_smart,
3067                                     ed->x + pf->x, ed->y + pf->y);
3068                    evas_object_resize(ep->nested_smart, pf->w, pf->h);
3069                 }
3070               if (ep->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
3071                 _edje_entry_real_part_configure(ep);
3072               break;
3073            case EDJE_PART_TYPE_TEXT:
3074               /* This is correctly handle in _edje_text_recalc_apply at the moment. */
3075               break;
3076            case EDJE_PART_TYPE_GRADIENT:
3077               /* FIXME: definitivly remove this code when we switch to new format. */
3078               abort();
3079               break;
3080            case EDJE_PART_TYPE_SPACER:
3081               /* We really should do nothing on SPACER part */
3082               break;
3083           }
3084
3085         /* Some object need special recalc. */
3086         switch (ep->part->type)
3087           {
3088            case EDJE_PART_TYPE_TEXT:
3089               _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc);
3090               break;
3091            case EDJE_PART_TYPE_PROXY:
3092               _edje_proxy_recalc_apply(ed, ep, pf, (Edje_Part_Description_Proxy*) chosen_desc, pos);
3093               break;
3094            case EDJE_PART_TYPE_IMAGE:
3095               _edje_image_recalc_apply(ed, ep, pf, (Edje_Part_Description_Image*) chosen_desc, pos);
3096               break;
3097            case EDJE_PART_TYPE_BOX:
3098               _edje_box_recalc_apply(ed, ep, pf, (Edje_Part_Description_Box*) chosen_desc);
3099               break;
3100            case EDJE_PART_TYPE_TABLE:
3101               _edje_table_recalc_apply(ed, ep, pf, (Edje_Part_Description_Table*) chosen_desc);
3102               break;
3103            case EDJE_PART_TYPE_TEXTBLOCK:
3104               _edje_textblock_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc);
3105               break;
3106            case EDJE_PART_TYPE_EXTERNAL:
3107            case EDJE_PART_TYPE_RECTANGLE:
3108            case EDJE_PART_TYPE_SWALLOW:
3109            case EDJE_PART_TYPE_GROUP:
3110               /* Nothing special to do for this type of object. */
3111               break;
3112            case EDJE_PART_TYPE_GRADIENT:
3113               /* FIXME: definitivly remove this code when we switch to new format. */
3114               abort();
3115               break;
3116            case EDJE_PART_TYPE_SPACER:
3117               /* We really should do nothing on SPACER part */
3118               break;
3119           }
3120
3121         if (((ep->type == EDJE_RP_TYPE_SWALLOW) &&
3122              (ep->typedata.swallow)) &&
3123             (ep->typedata.swallow->swallowed_object))
3124           {
3125              //// the below really is wrong - swallow color shouldn't affect swallowed object
3126              //// color - the edje color as a WHOLE should though - and that should be
3127              //// done via the clipper anyway. this created bugs when objects had their
3128              //// colro set and were swallowed - then had their color changed.
3129              //      evas_object_color_set(ep->typedata.swallow->swallowed_object,
3130              //                            (pf->color.r * pf->color.a) / 255,
3131              //                            (pf->color.g * pf->color.a) / 255,
3132              //                            (pf->color.b * pf->color.a) / 255,
3133              //                            pf->color.a);
3134              if (pf->visible)
3135                {
3136                   evas_object_move(ep->typedata.swallow->swallowed_object, ed->x + pf->x, ed->y + pf->y);
3137                   evas_object_resize(ep->typedata.swallow->swallowed_object, pf->w, pf->h);
3138                   evas_object_show(ep->typedata.swallow->swallowed_object);
3139                }
3140              else evas_object_hide(ep->typedata.swallow->swallowed_object);
3141              mo = ep->typedata.swallow->swallowed_object;
3142           }
3143         else mo = ep->object;
3144         if (chosen_desc->map.on && ep->part->type != EDJE_PART_TYPE_SPACER)
3145           {
3146              static Evas_Map *map = NULL;
3147
3148              ed->have_mapped_part = EINA_TRUE;
3149              // create map and populate with part geometry
3150              if (!map) map = evas_map_new(4);
3151              evas_map_util_points_populate_from_object(map, ep->object);
3152              if (ep->part->type == EDJE_PART_TYPE_IMAGE ||
3153                  ((ep->part->type == EDJE_PART_TYPE_SWALLOW) &&
3154                   (!strcmp(evas_object_type_get(mo), "image")))
3155                 )
3156                {
3157                   int iw = 1, ih = 1;
3158
3159                   evas_object_image_size_get(mo, &iw, &ih);
3160                   evas_map_point_image_uv_set(map, 0, 0.0, 0.0);
3161                   evas_map_point_image_uv_set(map, 1, iw , 0.0);
3162                   evas_map_point_image_uv_set(map, 2, iw , ih );
3163                   evas_map_point_image_uv_set(map, 3, 0.0, ih );
3164                }
3165              evas_map_util_3d_rotate(map,
3166                                      TO_DOUBLE(pf->map.rotation.x),
3167                                      TO_DOUBLE(pf->map.rotation.y),
3168                                      TO_DOUBLE(pf->map.rotation.z),
3169                                      pf->map.center.x, pf->map.center.y,
3170                                      pf->map.center.z);
3171
3172              // calculate light color & position etc. if there is one
3173              if (pf->lighted)
3174                {
3175                   evas_map_util_3d_lighting(map,
3176                                             pf->map.light.x, pf->map.light.y, pf->map.light.z,
3177                                             pf->map.light.r, pf->map.light.g, pf->map.light.b,
3178                                             pf->map.light.ar, pf->map.light.ag, pf->map.light.ab);
3179                }
3180
3181              // calculate perspective point
3182              if (chosen_desc->map.persp_on)
3183                {
3184                   evas_map_util_3d_perspective(map,
3185                                                pf->map.persp.x, pf->map.persp.y, pf->map.persp.z,
3186                                                pf->map.persp.focal);
3187                }
3188
3189              // handle backface culling (object is facing away from view
3190              if (chosen_desc->map.backcull)
3191                {
3192                   if (pf->visible)
3193                     {
3194                        if (evas_map_util_clockwise_get(map))
3195                          evas_object_show(mo);
3196                        else evas_object_hide(mo);
3197                     }
3198                }
3199
3200              // handle smooth
3201              if (chosen_desc->map.smooth) evas_map_smooth_set(map, 1);
3202              else evas_map_smooth_set(map, 0);
3203              // handle alpha
3204              if (chosen_desc->map.alpha) evas_map_alpha_set(map, 1);
3205              else evas_map_alpha_set(map, 0);
3206
3207
3208              if (ep->nested_smart)
3209                {  /* Apply map to smart obj holding nested parts */
3210                   evas_object_map_set(ep->nested_smart, map);
3211                   evas_object_map_enable_set(ep->nested_smart, 1);
3212                }
3213              else
3214                {
3215                   evas_object_map_set(mo, map);
3216                   evas_object_map_enable_set(mo, 1);
3217                }
3218           }
3219         else
3220           {
3221              if (ep->nested_smart)
3222                {  /* Cancel map of smart obj holding nested parts */
3223                   evas_object_map_enable_set(ep->nested_smart, 0);
3224                   evas_object_map_set(ep->nested_smart, NULL);
3225                }
3226              else
3227                {
3228                   evas_object_map_enable_set(mo, 0);
3229                   evas_object_map_set(mo, NULL);
3230                }
3231           }
3232      }
3233
3234    ep->x = pf->x;
3235    ep->y = pf->y;
3236    ep->w = pf->w;
3237    ep->h = pf->h;
3238
3239    ep->calculated |= flags;
3240    ep->calculating = FLAG_NONE;
3241
3242 #ifdef EDJE_CALC_CACHE
3243    if (ep->calculated == FLAG_XY)
3244      {
3245         ep->state = ed->state;
3246         ep->invalidate = 0;
3247      }
3248 #endif
3249 }