1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 # include <stdlib.h>
11 # endif
12 #endif
13
14 #include <string.h>
15 #include <limits.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <libgen.h>
19
20 #include <Ecore_Evas.h>
21
22 #include "edje_cc.h"
23 #include "edje_convert.h"
24 #include "edje_multisense_convert.h"
25
26 #include <lua.h>
27 #include <lauxlib.h>
28
29 typedef struct _External_Lookup External_Lookup;
30 typedef struct _Part_Lookup Part_Lookup;
31 typedef struct _Part_Lookup_Key Part_Lookup_Key;
32 typedef struct _Program_Lookup Program_Lookup;
33 typedef struct _Group_Lookup Group_Lookup;
34 typedef struct _Image_Lookup Image_Lookup;
35 typedef struct _Code_Lookup Code_Lookup;
36
37 struct _External_Lookup
38 {
39 char *name;
40 };
41
42 struct _Part_Lookup_Key
43 {
44 Edje_Part_Collection *pc;
45
46 union
47 {
48 int *dest;
49 struct
50 {
51 unsigned char **base;
52 int offset;
53 } reallocated;
54 } mem;
55 char **dest2;
56
57 Eina_Bool stable : 1;
58 };
59
60 struct _Part_Lookup
61 {
62 Part_Lookup_Key key;
63 char *name;
64 };
65
66 struct _Program_Lookup
67 {
68 Edje_Part_Collection *pc;
69
70 union
71 {
72 char *name;
73 Edje_Program *ep;
74 } u;
75
76 int *dest;
77
78 Eina_Bool anonymous : 1;
79 };
80
81 struct _Group_Lookup
82 {
83 char *name;
84 Edje_Part *part;
85 };
86
87 struct _String_Lookup
88 {
89 char *name;
90 int *dest;
91 };
92
93 struct _Image_Lookup
94 {
95 char *name;
96 int *dest;
97 Eina_Bool *set;
98 };
99
100 struct _Code_Lookup
101 {
102 char *ptr;
103 int len;
104 int val;
105 Eina_Bool set;
106 };
107
108 typedef struct _Script_Lua_Writer Script_Lua_Writer;
109
110 struct _Script_Lua_Writer
111 {
112 char *buf;
113 int size;
114 };
115
116 typedef struct _Script_Write Script_Write;
117 typedef struct _Head_Write Head_Write;
118 typedef struct _Fonts_Write Fonts_Write;
119 typedef struct _Image_Write Image_Write;
120 typedef struct _Sound_Write Sound_Write;
121 typedef struct _Mo_Write Mo_Write;
122 typedef struct _Vibration_Write Vibration_Write;
123 typedef struct _Group_Write Group_Write;
124 typedef struct _License_Write License_Write;
125
126 struct _Script_Write
127 {
128 Eet_File *ef;
129 Code *cd;
130 int i;
131 Ecore_Exe *exe;
132 int tmpn_fd;
133 Eina_Tmpstr *tmpn;
134 Eina_Tmpstr *tmpo;
135 char *errstr;
136 };
137
138 struct _Head_Write
139 {
140 Eet_File *ef;
141 char *errstr;
142 };
143
144 struct _Fonts_Write
145 {
146 Eet_File *ef;
147 Edje_Font *fn;
148 char *errstr;
149 };
150
151 struct _Image_Write
152 {
153 Eet_File *ef;
154 Edje_Image_Directory_Entry *img;
155 Evas_Object *im;
156 Emile_Image_Property prop;
157 Eina_File *f;
158 Emile_Image *emi;
159 int w, h;
160 int alpha;
161 unsigned int *data;
162 char *path;
163 char *errstr;
164 };
165
166 struct _Sound_Write
167 {
168 Eet_File *ef;
169 Edje_Sound_Sample *sample;
170 int i;
171 };
172
173 struct _Mo_Write
174 {
175 Eet_File *ef;
176 Edje_Mo *mo_entry;
177 char *mo_path;
178 Ecore_Exe *exe;
179 char *errstr;
180 };
181
182 struct _Vibration_Write
183 {
184 Eet_File *ef;
185 Edje_Vibration_Sample *sample;
186 int i;
187 };
188
189 struct _Group_Write
190 {
191 Eet_File *ef;
192 Edje_Part_Collection *pc;
193 char *errstr;
194 };
195
196 struct _License_Write
197 {
198 Eet_File *ef;
199 const char *file;
200 Eina_Bool master;
201 };
202
203 struct _Image_Unused_Ids
204 {
205 int old_id;
206 int new_id;
207 };
208
209 typedef struct _Image_Unused_Ids Image_Unused_Ids;
210
211 static int pending_threads = 0;
212 static int pending_image_threads = 0;
213
214 static void data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char *ptr, int len));
215
216 extern Eina_List *po_files;
217
218 Edje_File *edje_file = NULL;
219 Eina_List *edje_collections = NULL;
220 Eina_Hash *edje_collections_lookup = NULL;
221 Eina_List *externals = NULL;
222 Eina_List *fonts = NULL;
223 Eina_List *codes = NULL;
224 Eina_List *code_lookups = NULL;
225 Eina_List *aliases = NULL;
226 Eina_List *color_tree_root = NULL;
227
228 static Eet_Data_Descriptor *edd_edje_file = NULL;
229 static Eet_Data_Descriptor *edd_edje_part_collection = NULL;
230
231 static Eina_List *program_lookups = NULL;
232 static Eina_List *group_lookups = NULL;
233 static Eina_List *face_group_lookups = NULL;
234 static Eina_List *image_lookups = NULL;
235
236 static Eina_Hash *part_dest_lookup = NULL;
237 static Eina_Hash *part_pc_dest_lookup = NULL;
238 static Eina_Hash *groups_sourced = NULL;
239
240 static Eet_File *cur_ef;
241 static int image_num;
242 static Ecore_Evas *buffer_ee;
243 static int cur_image_entry;
244
245 static void data_write_images(void);
246
247 void
error_and_abort(Eet_File * ef EINA_UNUSED,const char * fmt,...)248 error_and_abort(Eet_File *ef EINA_UNUSED, const char *fmt, ...)
249 {
250 va_list ap;
251
252 va_start(ap, fmt);
253 eina_log_vprint(_edje_cc_log_dom, EINA_LOG_LEVEL_CRITICAL,
254 "unknown", "unknown", 0, fmt, ap);
255 va_end(ap);
256 unlink(file_out);
257 if (watchfile) unlink(watchfile);
258 exit(-1);
259 }
260
261 static void
thread_end(Eina_Bool img)262 thread_end(Eina_Bool img)
263 {
264 if (img)
265 pending_image_threads--;
266 else
267 pending_threads--;
268 if (threads)
269 {
270 if ((pending_image_threads + pending_threads) < (int)max_open_files - 2)
271 data_write_images();
272 }
273 if (pending_threads + pending_image_threads <= 0) ecore_main_loop_quit();
274 }
275
276 static unsigned int
_part_lookup_key_length(const void * key EINA_UNUSED)277 _part_lookup_key_length(const void *key EINA_UNUSED)
278 {
279 return sizeof (Part_Lookup_Key);
280 }
281
282 static int
_part_lookup_key_pc_cmp(const void * key1,int key1_length EINA_UNUSED,const void * key2,int key2_length EINA_UNUSED)283 _part_lookup_key_pc_cmp(const void *key1, int key1_length EINA_UNUSED,
284 const void *key2, int key2_length EINA_UNUSED)
285 {
286 const Part_Lookup_Key *a = key1;
287 const Part_Lookup_Key *b = key2;
288 uintptr_t delta;
289
290 delta = a->pc - b->pc;
291 if (delta) return delta;
292
293 if (a->stable) return a->mem.dest - b->mem.dest;
294
295 delta = a->mem.reallocated.base - b->mem.reallocated.base;
296 if (delta) return delta;
297 return a->mem.reallocated.offset - b->mem.reallocated.offset;
298 }
299
300 static int
_part_lookup_key_pc_hash(const void * key,int key_length EINA_UNUSED)301 _part_lookup_key_pc_hash(const void *key, int key_length EINA_UNUSED)
302 {
303 const Part_Lookup_Key *a = key;
304
305 if (a->stable)
306 {
307 #ifdef EFL64
308 return eina_hash_int64((unsigned long long int *)&a->pc, sizeof (void *)) ^
309 eina_hash_int64((unsigned long long int *)&a->mem.dest, sizeof (void *));
310 #else
311 return eina_hash_int32((uintptr_t *)&a->pc, sizeof (void *)) ^
312 eina_hash_int32((uintptr_t *)&a->mem.dest, sizeof (void *));
313 #endif
314 }
315 else
316 {
317 #ifdef EFL64
318 return eina_hash_int64((unsigned long long int *)&a->pc, sizeof (void *)) ^
319 eina_hash_int64((unsigned long long int *)&a->mem.reallocated.base, sizeof (void *)) ^
320 eina_hash_int32((unsigned int *)&a->mem.reallocated.offset, sizeof (int));
321 #else
322 return eina_hash_int32((uintptr_t *)&a->pc, sizeof (void *)) ^
323 eina_hash_int32((uintptr_t *)&a->mem.reallocated.base, sizeof (void *)) ^
324 eina_hash_int32((unsigned int *)&a->mem.reallocated.offset, sizeof (int));
325 #endif
326 }
327 }
328
329 static int
_part_lookup_key_cmp(const void * key1,int key1_length EINA_UNUSED,const void * key2,int key2_length EINA_UNUSED)330 _part_lookup_key_cmp(const void *key1, int key1_length EINA_UNUSED,
331 const void *key2, int key2_length EINA_UNUSED)
332 {
333 const Part_Lookup_Key *a = key1;
334 const Part_Lookup_Key *b = key2;
335 uintptr_t delta;
336
337 if (a->stable) return a->mem.dest - b->mem.dest;
338
339 delta = a->mem.reallocated.base - b->mem.reallocated.base;
340 if (delta) return delta;
341 return a->mem.reallocated.offset - b->mem.reallocated.offset;
342 }
343
344 static int
_part_lookup_key_hash(const void * key,int key_length EINA_UNUSED)345 _part_lookup_key_hash(const void *key, int key_length EINA_UNUSED)
346 {
347 const Part_Lookup_Key *a = key;
348
349 if (a->stable)
350 {
351 #ifdef EFL64
352 return eina_hash_int64((unsigned long long int *)&a->mem.dest, sizeof (void *));
353 #else
354 return eina_hash_int32((uintptr_t *)&a->mem.dest, sizeof (void *));
355 #endif
356 }
357 else
358 {
359 #ifdef EFL64
360 return eina_hash_int64((unsigned long long int *)&a->mem.reallocated.base, sizeof (void *)) ^
361 eina_hash_int32((unsigned int *)&a->mem.reallocated.offset, sizeof (int));
362 #else
363 return eina_hash_int32((uintptr_t *)&a->mem.reallocated.base, sizeof (void *)) ^
364 eina_hash_int32((unsigned int *)&a->mem.reallocated.offset, sizeof (int));
365 #endif
366 }
367 }
368
369 static void
data_part_lookup_free(Part_Lookup * pl)370 data_part_lookup_free(Part_Lookup *pl)
371 {
372 free(pl->name);
373 free(pl);
374 }
375
376 static void
list_free(void * list)377 list_free(void *list)
378 {
379 eina_list_free(list);
380 }
381
382 void
data_setup(void)383 data_setup(void)
384 {
385 edd_edje_file = _edje_edd_edje_file;
386 edd_edje_part_collection = _edje_edd_edje_part_collection;
387
388 part_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_part_lookup_key_length),
389 EINA_KEY_CMP(_part_lookup_key_cmp),
390 EINA_KEY_HASH(_part_lookup_key_hash),
391 EINA_FREE_CB(list_free),
392 8);
393 part_pc_dest_lookup = eina_hash_new(EINA_KEY_LENGTH(_part_lookup_key_length),
394 EINA_KEY_CMP(_part_lookup_key_pc_cmp),
395 EINA_KEY_HASH(_part_lookup_key_pc_hash),
396 EINA_FREE_CB(data_part_lookup_free),
397 8);
398 }
399
400 static void
check_image_part_desc(Edje_Part_Collection * pc,Edje_Part * ep,Edje_Part_Description_Image * epd,Eet_File * ef)401 check_image_part_desc(Edje_Part_Collection *pc, Edje_Part *ep,
402 Edje_Part_Description_Image *epd, Eet_File *ef)
403 {
404 unsigned int i;
405 Edje_Part_Collection_Parser *pcp = (Edje_Part_Collection_Parser *)pc;
406
407 if (pcp->inherit_only) return;
408
409 if (epd->image.id == -1 && epd->common.visible)
410 WRN("Collection %s(%i): image attributes missing for "
411 "part \"%s\", description \"%s\" %f",
412 pc->part, pc->id, ep->name, epd->common.state.name, epd->common.state.value);
413
414 for (i = 0; i < epd->image.tweens_count; ++i)
415 {
416 if (epd->image.tweens[i]->id == -1)
417 error_and_abort(ef, "Collection %i: tween image id missing for "
418 "part \"%s\", description \"%s\" %f",
419 pc->id, ep->name, epd->common.state.name, epd->common.state.value);
420 }
421 }
422
423 static Edje_Part_Collection *
_source_group_find(const char * source)424 _source_group_find(const char *source)
425 {
426 Edje_Part_Collection *pc2;
427 Eina_List *l;
428 if (!source) return NULL;
429 EINA_LIST_FOREACH(edje_collections, l, pc2)
430 {
431 if (!strcmp(pc2->part, source))
432 return pc2;
433 }
434 return NULL;
435 }
436
437 static Edje_Part *
_aliased_text_part_find(Edje_Part_Collection * pc,int id_source,const char * id_source_part)438 _aliased_text_part_find(Edje_Part_Collection *pc,
439 int id_source, const char *id_source_part)
440 {
441 Edje_Part_Collection *group;
442 unsigned int i;
443
444 if (!pc->parts[id_source]->source)
445 return NULL;
446
447 group = _source_group_find(pc->parts[id_source]->source);
448 if (!group) return NULL;
449
450 for (i = 0; i < group->parts_count; i++)
451 {
452 if (!strcmp(group->parts[i]->name, id_source_part))
453 return group->parts[i];
454 }
455 return NULL;
456 }
457
458 static void
check_text_part_desc(Edje_Part_Collection * pc,Edje_Part * ep,Edje_Part_Description_Text * epd,Eet_File * ef)459 check_text_part_desc(Edje_Part_Collection *pc, Edje_Part *ep,
460 Edje_Part_Description_Text *epd, Eet_File *ef)
461 {
462 Edje_Part *ep2;
463
464 if (epd->text.id_source != -1)
465 {
466 if ((pc->parts[epd->text.id_source]->type == EDJE_PART_TYPE_TEXT) ||
467 (pc->parts[epd->text.id_source]->type == EDJE_PART_TYPE_TEXTBLOCK))
468 return;
469
470 if (epd->text.id_source_part)
471 {
472 ep2 = _aliased_text_part_find(pc, epd->text.id_source, epd->text.id_source_part);
473 if (ep2 && ((ep2->type == EDJE_PART_TYPE_TEXT) ||
474 (ep2->type == EDJE_PART_TYPE_TEXTBLOCK)))
475 return;
476 }
477
478 error_and_abort(ef, "Collection \"%s\" Part \"%s\" Description \"%s\" [%.3f]: "
479 "text.source point to a non TEXT part \"%s\"!",
480 pc->part, ep->name, epd->common.state.name,
481 epd->common.state.value, pc->parts[epd->text.id_source]->name);
482 }
483
484 if (epd->text.id_text_source != -1)
485 {
486 if ((pc->parts[epd->text.id_text_source]->type == EDJE_PART_TYPE_TEXT) ||
487 (pc->parts[epd->text.id_text_source]->type == EDJE_PART_TYPE_TEXTBLOCK))
488 return;
489
490 if (epd->text.id_text_source_part)
491 {
492 ep2 = _aliased_text_part_find(pc, epd->text.id_text_source, epd->text.id_text_source_part);
493 if (ep2 && ((ep2->type == EDJE_PART_TYPE_TEXT) ||
494 (ep2->type == EDJE_PART_TYPE_TEXTBLOCK)))
495 return;
496 }
497
498 error_and_abort(ef, "Collection \"%s\" Part \"%s\" Description \"%s\" [%.3f]: "
499 "text.text_source point to a non TEXT part \"%s\"!",
500 pc->part, ep->name, epd->common.state.name,
501 epd->common.state.value, pc->parts[epd->text.id_text_source]->name);
502 }
503 }
504
505 /* This function check loops between groups.
506 For example:
507 > part in group A. It's source is B.
508 > part in group B. It's source is C.
509 > part in group C. It's source is A <- here is error.
510 It's loop that we need to avoid! */
511 static void
check_source_links(Edje_Part_Collection * pc,Edje_Part * ep,Eet_File * ef,Eina_List * group_path)512 check_source_links(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef, Eina_List *group_path)
513 {
514 unsigned int i;
515 char *data;
516 Edje_Part_Collection *pc_source;
517 Eina_List *l;
518
519 EINA_LIST_FOREACH(edje_collections, l, pc_source)
520 {
521 /* Find sourced group */
522 if (ep->source && pc_source->part && strcmp(ep->source, pc_source->part) == 0)
523 {
524 /* Go through every part to find parts with type GROUP */
525 for (i = 0; i < pc_source->parts_count; ++i)
526 {
527 if ((pc_source->parts[i]->type == EDJE_PART_TYPE_GROUP) &&
528 (pc_source->parts[i]->source))
529 {
530 /* Make sure that this group isn't already in the tree of parents */
531 EINA_LIST_FOREACH(group_path, l, data)
532 {
533 if (data == pc_source->parts[i]->source)
534 {
535 error_and_abort(ef, "Recursive loop group '%s' "
536 "already included inside "
537 "part '%s' of group '%s'",
538 data, pc_source->parts[i]->name,
539 pc->part);
540 }
541 }
542 group_path = eina_list_append(group_path, ep->source);
543 check_source_links(pc, pc_source->parts[i], ef, group_path);
544 }
545 }
546 }
547 }
548 }
549
550 static void
check_packed_items(Edje_Part_Collection * pc,Edje_Part * ep,Eet_File * ef)551 check_packed_items(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
552 {
553 unsigned int i;
554
555 for (i = 0; i < ep->items_count; ++i)
556 {
557 if (ep->items[i]->type == EDJE_PART_TYPE_GROUP && !ep->items[i]->source)
558 error_and_abort(ef, "Collection %i: missing source on packed item "
559 "of type GROUP in part \"%s\"",
560 pc->id, ep->name);
561 if (ep->type == EDJE_PART_TYPE_TABLE && (ep->items[i]->col < 0 || ep->items[i]->row < 0))
562 error_and_abort(ef, "Collection %i: missing col/row on packed item "
563 "for part \"%s\" of type TABLE",
564 pc->id, ep->name);
565 }
566 }
567
568 static void
check_nameless_state(Edje_Part_Collection * pc,Edje_Part * ep,Edje_Part_Description_Common * ed,Eet_File * ef)569 check_nameless_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Description_Common *ed, Eet_File *ef)
570 {
571 Edje_Part_Collection_Directory_Entry *de;
572
573 if (ed->state.name) return;
574
575 de = eina_hash_find(edje_collections_lookup, &pc->id);
576 error_and_abort(ef, "Group '%s': part \"%s\" has description with missing state",
577 de->entry, ep->name);
578 }
579
580 static void
check_state(Edje_Part_Collection * pc,Edje_Part * ep,Edje_Part_Description_Common * ed,Eet_File * ef)581 check_state(Edje_Part_Collection *pc, Edje_Part *ep, Edje_Part_Description_Common *ed, Eet_File *ef)
582 {
583 check_nameless_state(pc, ep, ed, ef);
584 }
585
586 static void
_part_namespace_verify(Edje_Part_Collection * pc,Edje_Part * ep,Eet_File * ef,Eina_Bool ns_required)587 _part_namespace_verify(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef, Eina_Bool ns_required)
588 {
589 char buf[1024], *p;
590 size_t len;
591 Edje_Part_Collection_Directory_Entry *de;
592
593 if (!namespace_verify) return;
594 /* this is from a group used as a source, either GROUP or TEXTBLOCK
595 * namespacing not required
596 */
597 if (eina_hash_find(groups_sourced, pc->part)) return;
598
599 de = eina_hash_find(edje_collections_lookup, &pc->id);
600
601 p = strchr(de->entry, '/');
602 if (!p) return;
603
604 len = p - de->entry;
605 if (eina_strlcpy(buf, de->entry, len + 1) >= sizeof(buf)) return;
606
607 p = strchr(ep->name, '.');
608 /* ignore part types without required namespacing or without '.' in name */
609 if ((!ns_required) && (!p)) return;
610
611 if (strncmp(ep->name, buf, len))
612 error_and_abort(ef, "Part '%s' from group %s is not properly namespaced (should begin with '%s.')!", ep->name, de->entry, buf);
613 }
614
615 static void
check_part(Edje_Part_Collection * pc,Edje_Part * ep,Eet_File * ef)616 check_part(Edje_Part_Collection *pc, Edje_Part *ep, Eet_File *ef)
617 {
618 Edje_Part_Collection_Parser *pcp = (Edje_Part_Collection_Parser*)pc;
619 unsigned int i;
620 Eina_List *group_path = NULL;
621 /* FIXME: check image set and sort them. */
622 if (!ep->default_desc)
623 error_and_abort(ef, "Collection %i: default description missing "
624 "for part \"%s\"", pc->id, ep->name);
625
626 check_state(pc, ep, ep->default_desc, ef);
627 for (i = 0; i < ep->other.desc_count; ++i)
628 check_state(pc, ep, ep->other.desc[i], ef);
629
630 if (ep->type == EDJE_PART_TYPE_IMAGE)
631 {
632 check_image_part_desc(pc, ep, (Edje_Part_Description_Image *)ep->default_desc, ef);
633
634 for (i = 0; i < ep->other.desc_count; ++i)
635 check_image_part_desc(pc, ep, (Edje_Part_Description_Image *)ep->other.desc[i], ef);
636 }
637 else if ((ep->type == EDJE_PART_TYPE_BOX) ||
638 (ep->type == EDJE_PART_TYPE_TABLE))
639 check_packed_items(pc, ep, ef);
640 else if (ep->type == EDJE_PART_TYPE_GROUP)
641 check_source_links(pc, ep, ef, group_path);
642 else if (ep->type == EDJE_PART_TYPE_TEXT)
643 {
644 check_text_part_desc(pc, ep, (Edje_Part_Description_Text *)ep->default_desc, ef);
645
646 for (i = 0; i < ep->other.desc_count; ++i)
647 check_text_part_desc(pc, ep, (Edje_Part_Description_Text *)ep->other.desc[i], ef);
648 }
649
650 if (!pcp->skip_namespace_validation)
651 {
652 switch (ep->type)
653 {
654 case EDJE_PART_TYPE_BOX:
655 case EDJE_PART_TYPE_TABLE:
656 case EDJE_PART_TYPE_SWALLOW:
657 _part_namespace_verify(pc, ep, ef, 1);
658 break;
659 case EDJE_PART_TYPE_TEXT:
660 case EDJE_PART_TYPE_TEXTBLOCK:
661 case EDJE_PART_TYPE_SPACER:
662 _part_namespace_verify(pc, ep, ef, 0);
663 break;
664 default: break;
665 }
666 }
667 }
668
669 static void
_program_signal_namespace_verify(Edje_Part_Collection * pc,Eet_File * ef,const char * sig,const char * src)670 _program_signal_namespace_verify(Edje_Part_Collection *pc, Eet_File *ef, const char *sig, const char *src)
671 {
672 char buf[1024], *p;
673 size_t len;
674 Edje_Part_Collection_Directory_Entry *de;
675
676 if (!namespace_verify) return;
677 /* this is from a group used as a source, either GROUP or TEXTBLOCK
678 * namespacing not required
679 */
680 if (eina_hash_find(groups_sourced, pc->part)) return;
681
682 /* ignore propagation to GROUP parts */
683 if (strchr(sig, ':')) return;
684
685 de = eina_hash_find(edje_collections_lookup, &pc->id);
686
687 p = strchr(de->entry, '/');
688 if (!p) return;
689 len = p - de->entry;
690 if (eina_strlcpy(buf, de->entry, len + 1) >= sizeof(buf)) return;
691
692 if (strncmp(sig, buf, len))
693 error_and_abort(ef, "SIGNAL_EMIT (%s:%s) does not match group namespace (%s)!", sig, src, de->entry);
694 }
695
696 static void
check_program(Edje_Part_Collection * pc,Edje_Program * ep,Eet_File * ef)697 check_program(Edje_Part_Collection *pc, Edje_Program *ep, Eet_File *ef)
698 {
699 Edje_Part_Collection_Parser *pcp = (Edje_Part_Collection_Parser*)pc;
700 switch (ep->action)
701 {
702 case EDJE_ACTION_TYPE_STATE_SET:
703 case EDJE_ACTION_TYPE_ACTION_STOP:
704 case EDJE_ACTION_TYPE_DRAG_VAL_SET:
705 case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
706 case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
707 if (!ep->targets)
708 error_and_abort(ef, "Collection %i: target missing in program "
709 "\"%s\"", pc->id, ep->name);
710 break;
711
712 default:
713 break;
714 }
715 Edje_Program_Target *et;
716 Eina_List *l;
717 unsigned int i = 0;
718
719 if ((!ep->targets) && (ep->action == EDJE_ACTION_TYPE_SIGNAL_EMIT))
720 {
721 if (!pcp->skip_namespace_validation)
722 _program_signal_namespace_verify(pc, ef, ep->state, ep->state2);
723 }
724
725 EINA_LIST_FOREACH(ep->targets, l, et)
726 {
727 Edje_Part *part;
728
729 /*
730 * we are accessing part with an id,
731 * if actions is ACTION_STOP or ACTION_TYPE_SCRIPT, then id is NOT from the parts array.
732 * In order to not crash here, we should continue here.
733 */
734 if (ep->action == EDJE_ACTION_TYPE_ACTION_STOP || ep->action == EDJE_ACTION_TYPE_SCRIPT)
735 continue;
736
737 if (et->id >= (int) pc->parts_count)
738 {
739 ERR("In group '%s' program '%s', target id '%d' greater than possible index '%d'.",
740 pc->part ? pc->part : "", ep->name ? ep->name : "", et->id, (int) pc->parts_count - 1);
741 exit(-1);
742 }
743
744 part = pc->parts[et->id];
745 /* verify existence of description in part */
746 if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
747 {
748 if ((!eina_streq(ep->state, "custom")) &&
749 ((!eina_streq(ep->state, "default")) || (!EINA_DBL_EQ(ep->value, 0.0))))
750 {
751 Edje_Part_Collection_Directory_Entry *de;
752 Eina_Bool found = EINA_FALSE;
753 for (i = 0; i < part->other.desc_count; i++)
754 {
755 Edje_Part_Description_Common *ed = part->other.desc[i];
756 if (eina_streq(ed->state.name, ep->state) && EINA_DBL_EQ(ep->value, ed->state.value))
757 {
758 found = EINA_TRUE;
759 break;
760 }
761 }
762 if (!found)
763 {
764 de = eina_hash_find(edje_collections_lookup, &pc->id);
765 error_and_abort(NULL, "GROUP %s - state '%s:%g' does not exist for part '%s'; set in program '%s'",
766 de->entry, ep->state, ep->value, part->name, ep->name);
767 }
768 }
769 }
770 }
771 }
772
773 /* reset part counters for alias */
774 static void
_alias_clean(Edje_Part_Collection_Directory_Entry * ce)775 _alias_clean(Edje_Part_Collection_Directory_Entry *ce)
776 {
777 if (ce)
778 {
779 ce->count.RECTANGLE = 0;
780 ce->count.TEXT = 0;
781 ce->count.IMAGE = 0;
782 ce->count.SWALLOW = 0;
783 ce->count.TEXTBLOCK = 0;
784 ce->count.GROUP = 0;
785 ce->count.BOX = 0;
786 ce->count.TABLE = 0;
787 ce->count.EXTERNAL = 0;
788 ce->count.PROXY = 0;
789 ce->count.SPACER = 0;
790 ce->count.VECTOR = 0;
791 ce->count.part = 0;
792 }
793 }
794
795 static void
data_thread_head(void * data,Ecore_Thread * thread EINA_UNUSED)796 data_thread_head(void *data, Ecore_Thread *thread EINA_UNUSED)
797 {
798 Head_Write *hw = data;
799 int bytes = 0;
800 char buf[EINA_PATH_MAX];
801
802 if (edje_file)
803 {
804 if (edje_file->collection)
805 {
806 Edje_Part_Collection_Directory_Entry *ce;
807
808 EINA_LIST_FREE(aliases, ce)
809 {
810 Edje_Part_Collection_Directory_Entry *sce;
811
812 if (!ce->entry)
813 {
814 snprintf(buf, sizeof(buf),
815 "Collection %i: name missing.", ce->id);
816 hw->errstr = strdup(buf);
817 return;
818 }
819
820 sce = eina_hash_find(edje_collections_lookup, &ce->id);
821 if (sce)
822 {
823 memcpy(&ce->count, &sce->count, sizeof (ce->count));
824 }
825 else
826 {
827 snprintf(buf, sizeof(buf),
828 "Collection %s (%i) can't find an correct alias.",
829 ce->entry, ce->id);
830 hw->errstr = strdup(buf);
831 return;
832 }
833
834 _alias_clean(ce);
835 eina_hash_direct_add(edje_file->collection, ce->entry, ce);
836 }
837 }
838 bytes = eet_data_write(hw->ef, edd_edje_file, "edje/file", edje_file,
839 compress_mode);
840 if (bytes <= 0)
841 {
842 snprintf(buf, sizeof(buf),
843 "Unable to write \"edje_file\" entry to \"%s\"",
844 file_out);
845 hw->errstr = strdup(buf);
846 return;
847 }
848 }
849
850 INF("Wrote %9i bytes (%4iKb) for \"edje_file\" header",
851 bytes, (bytes + 512) / 1024);
852 }
853
854 static void
data_thread_head_end(void * data,Ecore_Thread * thread EINA_UNUSED)855 data_thread_head_end(void *data, Ecore_Thread *thread EINA_UNUSED)
856 {
857 Head_Write *hw = data;
858
859 if (hw->errstr)
860 {
861 error_and_abort(hw->ef, hw->errstr);
862 free(hw->errstr);
863 }
864 free(hw);
865 thread_end(0);
866 }
867
868 static void
data_write_header(Eet_File * ef)869 data_write_header(Eet_File *ef)
870 {
871 Head_Write *hw;
872
873 hw = calloc(1, sizeof(Head_Write));
874 hw->ef = ef;
875 pending_threads++;
876 if (threads)
877 ecore_thread_run(data_thread_head, data_thread_head_end, NULL, hw);
878 else
879 {
880 data_thread_head(hw, NULL);
881 data_thread_head_end(hw, NULL);
882 }
883 }
884
885 static void
data_thread_fonts(void * data,Ecore_Thread * thread EINA_UNUSED)886 data_thread_fonts(void *data, Ecore_Thread *thread EINA_UNUSED)
887 {
888 Fonts_Write *fc = data;
889 Eina_List *ll;
890 Eina_File *f = NULL;
891 void *m = NULL;
892 int bytes = 0;
893 char buf[EINA_PATH_MAX];
894 char buf2[EINA_PATH_MAX + EINA_PATH_MAX + 128];
895 size_t size;
896
897 f = eina_file_open(fc->fn->file, 0);
898 if (f)
899 {
900 using_file(fc->fn->file, 'F');
901 m = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
902 }
903 else
904 {
905 char *dat;
906
907 EINA_LIST_FOREACH(fnt_dirs, ll, dat)
908 {
909 snprintf(buf, sizeof(buf), "%s/%s", dat, fc->fn->file);
910 f = eina_file_open(buf, 0);
911 if (f)
912 {
913 using_file(buf, 'F');
914 m = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
915 if (m) break;
916 eina_file_close(f);
917 f = NULL;
918 }
919 }
920 }
921 if (!m)
922 {
923 if (f) eina_file_close(f);
924 snprintf(buf, sizeof(buf),
925 "Unable to load font part \"%s\" entry to %s",
926 fc->fn->file, file_out);
927 fc->errstr = strdup(buf);
928 return;
929 }
930
931 snprintf(buf, sizeof(buf), "edje/fonts/%s", fc->fn->name);
932 bytes = eet_write(fc->ef, buf, m, eina_file_size_get(f), compress_mode);
933
934 if ((bytes <= 0) || eina_file_map_faulted(f, m))
935 {
936 eina_file_map_free(f, m);
937 eina_file_close(f);
938 snprintf(buf2, sizeof(buf2),
939 "Unable to write font part \"%s\" as \"%s\" "
940 "part entry to %s", fc->fn->file, buf, file_out);
941 fc->errstr = strdup(buf2);
942 return;
943 }
944
945 size = eina_file_size_get(f);
946 INF("Wrote %9i bytes (%4iKb) for \"%s\" font entry \"%s\" compress: [real: %2.1f%%]",
947 bytes, (bytes + 512) / 1024, buf, fc->fn->file,
948 100 - (100 * (double)bytes) / ((double)((size > 0) ? size : 1))
949 );
950 eina_file_map_free(f, m);
951 eina_file_close(f);
952 }
953
954 static void
data_thread_fonts_end(void * data,Ecore_Thread * thread EINA_UNUSED)955 data_thread_fonts_end(void *data, Ecore_Thread *thread EINA_UNUSED)
956 {
957 Fonts_Write *fc = data;
958 if (fc->errstr)
959 {
960 error_and_abort(fc->ef, fc->errstr);
961 free(fc->errstr);
962 }
963 free(fc);
964 thread_end(0);
965 }
966
967 static void
data_write_fonts(Eet_File * ef,int * font_num)968 data_write_fonts(Eet_File *ef, int *font_num)
969 {
970 Eina_Iterator *it;
971 Edje_Font *fn;
972
973 if (!edje_file->fonts) return;
974
975 it = eina_hash_iterator_data_new(edje_file->fonts);
976 EINA_ITERATOR_FOREACH(it, fn)
977 {
978 Fonts_Write *fc;
979
980 fc = calloc(1, sizeof(Fonts_Write));
981 if (!fc) continue;
982 fc->ef = ef;
983 fc->fn = fn;
984 pending_threads++;
985 if (threads)
986 ecore_thread_run(data_thread_fonts, data_thread_fonts_end, NULL, fc);
987 else
988 {
989 data_thread_fonts(fc, NULL);
990 data_thread_fonts_end(fc, NULL);
991 }
992 *font_num += 1;
993 }
994 eina_iterator_free(it);
995 }
996
997 static void
error_and_abort_image_load_error(Eet_File * ef,const char * file,int error)998 error_and_abort_image_load_error(Eet_File *ef, const char *file, int error)
999 {
1000 const char *errmsg = evas_load_error_str(error);
1001 char hint[1024] = "";
1002
1003 if (error == EVAS_LOAD_ERROR_DOES_NOT_EXIST)
1004 {
1005 snprintf
1006 (hint, sizeof(hint),
1007 " Check if path to file \"%s\" is correct "
1008 "(both directory and file name).",
1009 file);
1010 }
1011 else if (error == EVAS_LOAD_ERROR_CORRUPT_FILE)
1012 {
1013 snprintf
1014 (hint, sizeof(hint),
1015 " Check if file \"%s\" is consistent.",
1016 file);
1017 }
1018 else if (error == EVAS_LOAD_ERROR_UNKNOWN_FORMAT)
1019 {
1020 const char *ext = strrchr(file, '.');
1021 const char **itr, *known_loaders[] = {
1022 /* list from evas_image_load.c */
1023 "png",
1024 "jpg",
1025 "jpeg",
1026 "jfif",
1027 "eet",
1028 "edj",
1029 "eap",
1030 "edb",
1031 "xpm",
1032 "tiff",
1033 "tif",
1034 "svg",
1035 "svgz",
1036 "gif",
1037 "pbm",
1038 "pgm",
1039 "ppm",
1040 "pnm",
1041 "bmp",
1042 "ico",
1043 "tga",
1044 "tgv",
1045 NULL
1046 };
1047
1048 if (!ext)
1049 {
1050 snprintf
1051 (hint, sizeof(hint),
1052 " File \"%s\" does not have an extension, "
1053 "maybe it should?",
1054 file);
1055 goto show_err;
1056 }
1057
1058 ext++;
1059 for (itr = known_loaders; *itr; itr++)
1060 {
1061 if (strcasecmp(ext, *itr) == 0)
1062 {
1063 snprintf
1064 (hint, sizeof(hint),
1065 " Check if Evas was compiled with %s module enabled and "
1066 "all required dependencies exist.",
1067 ext);
1068 goto show_err;
1069 }
1070 }
1071
1072 snprintf(hint, sizeof(hint),
1073 " Check if Evas supports loading files of type \"%s\" (%s) "
1074 "and this module was compiled and all its dependencies exist.",
1075 ext, file);
1076 }
1077 show_err:
1078 error_and_abort
1079 (ef, "Unable to load image \"%s\" used by file \"%s\": %s.%s",
1080 file, file_out, errmsg, hint);
1081 }
1082
1083 static void
data_thread_image(void * data,Ecore_Thread * thread EINA_UNUSED)1084 data_thread_image(void *data, Ecore_Thread *thread EINA_UNUSED)
1085 {
1086 Image_Write *iw = data;
1087 char buf[PATH_MAX], buf2[EINA_PATH_MAX];
1088 unsigned int *start, *end;
1089 Eina_Bool opaque = EINA_TRUE;
1090 int bytes = 0;
1091
1092 if ((iw->data) && (iw->w > 0) && (iw->h > 0))
1093 {
1094 Eet_Image_Encoding lossy = EET_IMAGE_LOSSLESS;
1095 int mode, qual, comp = 0;
1096
1097 snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
1098 qual = 80;
1099 if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
1100 (iw->img->source_param == 0))
1101 mode = 0; /* RAW */
1102 else if ((iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_PERFECT) &&
1103 (iw->img->source_param == 1))
1104 mode = 1; /* COMPRESS */
1105 else if (iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1)
1106 mode = 3; /* LOSSY_ETC1 */
1107 else if (iw->img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2)
1108 mode = 4; /* LOSSY_ETC2 */
1109 else
1110 mode = 2; /* LOSSY */
1111 if ((mode == 0) && (no_raw))
1112 {
1113 mode = 1; /* promote compression */
1114 iw->img->source_param = 95;
1115 }
1116 if ((mode == 4) && (no_etc2)) mode = 2; /* demote etc2 to jpeg */
1117 if ((mode == 3) && (no_etc1)) mode = 2; /* demote etc1 to jpeg */
1118 if ((mode == 2) && (no_lossy)) mode = 1; /* demote compression */
1119 if ((mode == 1) && (no_comp))
1120 {
1121 if (no_lossy) mode = 0; /* demote compression */
1122 else if (no_raw)
1123 {
1124 iw->img->source_param = 90;
1125 mode = 2; /* no choice. lossy */
1126 }
1127 }
1128 if (mode == 2)
1129 {
1130 qual = iw->img->source_param;
1131 if (qual < min_quality) qual = min_quality;
1132 if (qual > max_quality) qual = max_quality;
1133 lossy = EET_IMAGE_JPEG;
1134 }
1135 if (iw->alpha)
1136 {
1137 start = (unsigned int *)iw->data;
1138 end = start + (iw->w * iw->h);
1139 while (start < end)
1140 {
1141 if ((*start & 0xff000000) != 0xff000000)
1142 {
1143 opaque = EINA_FALSE;
1144 break;
1145 }
1146 start++;
1147 }
1148 if (opaque) iw->alpha = 0;
1149 }
1150 if (mode == 3)
1151 {
1152 qual = iw->img->source_param;
1153 if (qual < min_quality) qual = min_quality;
1154 if (qual > max_quality) qual = max_quality;
1155 // Enable TGV with LZ4. A bit redundant with EET compression.
1156 comp = !no_comp;
1157 lossy = opaque ? EET_IMAGE_ETC1 : EET_IMAGE_ETC1_ALPHA;
1158 }
1159 if (mode == 4)
1160 {
1161 qual = iw->img->source_param;
1162 if (qual < min_quality) qual = min_quality;
1163 if (qual > max_quality) qual = max_quality;
1164 lossy = opaque ? EET_IMAGE_ETC2_RGB : EET_IMAGE_ETC2_RGBA;
1165 }
1166 if (mode == 0)
1167 bytes = eet_data_image_write(iw->ef, buf,
1168 iw->data, iw->w, iw->h,
1169 iw->alpha,
1170 0, 0, 0);
1171 else if (mode == 1)
1172 bytes = eet_data_image_write(iw->ef, buf,
1173 iw->data, iw->w, iw->h,
1174 iw->alpha,
1175 compress_mode,
1176 0, 0);
1177 else if (mode >= 2)
1178 bytes = eet_data_image_write(iw->ef, buf,
1179 iw->data, iw->w, iw->h,
1180 iw->alpha,
1181 comp, qual, lossy);
1182 if (bytes <= 0)
1183 {
1184 snprintf(buf2, sizeof(buf2),
1185 "Unable to write image part "
1186 "\"%s\" as \"%s\" part entry to "
1187 "%s", iw->img->entry, buf, file_out);
1188 iw->errstr = strdup(buf2);
1189 return;
1190 }
1191 }
1192 else
1193 {
1194 snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
1195 snprintf(buf2, sizeof(buf2),
1196 "Unable to load image part "
1197 "\"%s\" as \"%s\" part entry to "
1198 "%s", iw->img->entry, buf, file_out);
1199 iw->errstr = strdup(buf2);
1200 return;
1201 }
1202
1203 if (eina_log_domain_level_check(_edje_cc_log_dom, EINA_LOG_LEVEL_INFO))
1204 {
1205 struct stat st;
1206
1207 if (!iw->path || (stat(iw->path, &st))) st.st_size = 0;
1208 if (st.st_size > 0)
1209 {
1210 INF("Wrote %9i bytes (%4iKb) for \"%s\" image entry \"%s\" compress: [raw: %2.1f%%] [real: %2.1f%%]",
1211 bytes, (bytes + 512) / 1024, buf, iw->img->entry,
1212 100 - (100 * (double)bytes) / ((double)(iw->w * iw->h * 4)),
1213 100 - (100 * (double)bytes) / ((double)(st.st_size))
1214 );
1215 }
1216 }
1217 }
1218
1219 static void
data_thread_image_end(void * data,Ecore_Thread * thread EINA_UNUSED)1220 data_thread_image_end(void *data, Ecore_Thread *thread EINA_UNUSED)
1221 {
1222 Image_Write *iw = data;
1223
1224 if (iw->errstr)
1225 {
1226 error_and_abort(iw->ef, iw->errstr);
1227 free(iw->errstr);
1228 }
1229 free(iw->path);
1230 evas_object_del(iw->im);
1231 free(iw);
1232 thread_end(1);
1233 }
1234
1235 static void
data_image_preload_done(void * data,Evas * e EINA_UNUSED,Evas_Object * o,void * event_info EINA_UNUSED)1236 data_image_preload_done(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event_info EINA_UNUSED)
1237 {
1238 Image_Write *iw = data;
1239
1240 evas_object_image_size_get(o, &iw->w, &iw->h);
1241 iw->alpha = evas_object_image_alpha_get(o);
1242 iw->data = evas_object_image_data_get(o, 0);
1243 if (threads)
1244 ecore_thread_run(data_thread_image, data_thread_image_end, NULL, iw);
1245 else
1246 {
1247 data_thread_image(iw, NULL);
1248 data_thread_image_end(iw, NULL);
1249 }
1250 }
1251
1252 static void
tgv_file_thread(void * data,Ecore_Thread * thread EINA_UNUSED)1253 tgv_file_thread(void *data, Ecore_Thread *thread EINA_UNUSED)
1254 {
1255 Image_Write *iw = data;
1256 char buf[256];
1257 size_t len;
1258
1259 snprintf(buf, sizeof(buf), "edje/images/%i", iw->img->id);
1260
1261 len = eina_file_size_get(iw->f);
1262 eet_write_cipher(iw->ef, buf, iw->data, len, EINA_FALSE /*!no_comp*/, NULL);
1263 }
1264
1265 static void
tgv_file_thread_end(void * data,Ecore_Thread * thread EINA_UNUSED)1266 tgv_file_thread_end(void *data, Ecore_Thread *thread EINA_UNUSED)
1267 {
1268 Image_Write *iw = data;
1269
1270 if (iw->errstr)
1271 {
1272 error_and_abort(iw->ef, iw->errstr);
1273 free(iw->errstr);
1274 }
1275 free(iw->path);
1276 emile_image_close(iw->emi);
1277 eina_file_map_free(iw->f, iw->data);
1278 eina_file_close(iw->f);
1279 free(iw);
1280 thread_end(1);
1281 }
1282
1283 static Eina_Bool
tgv_file_check_and_add(Eet_File * ef,Edje_Image_Directory_Entry * img)1284 tgv_file_check_and_add(Eet_File *ef, Edje_Image_Directory_Entry *img)
1285 {
1286 Emile_Image_Load_Error err;
1287 Emile_Image *emi = NULL;
1288 Image_Write *iw = NULL;
1289 Eina_List *li;
1290 const char *s;
1291 Eina_File *f = NULL;
1292 void *data;
1293
1294 EINA_LIST_FOREACH(img_dirs, li, s)
1295 {
1296 char buf[PATH_MAX];
1297 snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
1298 f = eina_file_open(buf, EINA_FALSE);
1299 if (f) break;
1300 }
1301 if (!f) return EINA_FALSE;
1302
1303 data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
1304 if (!data) goto on_error;
1305
1306 using_file(img->entry, 'I');
1307
1308 emi = emile_image_tgv_file_open(f, NULL, NULL, &err);
1309 if (!emi || (err != EMILE_IMAGE_LOAD_ERROR_NONE)) goto on_error;
1310
1311 iw = calloc(1, sizeof(*iw));
1312
1313 if (!emile_image_head(emi, &iw->prop, sizeof(iw->prop), &err) ||
1314 (err != EMILE_IMAGE_LOAD_ERROR_NONE))
1315 goto on_error;
1316
1317 if (!iw->prop.cspaces || !iw->prop.w || !iw->prop.h)
1318 goto on_error;
1319
1320 iw->f = f;
1321 iw->ef = ef;
1322 iw->img = img;
1323 iw->emi = emi;
1324 iw->data = (unsigned int *)data;
1325 iw->w = iw->prop.w;
1326 iw->h = iw->prop.h;
1327
1328 iw->prop.cspace = iw->prop.cspaces[0];
1329 if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1)
1330 {
1331 if (no_etc1) goto on_error;
1332 if (iw->prop.cspace == EMILE_COLORSPACE_ETC1)
1333 iw->alpha = 0;
1334 else if (iw->prop.cspace == EMILE_COLORSPACE_ETC1_ALPHA)
1335 iw->alpha = 1;
1336 else
1337 goto on_error;
1338 }
1339 else if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2)
1340 {
1341 if (no_etc2) goto on_error;
1342 if (iw->prop.cspace == EMILE_COLORSPACE_RGB8_ETC2)
1343 iw->alpha = 0;
1344 else if (iw->prop.cspace == EMILE_COLORSPACE_RGBA8_ETC2_EAC)
1345 iw->alpha = 1;
1346 else
1347 goto on_error;
1348 }
1349
1350 image_num += 1;
1351 iw->path = strdup(img->entry);
1352
1353 pending_image_threads++;
1354 if (threads)
1355 ecore_thread_run(tgv_file_thread, tgv_file_thread_end, NULL, iw);
1356 else
1357 {
1358 tgv_file_thread(iw, NULL);
1359 tgv_file_thread_end(iw, NULL);
1360 }
1361
1362 return EINA_TRUE;
1363
1364 on_error:
1365 free(iw);
1366 emile_image_close(emi);
1367 if (data) eina_file_map_free(f, data);
1368 eina_file_close(f);
1369 return EINA_FALSE;
1370 }
1371
1372 static void
data_write_vectors(Eet_File * ef,int * vector_num)1373 data_write_vectors(Eet_File *ef, int *vector_num)
1374 {
1375 unsigned int i;
1376 Eina_List *ll;
1377 char *s;
1378 Eina_File *f = NULL;
1379 Edje_Vector_Directory_Entry *vector;
1380 Eina_Strbuf *buf;
1381 Eina_Bool found = EINA_FALSE;
1382 Evas *evas;
1383 Evas_Object *vg;
1384
1385 if (!((edje_file) && (edje_file->image_dir))) return;
1386
1387 if (!buffer_ee)
1388 buffer_ee = ecore_evas_buffer_new(1, 1);
1389 if (!buffer_ee)
1390 error_and_abort(ef, "Cannot create buffer engine canvas for image load.");
1391 evas = ecore_evas_get(buffer_ee);
1392 vg = evas_object_vg_add(evas);
1393 buf = eina_strbuf_new();
1394 for (i = 0; i < edje_file->image_dir->vectors_count; i++)
1395 {
1396 vector = &edje_file->image_dir->vectors[i];
1397 EINA_LIST_FOREACH(img_dirs, ll, s)
1398 {
1399 eina_strbuf_reset(buf);
1400 eina_strbuf_append_printf(buf, "%s" EINA_PATH_SEP_S "%s", s, vector->entry);
1401 f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
1402 if (!f) continue;
1403 eina_file_close(f);
1404
1405 if (vector->type == EDJE_VECTOR_FILE_TYPE_LOTTIE)
1406 {
1407 char *lottie_data = NULL;
1408 int lottie_data_len = 0;
1409
1410 f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
1411 if (!f) continue;
1412
1413 lottie_data_len = (int) eina_file_size_get(f);
1414 lottie_data = eina_file_map_all(f, EINA_FILE_POPULATE);
1415
1416 eina_strbuf_reset(buf);
1417 eina_strbuf_append_printf(buf, "edje/vectors/%i", vector->id);
1418 eet_write(ef, eina_strbuf_string_get(buf), lottie_data, lottie_data_len, EET_COMPRESSION_NONE);
1419
1420 eina_file_map_free(f, lottie_data);
1421 eina_file_close(f);
1422
1423 *vector_num += 1;
1424 found = EINA_TRUE;
1425 break;
1426 }
1427 else
1428 {
1429 f = eina_file_open(eina_strbuf_string_get(buf), EINA_FALSE);
1430 if (!f) continue;
1431 eina_file_close(f);
1432
1433 if (efl_file_set(vg, eina_strbuf_string_get(buf)))
1434 error_and_abort(ef, "Failed to parse svg : %s", vector->entry);
1435 if (efl_file_load(vg))
1436 error_and_abort(ef, "Failed to parse svg : %s", vector->entry);
1437
1438 eina_strbuf_reset(buf);
1439 eina_strbuf_append_printf(buf, "edje/vectors/%i", vector->id);
1440 if (!efl_file_save(vg, eet_file_get(ef), eina_strbuf_string_get(buf), NULL))
1441 error_and_abort(ef, "Failed to write data in Eet for svg :%s", vector->entry);
1442
1443 *vector_num += 1;
1444 found = EINA_TRUE;
1445 break;
1446 }
1447 }
1448 if (!found)
1449 error_and_abort(ef, "Unable to find the svg :%s", vector->entry);
1450 found = EINA_FALSE;
1451 }
1452 eina_strbuf_free(buf);
1453 }
1454
1455 static void
data_image_sets_init(void)1456 data_image_sets_init(void)
1457 {
1458 int i;
1459
1460 if (!((edje_file) && (edje_file->image_dir))) return;
1461 for (i = 0; i < (int)edje_file->image_dir->sets_count; i++)
1462 {
1463 Edje_Image_Directory_Set *set;
1464 Edje_Image_Directory_Set_Entry *set_entry;
1465 Edje_Image_Directory_Entry *img;
1466 Eina_List *ll = NULL;
1467
1468 set = edje_file->image_dir->sets + i;
1469 if (!set->entries) continue;
1470 EINA_LIST_FOREACH(set->entries, ll, set_entry)
1471 {
1472 img = &edje_file->image_dir->entries[set_entry->id];
1473 set_entry->name = img->entry;
1474 }
1475 }
1476 }
1477
1478 static void
data_write_images(void)1479 data_write_images(void)
1480 {
1481 Evas *evas;
1482 const char *ext = NULL;
1483
1484 if (!((edje_file) && (edje_file->image_dir))) return;
1485
1486 if (!buffer_ee)
1487 buffer_ee = ecore_evas_buffer_new(1, 1);
1488 if (!buffer_ee)
1489 error_and_abort(cur_ef, "Cannot create buffer engine canvas for image load.");
1490 evas = ecore_evas_get(buffer_ee);
1491
1492 for (; cur_image_entry < (int)edje_file->image_dir->entries_count; cur_image_entry++)
1493 {
1494 Edje_Image_Directory_Entry *img;
1495 Evas_Object *im;
1496 Eina_List *ll;
1497 char *s;
1498 int load_err = EVAS_LOAD_ERROR_NONE;
1499 Image_Write *iw;
1500
1501 img = &edje_file->image_dir->entries[cur_image_entry];
1502 if ((img->source_type >= EDJE_IMAGE_SOURCE_TYPE_USER) || !img->entry)
1503 continue;
1504
1505 if (img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC1 ||
1506 img->source_type == EDJE_IMAGE_SOURCE_TYPE_INLINE_LOSSY_ETC2)
1507 {
1508 ext = strrchr(img->entry, '.');
1509 if (ext && !strcasecmp(ext, ".tgv"))
1510 {
1511 if (tgv_file_check_and_add(cur_ef, img))
1512 {
1513 DBG("Directly copying data from TGV file into EDJ");
1514 continue;
1515 }
1516 else
1517 ERR("Source '%s' has incompatible ETC format.", img->entry);
1518 }
1519 }
1520
1521 iw = calloc(1, sizeof(Image_Write));
1522 iw->ef = cur_ef;
1523 iw->img = img;
1524 iw->im = im = evas_object_image_add(evas);
1525 if (threads)
1526 evas_object_event_callback_add(im,
1527 EVAS_CALLBACK_IMAGE_PRELOADED,
1528 data_image_preload_done,
1529 iw);
1530 EINA_LIST_FOREACH(img_dirs, ll, s)
1531 {
1532 char buf[PATH_MAX];
1533
1534 snprintf(buf, sizeof(buf), "%s/%s", s, img->entry);
1535 evas_object_image_file_set(im, buf, NULL);
1536 load_err = evas_object_image_load_error_get(im);
1537 if (load_err == EVAS_LOAD_ERROR_NONE)
1538 {
1539 image_num += 1;
1540 iw->path = strdup(buf);
1541 pending_image_threads++;
1542 if (threads)
1543 evas_object_image_preload(im, 0);
1544 using_file(buf, 'I');
1545 if (!threads)
1546 data_image_preload_done(iw, evas, im, NULL);
1547 break;
1548 }
1549 }
1550 if (!img_dirs || (load_err != EVAS_LOAD_ERROR_NONE))
1551 {
1552 evas_object_image_file_set(im, img->entry, NULL);
1553 load_err = evas_object_image_load_error_get(im);
1554 if (load_err == EVAS_LOAD_ERROR_NONE)
1555 {
1556 image_num += 1;
1557 iw->path = strdup(img->entry);
1558 pending_image_threads++;
1559 if (threads)
1560 evas_object_image_preload(im, 0);
1561 using_file(img->entry, 'I');
1562 if (!threads)
1563 data_image_preload_done(iw, evas, im, NULL);
1564 }
1565 else
1566 {
1567 free(iw);
1568 error_and_abort_image_load_error(cur_ef, img->entry, load_err);
1569 exit(1); // ensure static analysis tools know we exit
1570 }
1571 }
1572
1573 if (img->source_type < EDJE_IMAGE_SOURCE_TYPE_USER)
1574 {
1575 ext = strrchr(img->entry, '.');
1576 if (ext && (!strcasecmp(ext, ".svg") || !strcasecmp(ext, ".svgz")))
1577 {
1578 int size = strlen(img->entry) + strlen(".png") + 1;
1579 char *tmp = malloc(size);
1580 snprintf(tmp, size, "%s.png", img->entry);
1581 INF("Vector '%s' used as image, convert to bitmap '%s'", img->entry, tmp);
1582 free((void *)img->entry);
1583 img->entry = tmp;
1584 }
1585 }
1586 if (threads)
1587 {
1588 if (pending_threads + pending_image_threads > (int)max_open_files - 2) break;
1589 }
1590 }
1591 }
1592
1593 static void
data_thread_sounds(void * data,Ecore_Thread * thread EINA_UNUSED)1594 data_thread_sounds(void *data, Ecore_Thread *thread EINA_UNUSED)
1595 {
1596 Sound_Write *sw = data;
1597 Eina_List *ll;
1598 #ifdef HAVE_LIBSNDFILE
1599 Edje_Sound_Encode *enc_info;
1600 #endif
1601 char *dir_path = NULL;
1602 char snd_path[PATH_MAX];
1603 char sndid_str[15];
1604 Eina_File *f = NULL;
1605 void *m = NULL;
1606 int bytes = 0;
1607
1608 // Search the Sound file in all the -sd ( sound directory )
1609 EINA_LIST_FOREACH(snd_dirs, ll, dir_path)
1610 {
1611 snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path,
1612 sw->sample->snd_src);
1613 f = eina_file_open(snd_path, 0);
1614 if (f) break;
1615 }
1616 if (!f)
1617 {
1618 snprintf((char *)snd_path, sizeof(snd_path), "%s",
1619 sw->sample->snd_src);
1620 f = eina_file_open(snd_path, 0);
1621 }
1622 #ifdef HAVE_LIBSNDFILE
1623 if (f) eina_file_close(f);
1624 enc_info = _edje_multisense_encode(snd_path, sw->sample,
1625 sw->sample->quality);
1626 f = eina_file_open(enc_info->file, 0);
1627 if (f) using_file(enc_info->file, 'S');
1628 #else
1629 if (f) using_file(snd_path, 'S');
1630 #endif
1631 if (!f)
1632 {
1633 ERR("Unable to load sound data of: %s", sw->sample->name);
1634 exit(-1);
1635 }
1636
1637 snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sw->sample->id);
1638 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
1639 if (m)
1640 {
1641 bytes = eet_write(sw->ef, sndid_str, m, eina_file_size_get(f),
1642 EET_COMPRESSION_NONE);
1643 if (eina_file_map_faulted(f, m))
1644 {
1645 ERR("File access error when reading '%s'",
1646 eina_file_filename_get(f));
1647 exit(-1);
1648 }
1649 eina_file_map_free(f, m);
1650 }
1651 eina_file_close(f);
1652
1653 #ifdef HAVE_LIBSNDFILE
1654 //If encoded temporary file, delete it.
1655 if (enc_info->encoded) unlink(enc_info->file);
1656 #endif
1657 #ifdef HAVE_LIBSNDFILE
1658 INF("Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry \"%s\"",
1659 bytes, (bytes + 512) / 1024,
1660 sndid_str, enc_info->comp_type, sw->sample->name);
1661 #else
1662 INF("Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry \"%s\"",
1663 bytes, (bytes + 512) / 1024,
1664 sndid_str, "RAW PCM", sw->sample->name);
1665 #endif
1666
1667 #ifdef HAVE_LIBSNDFILE
1668 if ((enc_info->file) && (!enc_info->encoded))
1669 eina_stringshare_del(enc_info->file);
1670 free(enc_info);
1671 enc_info = NULL;
1672 #endif
1673 }
1674
1675 static void
data_thread_sounds_end(void * data,Ecore_Thread * thread EINA_UNUSED)1676 data_thread_sounds_end(void *data, Ecore_Thread *thread EINA_UNUSED)
1677 {
1678 Sound_Write *sw = data;
1679 free(sw);
1680 thread_end(0);
1681 }
1682
1683 static void
data_write_sounds(Eet_File * ef,int * sound_num)1684 data_write_sounds(Eet_File *ef, int *sound_num)
1685 {
1686 if ((edje_file) && (edje_file->sound_dir))
1687 {
1688 int i;
1689
1690 for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
1691 {
1692 Sound_Write *sw;
1693
1694 sw = calloc(1, sizeof(Sound_Write));
1695 if (!sw) continue;
1696 sw->ef = ef;
1697 sw->sample = &edje_file->sound_dir->samples[i];
1698 sw->i = i;
1699 *sound_num += 1;
1700 pending_threads++;
1701 if (threads)
1702 ecore_thread_run(data_thread_sounds, data_thread_sounds_end, NULL, sw);
1703 else
1704 {
1705 data_thread_sounds(sw, NULL);
1706 data_thread_sounds_end(sw, NULL);
1707 }
1708 }
1709 }
1710 }
1711
1712 static void
data_thread_mo(void * data,Ecore_Thread * thread EINA_UNUSED)1713 data_thread_mo(void *data, Ecore_Thread *thread EINA_UNUSED)
1714 {
1715 Mo_Write *mw = data;
1716 char buf[EINA_PATH_MAX];
1717 Eina_List *ll;
1718
1719 char *dir_path = NULL;
1720 char mo_path[PATH_MAX] = {0};
1721 char moid_str[50];
1722 Eina_File *f = NULL;
1723 void *m = NULL;
1724 int bytes = 0;
1725
1726 if (mw->mo_path)
1727 f = eina_file_open(mw->mo_path, 0);
1728 if (!f)
1729 {
1730 // Search the mo file in all the -md ( mo directory )
1731 EINA_LIST_FOREACH(mo_dirs, ll, dir_path)
1732 {
1733 snprintf((char *)mo_path, sizeof(mo_path), "%s/%s/%s", dir_path, mw->mo_entry->locale, mw->mo_entry->mo_src);
1734 f = eina_file_open(mo_path, 0);
1735 if (f) break;
1736 }
1737 }
1738 if (!f)
1739 {
1740 snprintf((char *)mo_path, sizeof(mo_path), "%s", mw->mo_entry->mo_src);
1741 f = eina_file_open(mo_path, 0);
1742 }
1743
1744 if (f) using_file(mo_path, 'S');
1745
1746 if (!f)
1747 {
1748 snprintf(buf, sizeof(buf), "Unable to load mo data of: %s", mo_path);
1749 ERR("%s", buf);
1750 mw->errstr = strdup(buf);
1751 exit(-1);
1752 }
1753
1754 snprintf(moid_str, sizeof(moid_str), "edje/mo/%i/%s/LC_MESSAGES", mw->mo_entry->id, mw->mo_entry->locale);
1755 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
1756 if (m)
1757 {
1758 bytes = eet_write(mw->ef, moid_str, m, eina_file_size_get(f), EET_COMPRESSION_NONE);
1759 if (eina_file_map_faulted(f, m))
1760 {
1761 snprintf(buf, sizeof(buf), "File access error when reading '%s'",
1762 eina_file_filename_get(f));
1763 ERR("%s", buf);
1764 mw->errstr = strdup(buf);
1765 eina_file_close(f);
1766 exit(-1);
1767 }
1768 eina_file_map_free(f, m);
1769 }
1770 eina_file_close(f);
1771 if (mw->mo_path)
1772 ecore_file_remove(mo_path);
1773
1774 INF("Wrote %9i bytes (%4iKb) for \"%s\" %s mo entry \"%s\"",
1775 bytes, (bytes + 512) / 1024, moid_str, "RAW PCM", mw->mo_entry->locale);
1776 }
1777
1778 static void
data_thread_mo_end(void * data,Ecore_Thread * thread EINA_UNUSED)1779 data_thread_mo_end(void *data, Ecore_Thread *thread EINA_UNUSED)
1780 {
1781 Mo_Write *mw = data;
1782 if (mw->errstr)
1783 {
1784 error_and_abort(mw->ef, mw->errstr);
1785 free(mw->errstr);
1786 }
1787 if (mw->mo_path)
1788 free(mw->mo_path);
1789 free(mw);
1790 thread_end(0);
1791 }
1792
1793 Eina_Bool
_exe_del_cb(void * data EINA_UNUSED,int evtype EINA_UNUSED,void * evinfo)1794 _exe_del_cb(void *data EINA_UNUSED, int evtype EINA_UNUSED, void *evinfo)
1795 {
1796 Mo_Write *mw = data;
1797 Ecore_Exe_Event_Del *ev = evinfo;
1798 if (!ev->exe) return ECORE_CALLBACK_RENEW;
1799 if (ecore_exe_data_get(ev->exe) != mw) return ECORE_CALLBACK_RENEW;
1800 if (ev->exit_code != 0)
1801 {
1802 error_and_abort(mw->ef, "Creation of .mo from .po failed.");
1803 return ECORE_CALLBACK_CANCEL;
1804 }
1805 if (ecore_file_exists(mw->mo_path))
1806 {
1807 if (threads)
1808 ecore_thread_run(data_thread_mo, data_thread_mo_end, NULL, mw);
1809 else
1810 {
1811 data_thread_mo(mw, NULL);
1812 data_thread_mo_end(mw, NULL);
1813 }
1814 }
1815 else
1816 return ECORE_CALLBACK_RENEW;
1817 if (pending_threads + pending_image_threads <= 0) ecore_main_loop_quit();
1818 return ECORE_CALLBACK_CANCEL;
1819 }
1820
1821 static void
data_write_mo(Eet_File * ef,int * mo_num)1822 data_write_mo(Eet_File *ef, int *mo_num)
1823 {
1824 if ((edje_file) && (edje_file->mo_dir))
1825 {
1826 int i;
1827 char *po_entry;
1828 char *sub_str;
1829 char buf[EINA_PATH_MAX + PATH_MAX + PATH_MAX + 128];
1830 Eina_List *ll;
1831 char *dir_path = NULL;
1832 char mo_path[PATH_MAX];
1833 char po_path[PATH_MAX];
1834
1835 for (i = 0; i < (int)edje_file->mo_dir->mo_entries_count; i++)
1836 {
1837 Mo_Write *mw, *mw2;
1838 mw = calloc(1, sizeof(Mo_Write));
1839 if (!mw) continue;
1840 mw->ef = ef;
1841 mw->mo_entry = &edje_file->mo_dir->mo_entries[i];
1842 *mo_num += 1;
1843 pending_threads++;
1844
1845 po_entry = strdup(mw->mo_entry->mo_src);
1846 sub_str = strstr(mw->mo_entry->mo_src, ".po");
1847
1848 if (sub_str)
1849 {
1850 sub_str[1] = 'm';
1851 EINA_LIST_FOREACH(mo_dirs, ll, dir_path)
1852 {
1853 snprintf((char *)po_path, sizeof(po_path), "%s/%s/%s", dir_path, mw->mo_entry->locale, po_entry);
1854 if (ecore_file_exists(po_path))
1855 {
1856 char *mo_dir = ecore_file_dir_get(eet_file_get(ef));
1857 snprintf((char *)mo_path, sizeof(mo_path), "%s/%s", mo_dir, mw->mo_entry->locale);
1858 ecore_file_mkpath(mo_path);
1859 snprintf((char *)mo_path, sizeof(mo_path), "%s/%s/%s", mo_dir, mw->mo_entry->locale, mw->mo_entry->mo_src);
1860 snprintf(buf, sizeof(buf), "msgfmt -o %s %s", mo_path, po_path);
1861 mw2 = malloc(sizeof(Mo_Write));
1862 if (mw2)
1863 {
1864 memcpy(mw2, mw, sizeof(Mo_Write));
1865 mw2->mo_path = strdup(mo_path);
1866 mw2->exe = ecore_exe_run(buf, mw2);
1867 ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
1868 _exe_del_cb, mw2);
1869 }
1870 free(mo_dir);
1871 }
1872 else
1873 error_and_abort(mw->ef, "Non-existent .po file specified: \"%s\".", po_path);
1874 }
1875 free(mw);
1876 }
1877 else
1878 {
1879 if (threads)
1880 ecore_thread_run(data_thread_mo, data_thread_mo_end, NULL, mw);
1881 else
1882 {
1883 data_thread_mo(mw, NULL);
1884 data_thread_mo_end(mw, NULL);
1885 }
1886 }
1887 free(po_entry);
1888 }
1889 }
1890 }
1891
1892 static void
data_thread_vibrations(void * data,Ecore_Thread * thread EINA_UNUSED)1893 data_thread_vibrations(void *data, Ecore_Thread *thread EINA_UNUSED)
1894 {
1895 Vibration_Write *vw = data;
1896 Eina_List *ll;
1897 char *dir_path = NULL;
1898 char path[PATH_MAX];
1899 char id_str[30];
1900 Eina_File *f = NULL;
1901 void *m = NULL;
1902 int bytes = 0;
1903
1904 EINA_LIST_FOREACH(vibration_dirs, ll, dir_path)
1905 {
1906 snprintf((char *)path, sizeof(path), "%s/%s", dir_path,
1907 vw->sample->src);
1908 f = eina_file_open(path, 0);
1909 if (f) break;
1910 }
1911 if (!f)
1912 {
1913 snprintf((char *)path, sizeof(path), "%s",
1914 vw->sample->src);
1915 f = eina_file_open(path, 0);
1916 }
1917 if (f) using_file(path, 'S');
1918 if (!f)
1919 {
1920 ERR("Unable to load vibration data of: %s", vw->sample->src);
1921 exit(-1);
1922 }
1923
1924 snprintf(id_str, sizeof(id_str), "edje/vibrations/%i", vw->sample->id);
1925 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
1926 if (m)
1927 {
1928 bytes = eet_write(vw->ef, id_str, m, eina_file_size_get(f),
1929 EET_COMPRESSION_NONE);
1930 if (eina_file_map_faulted(f, m))
1931 {
1932 ERR("File access error when reading '%s'",
1933 eina_file_filename_get(f));
1934 exit(-1);
1935 }
1936 eina_file_map_free(f, m);
1937 }
1938 eina_file_close(f);
1939
1940 INF("Wrote %9i bytes (%4iKb) for \"%s\" %s vibration entry \"%s\"",
1941 bytes, (bytes + 512) / 1024,
1942 id_str, "RAW", vw->sample->name);
1943 }
1944
1945 static void
data_thread_vibrations_end(void * data,Ecore_Thread * thread EINA_UNUSED)1946 data_thread_vibrations_end(void *data, Ecore_Thread *thread EINA_UNUSED)
1947 {
1948 Vibration_Write *sw = data;
1949 free(sw);
1950 thread_end(0);
1951 }
1952
1953 static void
data_write_vibrations(Eet_File * ef,int * num)1954 data_write_vibrations(Eet_File *ef, int *num)
1955 {
1956 if ((edje_file) && (edje_file->vibration_dir))
1957 {
1958 int i;
1959
1960 for (i = 0; i < (int)edje_file->vibration_dir->samples_count; i++)
1961 {
1962 Vibration_Write *vw;
1963
1964 vw = calloc(1, sizeof(Vibration_Write));
1965 if (!vw) continue;
1966 vw->ef = ef;
1967 vw->sample = &edje_file->vibration_dir->samples[i];
1968 vw->i = i;
1969 *num += 1;
1970 pending_threads++;
1971 if (threads)
1972 ecore_thread_run(data_thread_vibrations, data_thread_vibrations_end, NULL, vw);
1973 else
1974 {
1975 data_thread_vibrations(vw, NULL);
1976 data_thread_vibrations_end(vw, NULL);
1977 }
1978 }
1979 }
1980 }
1981
1982 static void
check_groups(Eet_File * ef)1983 check_groups(Eet_File *ef)
1984 {
1985 Edje_Part_Collection *pc;
1986 Eina_List *l;
1987
1988 /* sanity checks for parts and programs */
1989 EINA_LIST_FOREACH(edje_collections, l, pc)
1990 {
1991 unsigned int i;
1992
1993 for (i = 0; i < pc->parts_count; ++i)
1994 check_part(pc, pc->parts[i], ef);
1995
1996 #define CHECK_PROGRAM(Type, Pc, It) \
1997 for (It = 0; It < Pc->programs.Type ## _count; ++It) \
1998 check_program(Pc, Pc->programs.Type[i], ef); \
1999
2000 CHECK_PROGRAM(fnmatch, pc, i);
2001 CHECK_PROGRAM(strcmp, pc, i);
2002 CHECK_PROGRAM(strncmp, pc, i);
2003 CHECK_PROGRAM(strrncmp, pc, i);
2004 CHECK_PROGRAM(nocmp, pc, i);
2005 }
2006 }
2007
2008 static void
data_thread_group(void * data,Ecore_Thread * thread EINA_UNUSED)2009 data_thread_group(void *data, Ecore_Thread *thread EINA_UNUSED)
2010 {
2011 Group_Write *gw = data;
2012 char buf[PATH_MAX];
2013
2014 snprintf(buf, sizeof(buf), "edje/collections/%i", gw->pc->id);
2015 eet_data_write(gw->ef, edd_edje_part_collection, buf, gw->pc,
2016 compress_mode);
2017 return;
2018 }
2019
2020 static void
data_thread_group_end(void * data,Ecore_Thread * thread EINA_UNUSED)2021 data_thread_group_end(void *data, Ecore_Thread *thread EINA_UNUSED)
2022 {
2023 Group_Write *gw = data;
2024 if (gw->errstr)
2025 {
2026 error_and_abort(gw->ef, gw->errstr);
2027 free(gw->errstr);
2028 }
2029 free(gw);
2030 thread_end(0);
2031 }
2032
2033 static void
data_write_groups(Eet_File * ef,int * collection_num)2034 data_write_groups(Eet_File *ef, int *collection_num)
2035 {
2036 Eina_List *l;
2037 Edje_Part_Collection *pc;
2038
2039 EINA_LIST_FOREACH(edje_collections, l, pc)
2040 {
2041 Group_Write *gw;
2042
2043 gw = calloc(1, sizeof(Group_Write));
2044 if (!gw)
2045 {
2046 error_and_abort(ef, "Cannot allocate memory for group writer");
2047 return;
2048 }
2049 gw->ef = ef;
2050 gw->pc = pc;
2051 pending_threads++;
2052 if (threads)
2053 ecore_thread_run(data_thread_group, data_thread_group_end, NULL, gw);
2054 else
2055 {
2056 data_thread_group(gw, NULL);
2057 data_thread_group_end(gw, NULL);
2058 }
2059 *collection_num += 1;
2060 }
2061 }
2062
2063 static void
create_script_file(Eet_File * ef,const char * filename,const Code * cd,int fd)2064 create_script_file(Eet_File *ef, const char *filename, const Code *cd, int fd)
2065 {
2066 FILE *f = fdopen(fd, "wb");
2067 if (!f)
2068 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
2069 "compilation.", filename);
2070
2071 Eina_List *ll;
2072 Code_Program *cp;
2073
2074 fprintf(f, "#include <edje>\n");
2075 int ln = 2;
2076
2077 if (cd->shared)
2078 {
2079 while (ln < (cd->l1 - 1))
2080 {
2081 fprintf(f, " \n");
2082 ln++;
2083 }
2084 {
2085 char *sp;
2086 int hash = 0;
2087 int newlined = 0;
2088
2089 for (sp = cd->shared; *sp; sp++)
2090 {
2091 if ((sp[0] == '#') && (newlined))
2092 {
2093 hash = 1;
2094 }
2095 newlined = 0;
2096 if (sp[0] == '\n') newlined = 1;
2097 if (!hash) fputc(sp[0], f);
2098 else if (sp[0] == '\n')
2099 hash = 0;
2100 }
2101 fputc('\n', f);
2102 }
2103 ln += cd->l2 - cd->l1 + 1;
2104 }
2105 EINA_LIST_FOREACH(cd->programs, ll, cp)
2106 {
2107 if (cp->script)
2108 {
2109 while (ln < (cp->l1 - 1))
2110 {
2111 fprintf(f, " \n");
2112 ln++;
2113 }
2114 /* FIXME: this prototype needs to be */
2115 /* formalised and set in stone */
2116 fprintf(f, "public _p%i(sig[], src[]) {", cp->id);
2117 {
2118 char *sp;
2119 int hash = 0;
2120 int newlined = 0;
2121
2122 for (sp = cp->script; *sp; sp++)
2123 {
2124 if ((sp[0] == '#') && (newlined))
2125 {
2126 hash = 1;
2127 }
2128 newlined = 0;
2129 if (sp[0] == '\n') newlined = 1;
2130 if (!hash) fputc(sp[0], f);
2131 else if (sp[0] == '\n')
2132 hash = 0;
2133 }
2134 }
2135 fprintf(f, "}\n");
2136 ln += cp->l2 - cp->l1 + 1;
2137 }
2138 }
2139
2140 fclose(f);
2141 }
2142
2143 static void
data_thread_script(void * data,Ecore_Thread * thread EINA_UNUSED)2144 data_thread_script(void *data, Ecore_Thread *thread EINA_UNUSED)
2145 {
2146 Script_Write *sc = data;
2147 FILE *f;
2148 int size;
2149 char buf[PATH_MAX];
2150
2151 f = fopen(sc->tmpo, "rb");
2152 if (!f)
2153 {
2154 snprintf(buf, sizeof(buf),
2155 "Unable to open script object \"%s\" for reading.",
2156 sc->tmpo);
2157 sc->errstr = strdup(buf);
2158 return;
2159 }
2160
2161 if (fseek(f, 0, SEEK_END) < 0)
2162 ERR("Error seeking");
2163 size = ftell(f);
2164 rewind(f);
2165
2166 if (size > 0)
2167 {
2168 void *dat = malloc(size);
2169
2170 if (dat)
2171 {
2172 if (fread(dat, size, 1, f) != 1)
2173 {
2174 snprintf(buf, sizeof(buf),
2175 "Unable to read all of script object \"%s\"",
2176 sc->tmpo);
2177 sc->errstr = strdup(buf);
2178 free(dat);
2179 fclose(f);
2180 return;
2181 }
2182 snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i",
2183 sc->i);
2184 eet_write(sc->ef, buf, dat, size, compress_mode);
2185 free(dat);
2186 }
2187 else
2188 {
2189 snprintf(buf, sizeof(buf),
2190 "Alloc failed for %lu bytes", (unsigned long)size);
2191 sc->errstr = strdup(buf);
2192 fclose(f);
2193 return;
2194 }
2195 }
2196
2197 if (no_save)
2198 WRN("You are removing the source from this Edje file. This may break some use cases.\nBe aware of your choice and the poor kitten you are harming with it!");
2199 else
2200 {
2201 Eina_List *ll;
2202 Code_Program *cp;
2203
2204 if (sc->cd->original)
2205 {
2206 snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i", sc->i);
2207 eet_write(sc->ef, buf, sc->cd->original,
2208 strlen(sc->cd->original) + 1, compress_mode);
2209 }
2210 EINA_LIST_FOREACH(sc->cd->programs, ll, cp)
2211 {
2212 if (!cp->original) continue;
2213 snprintf(buf, PATH_MAX, "edje/scripts/embryo/source/%i/%i",
2214 sc->i, cp->id);
2215 eet_write(sc->ef, buf, cp->original,
2216 strlen(cp->original) + 1, compress_mode);
2217 }
2218 }
2219 fclose(f);
2220
2221 unlink(sc->tmpn);
2222 unlink(sc->tmpo);
2223 eina_tmpstr_del(sc->tmpn);
2224 eina_tmpstr_del(sc->tmpo);
2225 // closed by fclose(f) in create_script_file()
2226 // close(sc->tmpn_fd);
2227 }
2228
2229 typedef struct
2230 {
2231 char *exe;
2232 Script_Write *sc;
2233 } Pending_Script_Write;
2234
2235 #define PENDING_COMMANDS_MAX 8
2236
2237 static int pending_write_commands = 0;
2238 static Eina_List *pending_script_writes = NULL;
2239
2240 static void data_write_script_queue(Script_Write *sc, const char *exeline);
2241
2242 static void
data_thread_script_end(void * data,Ecore_Thread * thread EINA_UNUSED)2243 data_thread_script_end(void *data, Ecore_Thread *thread EINA_UNUSED)
2244 {
2245 Script_Write *sc = data;
2246 if (sc->errstr)
2247 {
2248 error_and_abort(sc->ef, sc->errstr);
2249 free(sc->errstr);
2250 }
2251 free(sc);
2252 thread_end(0);
2253 }
2254
2255 static Eina_Bool
data_scripts_exe_del_cb(void * data EINA_UNUSED,int evtype EINA_UNUSED,void * evinfo)2256 data_scripts_exe_del_cb(void *data EINA_UNUSED, int evtype EINA_UNUSED, void *evinfo)
2257 {
2258 Script_Write *sc = data;
2259 Ecore_Exe_Event_Del *ev = evinfo;
2260
2261 if (!ev->exe) return ECORE_CALLBACK_RENEW;
2262 if (ecore_exe_data_get(ev->exe) != sc) return ECORE_CALLBACK_RENEW;
2263 pending_write_commands--;
2264 if (pending_write_commands < PENDING_COMMANDS_MAX)
2265 {
2266 if (pending_script_writes)
2267 {
2268 Pending_Script_Write *pend = pending_script_writes->data;
2269
2270 pending_script_writes = eina_list_remove_list
2271 (pending_script_writes, pending_script_writes);
2272 data_write_script_queue(pend->sc, pend->exe);
2273 free(pend->exe);
2274 free(pend);
2275 }
2276 }
2277 if (ev->exit_code != 0)
2278 {
2279 error_and_abort(sc->ef, "Compiling script code not clean.");
2280 return ECORE_CALLBACK_CANCEL;
2281 }
2282 if (threads)
2283 {
2284 ecore_thread_run(data_thread_script, data_thread_script_end, NULL, sc);
2285 }
2286 else
2287 {
2288 data_thread_script(sc, NULL);
2289 data_thread_script_end(sc, NULL);
2290 }
2291 if (pending_threads + pending_image_threads <= 0) ecore_main_loop_quit();
2292 return ECORE_CALLBACK_CANCEL;
2293 }
2294
2295 static void
data_write_script_queue(Script_Write * sc,const char * exeline)2296 data_write_script_queue(Script_Write *sc, const char *exeline)
2297 {
2298 if (pending_write_commands >= PENDING_COMMANDS_MAX)
2299 {
2300 Pending_Script_Write *pend = malloc(sizeof(Pending_Script_Write));
2301 if (pend)
2302 {
2303 pend->sc = sc;
2304 pend->exe = strdup(exeline);
2305 if (!pend->exe)
2306 {
2307 error_and_abort(sc->ef,
2308 "Unable to allocate mem pending string.");
2309 free(pend);
2310 return;
2311 }
2312 pending_script_writes = eina_list_append(pending_script_writes,
2313 pend);
2314 }
2315 else
2316 error_and_abort(sc->ef,
2317 "Unable to allocate mem for pending script.");
2318 }
2319 else
2320 {
2321 pending_threads++;
2322 sc->exe = ecore_exe_run(exeline, sc);
2323 if (!sc->exe) error_and_abort(sc->ef, "Unable to fork off embryo_cc.");
2324 ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
2325 data_scripts_exe_del_cb, sc);
2326 pending_write_commands++;
2327 }
2328 }
2329
2330 static void
data_write_scripts(Eet_File * ef)2331 data_write_scripts(Eet_File *ef)
2332 {
2333 Eina_List *l;
2334 char embryo_cc_path[PATH_MAX] = "";
2335 char inc_path[PATH_MAX] = "";
2336 int i;
2337
2338 #ifdef _WIN32
2339 # define BIN_EXT ".exe"
2340 #else
2341 # define BIN_EXT
2342 #endif
2343 #ifdef NEED_RUN_IN_TREE
2344 if (getenv("EFL_RUN_IN_TREE"))
2345 {
2346 snprintf(embryo_cc_path, sizeof(embryo_cc_path),
2347 "%s/src/bin/embryo/embryo_cc" BIN_EXT,
2348 PACKAGE_BUILD_DIR);
2349 snprintf(inc_path, sizeof(inc_path),
2350 "%s/data/edje/include", PACKAGE_SRC_DIR);
2351 if (!ecore_file_exists(embryo_cc_path))
2352 embryo_cc_path[0] = '\0';
2353 }
2354 #endif
2355
2356 if (embryo_cc_path[0] == '\0')
2357 {
2358 snprintf(embryo_cc_path, sizeof(embryo_cc_path),
2359 "%s/embryo_cc" BIN_EXT,
2360 eina_prefix_bin_get(pfx));
2361 snprintf(inc_path, sizeof(inc_path),
2362 "%s/include",
2363 eina_prefix_data_get(pfx));
2364 }
2365 #undef BIN_EXT
2366
2367 for (i = 0, l = codes; l; l = eina_list_next(l), i++)
2368 {
2369 Code *cd = eina_list_data_get(l);
2370 Script_Write *sc;
2371 int fd;
2372 char buf[EINA_PATH_MAX + PATH_MAX + PATH_MAX + 128];
2373
2374 if (cd->is_lua)
2375 continue;
2376 if ((!cd->shared) && (!cd->programs))
2377 continue;
2378 sc = calloc(1, sizeof(Script_Write));
2379 sc->ef = ef;
2380 sc->cd = cd;
2381 sc->i = i;
2382 sc->tmpn_fd = eina_file_mkstemp("edje_cc.sma-tmp-XXXXXX", &sc->tmpn);
2383 if (sc->tmpn_fd < 0)
2384 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
2385 "compilation.", sc->tmpn);
2386 fd = eina_file_mkstemp("edje_cc.amx-tmp-XXXXXX", &sc->tmpo);
2387 if (fd < 0)
2388 {
2389 unlink(sc->tmpn);
2390 eina_tmpstr_del(sc->tmpn);
2391 error_and_abort(ef, "Unable to open temp file \"%s\" for script "
2392 "compilation.", sc->tmpo);
2393 }
2394 //do not carry the fd over the time
2395 //we should not unnesseserrily carry filedescriptors over time as this could excede system limits
2396 //which have been fetched earlier
2397 close(fd);
2398 create_script_file(ef, sc->tmpn, cd, sc->tmpn_fd);
2399 snprintf(buf, sizeof(buf),
2400 "%s -i %s -o %s %s", embryo_cc_path, inc_path,
2401 sc->tmpo, sc->tmpn);
2402 data_write_script_queue(sc, buf);
2403 }
2404 }
2405
2406 #ifdef LUA_BINARY
2407 static int
_edje_lua_script_writer(lua_State * L EINA_UNUSED,const void * chunk_buf,size_t chunk_size,void * _data)2408 _edje_lua_script_writer(lua_State *L EINA_UNUSED, const void *chunk_buf, size_t chunk_size, void *_data)
2409 {
2410 Script_Lua_Writer *data;
2411 void *old;
2412
2413 data = (Script_Lua_Writer *)_data;
2414 old = data->buf;
2415 data->buf = realloc(data->buf, data->size + chunk_size);
2416 if (data->buf)
2417 {
2418 memcpy(&((data->buf)[data->size]), chunk_buf, chunk_size);
2419 data->size += chunk_size;
2420 }
2421 else
2422 {
2423 ERR("Failed to copy chunk buffer.\n");
2424 data->buf = old;
2425 }
2426
2427 return 0;
2428 }
2429
2430 #endif
2431
2432 void
_edje_lua_error_and_abort(lua_State * L,int err_code,Script_Write * sc)2433 _edje_lua_error_and_abort(lua_State *L, int err_code, Script_Write *sc)
2434 {
2435 char buf[PATH_MAX];
2436 char *err_type;
2437
2438 switch (err_code)
2439 {
2440 case LUA_ERRRUN:
2441 err_type = "runtime";
2442 break;
2443
2444 case LUA_ERRSYNTAX:
2445 err_type = "syntax";
2446 break;
2447
2448 case LUA_ERRMEM:
2449 err_type = "memory allocation";
2450 break;
2451
2452 case LUA_ERRERR:
2453 err_type = "error handler";
2454 break;
2455
2456 default:
2457 err_type = "unknown";
2458 break;
2459 }
2460 snprintf(buf, sizeof(buf),
2461 "Lua %s error: %s", err_type, lua_tostring(L, -1));
2462 sc->errstr = strdup(buf);
2463 }
2464
2465 static void
data_thread_lua_script(void * data,Ecore_Thread * thread EINA_UNUSED)2466 data_thread_lua_script(void *data, Ecore_Thread *thread EINA_UNUSED)
2467 {
2468 Script_Write *sc = data;
2469 char buf[PATH_MAX];
2470 lua_State *L;
2471 int ln = 1;
2472 luaL_Buffer b;
2473 Script_Lua_Writer dat;
2474 Eina_List *ll;
2475 Code_Program *cp;
2476 #ifdef LUA_BINARY
2477 int err_code;
2478 #endif
2479
2480 L = luaL_newstate();
2481 if (!L)
2482 {
2483 snprintf(buf, sizeof(buf),
2484 "Lua error: Lua state could not be initialized");
2485 sc->errstr = strdup(buf);
2486 return;
2487 }
2488
2489 luaL_buffinit(L, &b);
2490
2491 dat.buf = NULL;
2492 dat.size = 0;
2493 if (sc->cd->shared)
2494 {
2495 while (ln < (sc->cd->l1 - 1))
2496 {
2497 luaL_addchar(&b, '\n');
2498 ln++;
2499 }
2500 luaL_addstring(&b, sc->cd->shared);
2501 ln += sc->cd->l2 - sc->cd->l1;
2502 }
2503
2504 EINA_LIST_FOREACH(sc->cd->programs, ll, cp)
2505 {
2506 if (cp->script)
2507 {
2508 while (ln < (cp->l1 - 1))
2509 {
2510 luaL_addchar(&b, '\n');
2511 ln++;
2512 }
2513 luaL_addstring(&b, "_G[");
2514 lua_pushnumber(L, cp->id);
2515 luaL_addvalue(&b);
2516 luaL_addstring(&b, "] = function (ed, signal, source)");
2517 luaL_addstring(&b, cp->script);
2518 luaL_addstring(&b, "end\n");
2519 ln += cp->l2 - cp->l1 + 1;
2520 }
2521 }
2522 luaL_pushresult(&b);
2523 #ifdef LUA_BINARY
2524 if (err_code = luaL_loadstring(L, lua_tostring(L, -1)))
2525 {
2526 _edje_lua_error_and_abort(L, err_code, sc);
2527 return;
2528 }
2529 lua_dump(L, _edje_lua_script_writer, &dat);
2530 #else // LUA_PLAIN_TEXT
2531 dat.buf = (char *)lua_tostring(L, -1);
2532 dat.size = strlen(dat.buf);
2533 #endif
2534 //printf("lua chunk size: %d\n", dat.size);
2535
2536 /*
2537 * TODO load and test Lua chunk
2538 */
2539
2540 /*
2541 if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script"))
2542 printf("lua load error: %s\n", lua_tostring (L, -1));
2543 if (lua_pcall(L, 0, 0, 0))
2544 printf("lua call error: %s\n", lua_tostring (L, -1));
2545 */
2546
2547 snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", sc->i);
2548 if (eet_write(sc->ef, buf, dat.buf, dat.size, compress_mode) <= 0)
2549 {
2550 snprintf(buf, sizeof(buf),
2551 "Unable to write script %i", sc->i);
2552 sc->errstr = strdup(buf);
2553 return;
2554 }
2555 #ifdef LUA_BINARY
2556 free(dat.buf);
2557 #endif
2558 lua_close(L);
2559 }
2560
2561 static void
data_thread_lua_script_end(void * data,Ecore_Thread * thread EINA_UNUSED)2562 data_thread_lua_script_end(void *data, Ecore_Thread *thread EINA_UNUSED)
2563 {
2564 Script_Write *sc = data;
2565 if (sc->errstr)
2566 {
2567 error_and_abort(sc->ef, sc->errstr);
2568 free(sc->errstr);
2569 }
2570 free(sc);
2571 thread_end(0);
2572 }
2573
2574 static void
data_write_lua_scripts(Eet_File * ef)2575 data_write_lua_scripts(Eet_File *ef)
2576 {
2577 Eina_List *l;
2578 int i;
2579
2580 for (i = 0, l = codes; l; l = eina_list_next(l), i++)
2581 {
2582 Code *cd;
2583 Script_Write *sc;
2584
2585 cd = (Code *)eina_list_data_get(l);
2586 if (!cd->is_lua)
2587 continue;
2588 if ((!cd->shared) && (!cd->programs))
2589 continue;
2590
2591 sc = calloc(1, sizeof(Script_Write));
2592 sc->ef = ef;
2593 sc->cd = cd;
2594 sc->i = i;
2595 pending_threads++;
2596 if (threads)
2597 ecore_thread_run(data_thread_lua_script, data_thread_lua_script_end, NULL, sc);
2598 else
2599 {
2600 data_thread_lua_script(sc, NULL);
2601 data_thread_lua_script_end(sc, NULL);
2602 }
2603 }
2604 }
2605
2606 static void
data_thread_source(void * data,Ecore_Thread * thread EINA_UNUSED)2607 data_thread_source(void *data, Ecore_Thread *thread EINA_UNUSED)
2608 {
2609 Eet_File *ef = data;
2610 source_append(ef);
2611 }
2612
2613 static void
data_thread_source_end(void * data EINA_UNUSED,Ecore_Thread * thread EINA_UNUSED)2614 data_thread_source_end(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED)
2615 {
2616 thread_end(0);
2617 }
2618
2619 static void
data_thread_license(void * data,Ecore_Thread * thread EINA_UNUSED)2620 data_thread_license(void *data, Ecore_Thread *thread EINA_UNUSED)
2621 {
2622 License_Write *lw = data;
2623 Eet_File *ef = lw->ef;
2624 Eina_File *f;
2625 void *m;
2626 int bytes;
2627
2628 f = eina_file_open(lw->file, 0);
2629 if (!f) return;
2630
2631 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
2632 if (!m) goto on_error;
2633
2634 if (lw->master)
2635 {
2636 bytes = eet_write(ef, "edje/license", m, eina_file_size_get(f), compress_mode);
2637 }
2638 else
2639 {
2640 char *s = alloca(strlen(lw->file) + 1 + 13);
2641
2642 strcpy(s, lw->file);
2643 sprintf(s, "edje/license/%s", basename(s));
2644
2645 bytes = eet_write(ef, s, m, eina_file_size_get(f), compress_mode);
2646 }
2647
2648 if ((bytes <= 0) || eina_file_map_faulted(f, m))
2649 {
2650 ERR("Unable to write license part \"%s\".", lw->file);
2651 }
2652 else
2653 {
2654 double fsize = eina_file_size_get(f);
2655
2656 if (fsize <= 0.0) fsize = 1.0;
2657 INF("Wrote %9i bytes (%4iKb) for \"%s\" license entry compress: [real: %2.1f%%]",
2658 bytes, (bytes + 512) / 1024, license,
2659 100.0 - ((100.0 * (double)bytes) / fsize));
2660 }
2661
2662 eina_file_map_free(f, m);
2663
2664 on_error:
2665 eina_file_close(f);
2666 }
2667
2668 static void
data_thread_license_end(void * data,Ecore_Thread * thread EINA_UNUSED)2669 data_thread_license_end(void *data, Ecore_Thread *thread EINA_UNUSED)
2670 {
2671 free(data);
2672 thread_end(0);
2673 }
2674
2675 static void
data_write_license(Eet_File * ef)2676 data_write_license(Eet_File *ef)
2677 {
2678 License_Write *lw;
2679 Eina_List *l;
2680 const char *file;
2681
2682 if (!license) return;
2683
2684 lw = calloc(1, sizeof (License_Write));
2685 if (!lw) return;
2686
2687 lw->ef = ef;
2688 lw->file = license;
2689 lw->master = EINA_TRUE;
2690
2691 pending_threads++;
2692 if (threads)
2693 ecore_thread_run(data_thread_license, data_thread_license_end, NULL, lw);
2694 else
2695 {
2696 data_thread_license(lw, NULL);
2697 data_thread_license_end(lw, NULL);
2698 }
2699
2700 EINA_LIST_FOREACH(licenses, l, file)
2701 {
2702 lw = calloc(1, sizeof (License_Write));
2703 if (!lw) return;
2704
2705 lw->ef = ef;
2706 lw->file = file;
2707 lw->master = EINA_FALSE;
2708
2709 pending_threads++;
2710 if (threads)
2711 ecore_thread_run(data_thread_license, data_thread_license_end, NULL, lw);
2712 else
2713 {
2714 data_thread_license(lw, NULL);
2715 data_thread_license_end(lw, NULL);
2716 }
2717 }
2718 }
2719
2720 static void
data_thread_authors(void * data,Ecore_Thread * thread EINA_UNUSED)2721 data_thread_authors(void *data, Ecore_Thread *thread EINA_UNUSED)
2722 {
2723 Eet_File *ef = data;
2724 Eina_File *f;
2725 void *m;
2726 int bytes;
2727
2728 f = eina_file_open(authors, 0);
2729 if (!f) return;
2730
2731 m = eina_file_map_all(f, EINA_FILE_WILLNEED);
2732 if (!m) goto on_error;
2733
2734 bytes = eet_write(ef, "edje/authors", m, eina_file_size_get(f), compress_mode);
2735 if ((bytes <= 0) || eina_file_map_faulted(f, m))
2736 {
2737 ERR("Unable to write authors part \"%s\".", authors);
2738 }
2739 else
2740 {
2741 double fsize = eina_file_size_get(f);
2742
2743 if (fsize <= 0.0) fsize = 1.0;
2744 INF("Wrote %9i bytes (%4iKb) for \"%s\" authors entry compress: [real: %2.1f%%]",
2745 bytes, (bytes + 512) / 1024, license,
2746 100.0 - ((100.0 * (double)bytes) / fsize));
2747 }
2748
2749 eina_file_map_free(f, m);
2750
2751 on_error:
2752 eina_file_close(f);
2753 }
2754
2755 static void
data_thread_authors_end(void * data EINA_UNUSED,Ecore_Thread * thread EINA_UNUSED)2756 data_thread_authors_end(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED)
2757 {
2758 thread_end(0);
2759 }
2760
2761 static void
data_thread_fontmap(void * data,Ecore_Thread * thread EINA_UNUSED)2762 data_thread_fontmap(void *data, Ecore_Thread *thread EINA_UNUSED)
2763 {
2764 Eet_File *ef = data;
2765 source_fontmap_save(ef, fonts);
2766 }
2767
2768 static void
data_thread_fontmap_end(void * data EINA_UNUSED,Ecore_Thread * thread EINA_UNUSED)2769 data_thread_fontmap_end(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED)
2770 {
2771 thread_end(0);
2772 }
2773
2774 void
data_write(void)2775 data_write(void)
2776 {
2777 Eet_File *ef;
2778 Eet_Error err;
2779 int sound_num = 0;
2780 int mo_num = 0;
2781 int vibration_num = 0;
2782 int font_num = 0;
2783 int collection_num = 0;
2784 int vector_num = 0;
2785 double t;
2786
2787 if (!edje_file)
2788 {
2789 ERR("No data to put in \"%s\"", file_out);
2790 exit(-1);
2791 }
2792
2793 cur_ef = ef = eet_open(file_out, EET_FILE_MODE_WRITE);
2794 if (!ef)
2795 {
2796 ERR("Unable to open \"%s\" for writing output", file_out);
2797 exit(-1);
2798 }
2799
2800 if ((edje_file->efl_version.major <= 1) && (edje_file->efl_version.minor <= 18)
2801 && edje_file->has_textblock_min_max)
2802 {
2803 WRN("This EDC file was designed for EFL 1.18. Until 1.19, EFL used an "
2804 "invalid calculation mechanism for textblock parts, where the value "
2805 "of text min/max was not properly taken into account. You might "
2806 "want to consider adding \"efl_version: %d %d;\" in your EDC "
2807 "file (before the \"collections\" block), and then check the sizing "
2808 "for all textblock parts that specify text min/max values (the bool "
2809 "defined as description.text.{min,max}).",
2810 EFL_VERSION_MAJOR, EFL_VERSION_MINOR);
2811 }
2812
2813 if (eina_array_count(requires))
2814 {
2815 int i = 0;
2816
2817 edje_file->requires_count = eina_array_count(requires);
2818 edje_file->requires = mem_alloc(edje_file->requires_count * sizeof(void*));
2819 do
2820 {
2821 edje_file->requires[i] = eina_array_pop(requires);
2822 i++;
2823 } while (eina_array_count(requires));
2824 eina_array_free(requires);
2825 }
2826
2827 check_groups(ef);
2828
2829 ecore_thread_max_set(ecore_thread_max_get() * 2);
2830
2831 pending_threads++;
2832 t = ecore_time_get();
2833
2834 INF("header: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2835 data_write_groups(ef, &collection_num);
2836 INF("groups: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2837 data_write_scripts(ef);
2838 INF("scripts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2839 data_write_lua_scripts(ef);
2840 INF("lua scripts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2841
2842 if (!no_save)
2843 {
2844 pending_threads++;
2845 if (threads)
2846 ecore_thread_run(data_thread_source, data_thread_source_end, NULL, ef);
2847 else
2848 {
2849 data_thread_source(ef, NULL);
2850 data_thread_source_end(ef, NULL);
2851 }
2852 }
2853 INF("source: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2854 pending_threads++;
2855 if (threads)
2856 ecore_thread_run(data_thread_fontmap, data_thread_fontmap_end, NULL, ef);
2857 else
2858 {
2859 data_thread_fontmap(ef, NULL);
2860 data_thread_fontmap_end(ef, NULL);
2861 }
2862 INF("fontmap: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2863 data_write_vectors(ef, &vector_num);
2864 INF("vectors: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2865 data_write_fonts(ef, &font_num);
2866 INF("fonts: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2867 data_write_sounds(ef, &sound_num);
2868 INF("sounds: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2869 data_write_mo(ef, &mo_num);
2870 INF("mo: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2871 data_write_vibrations(ef, &vibration_num);
2872 INF("vibrations: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2873 data_write_license(ef);
2874 INF("license: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2875 if (authors)
2876 {
2877 pending_threads++;
2878 if (threads)
2879 ecore_thread_run(data_thread_authors, data_thread_authors_end, NULL, ef);
2880 else
2881 {
2882 data_thread_authors(ef, NULL);
2883 data_thread_authors_end(ef, NULL);
2884 }
2885 }
2886 data_write_images();
2887 data_image_sets_init();
2888 INF("images: %3.5f", ecore_time_get() - t); t = ecore_time_get();
2889 pending_threads--;
2890 if (pending_threads + pending_image_threads > 0) ecore_main_loop_begin();
2891 INF("THREADS: %3.5f", ecore_time_get() - t);
2892 data_write_header(ef);
2893 if (pending_threads + pending_image_threads > 0) ecore_main_loop_begin();
2894 INF("THREADS: %3.5f", ecore_time_get() - t);
2895
2896 if (threads)
2897 {
2898 /* probably caught signal, exit immediately to avoid crash */
2899 if (pending_threads + pending_image_threads > 0) exit(-1);
2900 }
2901
2902 err = eet_close(ef);
2903 if (err)
2904 {
2905 ERR("Couldn't write file: \"%s\"", file_out);
2906 exit(-1);
2907 }
2908
2909 if (eina_log_domain_level_check(_edje_cc_log_dom, EINA_LOG_LEVEL_INFO))
2910 {
2911 printf("Summary:\n"
2912 " Wrote %i collections\n"
2913 " Wrote %i images\n"
2914 " Wrote %i sounds\n"
2915 " Wrote %i fonts\n"
2916 ,
2917 collection_num,
2918 image_num,
2919 sound_num,
2920 font_num);
2921 }
2922 }
2923
2924 void
reorder_parts(void)2925 reorder_parts(void)
2926 {
2927 Edje_Part_Collection *pc;
2928 Edje_Part **parts;
2929 Edje_Part_Parser *ep, *ep2;
2930 Eina_List *l;
2931
2932 /* sanity checks for parts and programs */
2933 EINA_LIST_FOREACH(edje_collections, l, pc)
2934 {
2935 unsigned int i, j, k;
2936 Eina_Bool found = EINA_FALSE;
2937
2938 for (i = 0; i < pc->parts_count; i++)
2939 {
2940 ep = (Edje_Part_Parser *)pc->parts[i];
2941 if (ep->reorder.insert_before && ep->reorder.insert_after)
2942 error_and_abort(NULL, "In group \"%s\": Unable to use together insert_before and insert_after in part \"%s\".",
2943 pc->part, pc->parts[i]->name);
2944
2945 if (ep->reorder.done)
2946 {
2947 continue;
2948 }
2949 if (ep->reorder.insert_before || ep->reorder.insert_after)
2950 {
2951 found = EINA_FALSE;
2952 for (j = 0; j < pc->parts_count; j++)
2953 {
2954 if (ep->reorder.insert_before &&
2955 !strcmp(ep->reorder.insert_before, pc->parts[j]->name))
2956 {
2957 ep2 = (Edje_Part_Parser *)pc->parts[j];
2958 if (ep2->reorder.after)
2959 error_and_abort(NULL, "In group \"%s\": The part \"%s\" is ambiguous ordered part.",
2960 pc->part, pc->parts[i]->name);
2961 if (ep2->reorder.linked_prev)
2962 error_and_abort(NULL, "In group \"%s\": Unable to insert two or more parts in same part \"%s\".",
2963 pc->part, pc->parts[j]->name);
2964 /* Need it to be able to insert an element before the first */
2965 if (j == 0) k = 0;
2966 else k = j - 1;
2967 found = EINA_TRUE;
2968 ep2->reorder.linked_prev += ep->reorder.linked_prev + 1;
2969 ep->reorder.before = (Edje_Part_Parser *)pc->parts[j];
2970 while (ep2->reorder.before)
2971 {
2972 ep2->reorder.before->reorder.linked_prev = ep2->reorder.linked_prev + 1;
2973 ep2 = ep2->reorder.before;
2974 }
2975 break;
2976 }
2977 else if (ep->reorder.insert_after &&
2978 !strcmp(ep->reorder.insert_after, pc->parts[j]->name))
2979 {
2980 ep2 = (Edje_Part_Parser *)pc->parts[j];
2981 if (ep2->reorder.before)
2982 error_and_abort(NULL, "In group \"%s\": The part \"%s\" is ambiguous ordered part.",
2983 pc->part, pc->parts[i]->name);
2984 if (ep2->reorder.linked_next)
2985 error_and_abort(NULL, "In group \"%s\": Unable to insert two or more parts in same part \"%s\".",
2986 pc->part, pc->parts[j]->name);
2987 k = j;
2988 found = EINA_TRUE;
2989 ep2->reorder.linked_next += ep->reorder.linked_next + 1;
2990 ep->reorder.after = (Edje_Part_Parser *)pc->parts[j];
2991 while (ep2->reorder.after)
2992 {
2993 ep2->reorder.after->reorder.linked_next = ep2->reorder.linked_next + 1;
2994 ep2 = ep2->reorder.after;
2995 }
2996 break;
2997 }
2998 }
2999 if (found)
3000 {
3001 unsigned int amount, linked;
3002
3003 if (((i > k) && ((i - ep->reorder.linked_prev) <= k))
3004 || ((i < k) && ((i + ep->reorder.linked_next) >= k)))
3005 error_and_abort(NULL, "In group \"%s\": The part order is wrong. It has circular dependency.", pc->part);
3006
3007 amount = ep->reorder.linked_prev + ep->reorder.linked_next + 1;
3008 linked = i - ep->reorder.linked_prev;
3009 parts = malloc(amount * sizeof(Edje_Part *));
3010 for (j = 0; j < amount; j++)
3011 {
3012 parts[j] = pc->parts[linked];
3013 linked++;
3014 }
3015 if (i > k)
3016 {
3017 for (j = i - ep->reorder.linked_prev; j > k; j--)
3018 {
3019 pc->parts[j + amount - 1] = pc->parts[j - 1];
3020 pc->parts[j + amount - 1]->id = j + amount - 1;
3021 }
3022 for (j = 0; j < amount; j++)
3023 {
3024 pc->parts[j + k] = parts[j];
3025 pc->parts[j + k]->id = j + k;
3026 }
3027 }
3028 else if (i < k)
3029 {
3030 for (j = i + ep->reorder.linked_next + 1; j <= k; j++)
3031 {
3032 pc->parts[j - amount] = pc->parts[j];
3033 pc->parts[j - amount]->id = j - amount;
3034 }
3035 for (j = 0; j < amount; j++)
3036 {
3037 pc->parts[j + k - amount + 1] = parts[j];
3038 pc->parts[j + k - amount + 1]->id = j + k - amount + 1;
3039 }
3040 i -= amount;
3041 }
3042 ep->reorder.done = EINA_TRUE;
3043 free(parts);
3044 }
3045 else
3046 {
3047 if (ep->reorder.insert_before)
3048 error_and_abort(NULL, "In group \"%s\": Unable to find part \"%s\" for insert_before in part \"%s\".",
3049 pc->part, ep->reorder.insert_before, pc->parts[i]->name);
3050 else
3051 error_and_abort(NULL, "In group \"%s\": Unable to find part \"%s\" for insert_after in part \"%s\".",
3052 pc->part, ep->reorder.insert_after, pc->parts[i]->name);
3053 }
3054 }
3055 }
3056 }
3057 }
3058
3059 void
data_queue_group_lookup(const char * name,Edje_Part * part)3060 data_queue_group_lookup(const char *name, Edje_Part *part)
3061 {
3062 Group_Lookup *gl;
3063
3064 if (!name || !name[0]) return;
3065
3066 gl = mem_alloc(SZ(Group_Lookup));
3067 group_lookups = eina_list_append(group_lookups, gl);
3068 gl->name = mem_strdup(name);
3069 gl->part = part;
3070 }
3071
3072 void
data_queue_face_group_lookup(const char * name)3073 data_queue_face_group_lookup(const char *name)
3074 {
3075 char *group_name;
3076
3077 if (!name || !name[0]) return;
3078
3079 group_name = mem_strdup(name);
3080 face_group_lookups = eina_list_append(face_group_lookups, group_name);
3081 }
3082
3083 void
data_queue_part_lookup(Edje_Part_Collection * pc,const char * name,int * dest)3084 data_queue_part_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
3085 {
3086 data_queue_part_nest_lookup(pc, name, dest, NULL);
3087 }
3088
3089 void
data_queue_part_nest_lookup(Edje_Part_Collection * pc,const char * name,int * dest,char ** dest2)3090 data_queue_part_nest_lookup(Edje_Part_Collection *pc, const char *name, int *dest, char **dest2)
3091 {
3092 Part_Lookup_Key key;
3093 Part_Lookup *pl = NULL;
3094 Eina_List *list;
3095 key.pc = pc;
3096 key.mem.dest = dest;
3097 key.stable = EINA_TRUE;
3098
3099 pl = eina_hash_find(part_pc_dest_lookup, &key);
3100 if (pl)
3101 {
3102 if (name[0])
3103 {
3104 free(pl->name);
3105 pl->name = mem_strdup(name);
3106 }
3107 else
3108 {
3109 list = eina_hash_find(part_dest_lookup, &pl->key);
3110 list = eina_list_remove(list, pl);
3111 eina_hash_set(part_dest_lookup, &pl->key, list);
3112 eina_hash_del(part_pc_dest_lookup, &key, pl);
3113 }
3114 return;
3115 }
3116
3117 if (!name[0]) return;
3118
3119 pl = mem_alloc(SZ(Part_Lookup));
3120 pl->name = mem_strdup(name);
3121 pl->key.pc = pc;
3122 pl->key.mem.dest = dest;
3123 pl->key.dest2 = dest2;
3124 pl->key.stable = EINA_TRUE;
3125
3126 eina_hash_add(part_pc_dest_lookup, &key, pl);
3127
3128 list = eina_hash_find(part_dest_lookup, &pl->key);
3129 list = eina_list_prepend(list, pl);
3130 eina_hash_set(part_dest_lookup, &pl->key, list);
3131 }
3132
3133 void
data_queue_part_reallocated_lookup(Edje_Part_Collection * pc,const char * name,unsigned char ** base,int offset)3134 data_queue_part_reallocated_lookup(Edje_Part_Collection *pc, const char *name,
3135 unsigned char **base, int offset)
3136 {
3137 Part_Lookup_Key key;
3138 Part_Lookup *pl = NULL;
3139 Eina_List *list;
3140 key.pc = pc;
3141 key.mem.reallocated.base = base;
3142 key.mem.reallocated.offset = offset;
3143 key.stable = EINA_FALSE;
3144
3145 pl = eina_hash_find(part_pc_dest_lookup, &key);
3146 if (pl)
3147 {
3148 if (name[0])
3149 {
3150 free(pl->name);
3151 pl->name = mem_strdup(name);
3152 }
3153 else
3154 {
3155 list = eina_hash_find(part_dest_lookup, &pl->key);
3156 list = eina_list_remove(list, pl);
3157 eina_hash_set(part_dest_lookup, &pl->key, list);
3158 eina_hash_del(part_pc_dest_lookup, &key, pl);
3159 }
3160 return;
3161 }
3162
3163 if (!name[0]) return;
3164
3165 pl = mem_alloc(SZ(Part_Lookup));
3166 pl->name = mem_strdup(name);
3167 pl->key.pc = pc;
3168 pl->key.mem.reallocated.base = base;
3169 pl->key.mem.reallocated.offset = offset;
3170 pl->key.stable = EINA_FALSE;
3171
3172 eina_hash_add(part_pc_dest_lookup, &key, pl);
3173
3174 list = eina_hash_find(part_dest_lookup, &pl->key);
3175 list = eina_list_prepend(list, pl);
3176 eina_hash_set(part_dest_lookup, &pl->key, list);
3177 }
3178
3179 void
part_lookup_del(Edje_Part_Collection * pc,int * dest)3180 part_lookup_del(Edje_Part_Collection *pc, int *dest)
3181 {
3182 Part_Lookup_Key key;
3183 Part_Lookup *pl = NULL;
3184 Eina_List *list;
3185 key.pc = pc;
3186 key.mem.dest = dest;
3187 key.stable = EINA_TRUE;
3188
3189 pl = eina_hash_find(part_pc_dest_lookup, &key);
3190 if (!pl) return;
3191 list = eina_hash_find(part_dest_lookup, &pl->key);
3192 if (list)
3193 eina_hash_del(part_dest_lookup, &pl->key, list);
3194 eina_hash_del(part_pc_dest_lookup, &key, pl);
3195 }
3196
3197 void
part_lookup_delete(Edje_Part_Collection * pc,const char * name,int * dest,char ** dest2)3198 part_lookup_delete(Edje_Part_Collection *pc, const char *name, int *dest, char **dest2)
3199 {
3200 Part_Lookup_Key key;
3201 Part_Lookup *pl = NULL;
3202 Part_Lookup *lpl;
3203 Eina_List *list, *l, *ll;
3204 key.pc = pc;
3205 key.mem.dest = dest;
3206 key.stable = EINA_TRUE;
3207
3208 pl = eina_hash_find(part_pc_dest_lookup, &key);
3209 if (!pl) return;
3210 list = eina_hash_find(part_dest_lookup, &pl->key);
3211 EINA_LIST_FOREACH_SAFE(list, l, ll, lpl)
3212 {
3213 if (strcmp(lpl->name, name) || (lpl->key.dest2 != dest2)) continue;
3214 free(lpl->name);
3215 list = eina_list_remove_list(list, l);
3216 free(lpl);
3217 }
3218 eina_hash_set(part_dest_lookup, &pl->key, list);
3219 }
3220
3221 void
data_queue_copied_part_lookup(Edje_Part_Collection * pc,int * src,int * dest)3222 data_queue_copied_part_lookup(Edje_Part_Collection *pc, int *src, int *dest)
3223 {
3224 data_queue_copied_part_nest_lookup(pc, src, dest, NULL);
3225 }
3226
3227 void
data_queue_copied_part_nest_lookup(Edje_Part_Collection * pc,int * src,int * dest,char ** dest2)3228 data_queue_copied_part_nest_lookup(Edje_Part_Collection *pc, int *src, int *dest, char **dest2)
3229 {
3230 Eina_List *list;
3231 Eina_List *l;
3232 Part_Lookup *pl;
3233 Part_Lookup_Key key;
3234
3235 key.pc = NULL;
3236 key.mem.dest = src;
3237 key.stable = EINA_TRUE;
3238
3239 list = eina_hash_find(part_dest_lookup, &key);
3240 EINA_LIST_FOREACH(list, l, pl)
3241 if (pl->key.stable)
3242 data_queue_part_nest_lookup(pc, pl->name, dest, dest2);
3243 }
3244
3245 void
data_queue_anonymous_lookup(Edje_Part_Collection * pc,Edje_Program * ep,int * dest)3246 data_queue_anonymous_lookup(Edje_Part_Collection *pc, Edje_Program *ep, int *dest)
3247 {
3248 Eina_List *l, *l1, *l2, *l3;
3249 Program_Lookup *pl;
3250
3251 if (!ep) return; /* FIXME: should we stop compiling ? */
3252
3253 EINA_LIST_FOREACH_SAFE(program_lookups, l, l1, pl)
3254 {
3255 if (pl->u.ep == ep)
3256 {
3257 Code *cd;
3258 Code_Program *cp;
3259
3260 cd = eina_list_data_get(eina_list_last(codes));
3261
3262 EINA_LIST_FOREACH_SAFE(cd->programs, l2, l3, cp)
3263 {
3264 if (&(cp->id) == pl->dest)
3265 {
3266 cd->programs = eina_list_remove_list(cd->programs, l2);
3267 free(cp);
3268 cp = NULL;
3269 }
3270 }
3271 program_lookups = eina_list_remove_list(program_lookups, l);
3272 free(pl);
3273 }
3274 }
3275
3276 if (dest)
3277 {
3278 pl = mem_alloc(SZ(Program_Lookup));
3279 program_lookups = eina_list_append(program_lookups, pl);
3280 pl->pc = pc;
3281 pl->u.ep = ep;
3282 pl->dest = dest;
3283 pl->anonymous = EINA_TRUE;
3284 }
3285 }
3286
3287 void
copied_program_anonymous_lookup_delete(Edje_Part_Collection * pc,int * dest)3288 copied_program_anonymous_lookup_delete(Edje_Part_Collection *pc, int *dest)
3289 {
3290 Program_Lookup *pl;
3291 Eina_List *l, *ll;
3292
3293 EINA_LIST_FOREACH_SAFE(program_lookups, l, ll, pl)
3294 {
3295 if ((!pl->anonymous) || (pl->pc != pc) || (dest != &pl->u.ep->id)) continue;
3296 program_lookups = eina_list_remove_list(program_lookups, l);
3297
3298 Code *cd;
3299 Code_Program *cp;
3300 Edje_Part_Collection_Directory_Entry *de;
3301 Eina_List *l2, *ll2;
3302
3303 de = eina_hash_find(edje_file->collection, pl->pc->part);
3304 cd = eina_list_nth(codes, de->id);
3305
3306 EINA_LIST_FOREACH_SAFE(cd->programs, l2, ll2, cp)
3307 {
3308 if (pl->dest == &cp->id)
3309 {
3310 cd->programs = eina_list_remove_list(cd->programs, l2);
3311 free(cp);
3312 break;
3313 }
3314 }
3315
3316 free(pl);
3317 }
3318 }
3319
3320 void
data_queue_copied_anonymous_lookup(Edje_Part_Collection * pc,int * src,int * dest)3321 data_queue_copied_anonymous_lookup(Edje_Part_Collection *pc, int *src, int *dest)
3322 {
3323 Eina_List *l;
3324 Program_Lookup *pl;
3325 unsigned int i;
3326
3327 EINA_LIST_FOREACH(program_lookups, l, pl)
3328 {
3329 if (pl->dest == src && pl->u.ep->name)
3330 {
3331 for (i = 0; i < pc->programs.fnmatch_count; i++)
3332 {
3333 if (pc->programs.fnmatch[i]->name &&
3334 !strcmp(pl->u.ep->name, pc->programs.fnmatch[i]->name))
3335 data_queue_anonymous_lookup(pc, pc->programs.fnmatch[i], dest);
3336 }
3337 for (i = 0; i < pc->programs.strcmp_count; i++)
3338 {
3339 if (pc->programs.strcmp[i]->name &&
3340 !strcmp(pl->u.ep->name, pc->programs.strcmp[i]->name))
3341 data_queue_anonymous_lookup(pc, pc->programs.strcmp[i], dest);
3342 }
3343 for (i = 0; i < pc->programs.strncmp_count; i++)
3344 {
3345 if (pc->programs.strncmp[i]->name &&
3346 !strcmp(pl->u.ep->name, pc->programs.strncmp[i]->name))
3347 data_queue_anonymous_lookup(pc, pc->programs.strncmp[i], dest);
3348 }
3349 for (i = 0; i < pc->programs.strrncmp_count; i++)
3350 {
3351 if (pc->programs.strrncmp[i]->name &&
3352 !strcmp(pl->u.ep->name, pc->programs.strrncmp[i]->name))
3353 data_queue_anonymous_lookup(pc, pc->programs.strrncmp[i], dest);
3354 }
3355 for (i = 0; i < pc->programs.nocmp_count; i++)
3356 {
3357 if (pc->programs.nocmp[i]->name &&
3358 !strcmp(pl->u.ep->name, pc->programs.nocmp[i]->name))
3359 data_queue_anonymous_lookup(pc, pc->programs.nocmp[i], dest);
3360 }
3361 }
3362 }
3363 }
3364
3365 void *
data_queue_program_lookup(Edje_Part_Collection * pc,const char * name,int * dest)3366 data_queue_program_lookup(Edje_Part_Collection *pc, const char *name, int *dest)
3367 {
3368 Program_Lookup *pl;
3369 Edje_Part_Collection_Parser *pcp = (Edje_Part_Collection_Parser *)pc;
3370
3371 if (pcp->inherit_only && (!current_group_inherit)) return NULL;
3372
3373 if (!name) return NULL; /* FIXME: should we stop compiling ? */
3374
3375 pl = mem_alloc(SZ(Program_Lookup));
3376 program_lookups = eina_list_append(program_lookups, pl);
3377 pl->pc = pc;
3378 pl->u.name = mem_strdup(name);
3379 pl->dest = dest;
3380 pl->anonymous = EINA_FALSE;
3381 return pl;
3382 }
3383
3384 void
program_lookup_rename(void * p,const char * name)3385 program_lookup_rename(void *p, const char *name)
3386 {
3387 Program_Lookup *pl = p;
3388
3389 free(pl->u.name);
3390 pl->u.name = strdup(name);
3391 }
3392
3393 void
copied_program_lookup_delete(Edje_Part_Collection * pc,const char * name)3394 copied_program_lookup_delete(Edje_Part_Collection *pc, const char *name)
3395 {
3396 Program_Lookup *pl;
3397 Eina_List *l, *ll;
3398
3399 EINA_LIST_FOREACH_SAFE(program_lookups, l, ll, pl)
3400 {
3401 if (pl->anonymous || (pl->pc != pc) || strcmp(pl->u.name, name)) continue;
3402 free(pl->u.name);
3403 program_lookups = eina_list_remove_list(program_lookups, l);
3404 free(pl);
3405 }
3406 }
3407
3408 Eina_Bool
data_queue_copied_program_lookup(Edje_Part_Collection * pc,int * src,int * dest)3409 data_queue_copied_program_lookup(Edje_Part_Collection *pc, int *src, int *dest)
3410 {
3411 Eina_List *l;
3412 Program_Lookup *pl;
3413
3414 EINA_LIST_FOREACH(program_lookups, l, pl)
3415 {
3416 if (pl->dest == src)
3417 {
3418 data_queue_program_lookup(pc, pl->u.name, dest);
3419 return EINA_TRUE;
3420 }
3421 }
3422 return EINA_FALSE;
3423 }
3424
3425 void
data_queue_image_lookup(char * name,int * dest,Eina_Bool * set)3426 data_queue_image_lookup(char *name, int *dest, Eina_Bool *set)
3427 {
3428 Image_Lookup *il;
3429
3430 il = mem_alloc(SZ(Image_Lookup));
3431 image_lookups = eina_list_append(image_lookups, il);
3432 il->name = mem_strdup(name);
3433 il->dest = dest;
3434 il->set = set;
3435 }
3436
3437 void
data_queue_image_remove(int * dest,Eina_Bool * set)3438 data_queue_image_remove(int *dest, Eina_Bool *set)
3439 {
3440 Eina_List *l;
3441 Image_Lookup *il;
3442
3443 EINA_LIST_FOREACH(image_lookups, l, il)
3444 {
3445 if (il->dest == dest && il->set == set)
3446 {
3447 image_lookups = eina_list_remove_list(image_lookups, l);
3448 free(il->name);
3449 free(il);
3450 return;
3451 }
3452 }
3453 }
3454
3455 void
data_queue_copied_image_lookup(int * src,int * dest,Eina_Bool * set)3456 data_queue_copied_image_lookup(int *src, int *dest, Eina_Bool *set)
3457 {
3458 Eina_List *l;
3459 Image_Lookup *il;
3460
3461 EINA_LIST_FOREACH(image_lookups, l, il)
3462 {
3463 if (il->dest == src)
3464 data_queue_image_lookup(il->name, dest, set);
3465 }
3466 }
3467
3468 static Eina_Bool
data_process_part_set(Part_Lookup * target,int value)3469 data_process_part_set(Part_Lookup *target, int value)
3470 {
3471 if (target->key.stable)
3472 {
3473 *(target->key.mem.dest) = value;
3474 if (target->key.dest2) return EINA_TRUE;
3475 }
3476 else
3477 {
3478 *((int *)(*target->key.mem.reallocated.base +
3479 target->key.mem.reallocated.offset)) = value;
3480 }
3481 return EINA_FALSE;
3482 }
3483
3484 static int
_data_image_w_size_compare_cb(const void * data1,const void * data2)3485 _data_image_w_size_compare_cb(const void *data1, const void *data2)
3486 {
3487 const Edje_Image_Directory_Set_Entry *img1 = data1;
3488 const Edje_Image_Directory_Set_Entry *img2 = data2;
3489
3490 if (img1->size.w < img2->size.w) return -1;
3491 if (img1->size.w > img2->size.w) return 1;
3492
3493 return 0;
3494 }
3495
3496 static int
_data_image_h_size_compare_cb(const void * data1,const void * data2)3497 _data_image_h_size_compare_cb(const void *data1, const void *data2)
3498 {
3499 const Edje_Image_Directory_Set_Entry *img1 = data1;
3500 const Edje_Image_Directory_Set_Entry *img2 = data2;
3501
3502 if (img1->size.h < img2->size.h) return -1;
3503 if (img1->size.h > img2->size.h) return 1;
3504
3505 return 0;
3506 }
3507
3508 static void
_data_image_sets_size_set(void)3509 _data_image_sets_size_set(void)
3510 {
3511 Evas *evas;
3512 Edje_Image_Directory_Set *set;
3513 Edje_Image_Directory_Set_Entry *simg, *preimg;
3514 Eina_List *l, *entries;
3515 unsigned int i;
3516
3517 if (!buffer_ee)
3518 buffer_ee = ecore_evas_buffer_new(1, 1);
3519 if (!buffer_ee)
3520 {
3521 ERR("Cannot create buffer engine canvas for image load.");
3522 exit(-1);
3523 }
3524 evas = ecore_evas_get(buffer_ee);
3525
3526 for (i = 0; i < edje_file->image_dir->sets_count; i++)
3527 {
3528 set = edje_file->image_dir->sets + i;
3529
3530 if (!set->entries) continue;
3531 EINA_LIST_FOREACH(set->entries, l, simg)
3532 {
3533 Evas_Object *im;
3534 Eina_List *ll;
3535 char *s;
3536
3537 im = evas_object_image_add(evas);
3538 EINA_LIST_FOREACH(img_dirs, ll, s)
3539 {
3540 char buf[PATH_MAX];
3541 int load_err = EVAS_LOAD_ERROR_NONE;
3542
3543 snprintf(buf, sizeof(buf), "%s/%s", s, simg->name);
3544 evas_object_image_file_set(im, buf, NULL);
3545 load_err = evas_object_image_load_error_get(im);
3546 if (load_err == EVAS_LOAD_ERROR_NONE)
3547 {
3548 evas_object_image_size_get(im, &simg->size.w, &simg->size.h);
3549 break;
3550 }
3551 }
3552 evas_object_del(im);
3553 }
3554
3555 entries = eina_list_clone(set->entries);
3556
3557 entries = eina_list_sort(entries, 0, _data_image_w_size_compare_cb);
3558 preimg = eina_list_data_get(entries);
3559 EINA_LIST_FOREACH(entries, l, simg)
3560 {
3561 if (simg == preimg) continue;
3562 if (!(preimg->size.max.w) && !(simg->size.min.w))
3563 {
3564 preimg->size.max.w = (preimg->size.w + simg->size.w) / 2;
3565 simg->size.min.w = preimg->size.max.w + 1;
3566 if (simg->size.min.w <= (simg->border.l + simg->border.r))
3567 {
3568 preimg->size.max.w = simg->border.l + simg->border.r;
3569 simg->size.min.w = preimg->size.max.w + 1;
3570 }
3571 }
3572 else if (preimg->size.max.w && !(simg->size.min.w))
3573 simg->size.min.w = preimg->size.max.w + 1;
3574 else if (!(preimg->size.max.w) && simg->size.min.w)
3575 preimg->size.max.w = simg->size.min.w - 1;
3576 preimg = simg;
3577 }
3578 simg = eina_list_data_get(eina_list_last(entries));
3579 if (!(simg->size.max.w)) simg->size.max.w = 99999;
3580
3581 entries = eina_list_sort(entries, 0, _data_image_h_size_compare_cb);
3582 preimg = eina_list_data_get(entries);
3583 EINA_LIST_FOREACH(entries, l, simg)
3584 {
3585 if (simg == preimg) continue;
3586 if (!(preimg->size.max.h) && !(simg->size.min.h))
3587 {
3588 preimg->size.max.h = (preimg->size.h + simg->size.h) / 2;
3589 simg->size.min.h = preimg->size.max.h + 1;
3590 if (simg->size.min.h <= (simg->border.t + simg->border.b))
3591 {
3592 preimg->size.max.h = simg->border.t + simg->border.b;
3593 simg->size.min.h = preimg->size.max.h + 1;
3594 }
3595 }
3596 else if (preimg->size.max.h && !(simg->size.min.h))
3597 simg->size.min.h = preimg->size.max.h + 1;
3598 else if (!(preimg->size.max.h) && simg->size.min.h)
3599 preimg->size.max.h = simg->size.min.h - 1;
3600 preimg = simg;
3601 }
3602 simg = eina_list_data_get(eina_list_last(entries));
3603 if (!(simg->size.max.h)) simg->size.max.h = 99999;
3604
3605 eina_list_free(entries);
3606 }
3607 }
3608
3609 static void
_data_image_id_update(Eina_List * images_unused_list)3610 _data_image_id_update(Eina_List *images_unused_list)
3611 {
3612 Image_Unused_Ids *iui;
3613 Edje_Part_Collection *pc;
3614 Edje_Part *part;
3615 Edje_Part_Description_Image *part_desc_image;
3616 Edje_Part_Image_Id *tween_id;
3617 unsigned int i, j, desc_it;
3618 Eina_List *l, *l2, *l3;
3619
3620 #define PART_DESC_IMAGE_ID_UPDATE \
3621 EINA_LIST_FOREACH(images_unused_list, l3, iui) \
3622 { \
3623 if ((iui) && (part_desc_image->image.id == iui->old_id)) \
3624 { \
3625 part_desc_image->image.id = iui->new_id; \
3626 break; \
3627 } \
3628 } \
3629 for (desc_it = 0; desc_it < part_desc_image->image.tweens_count; desc_it++) \
3630 { \
3631 tween_id = part_desc_image->image.tweens[desc_it]; \
3632 EINA_LIST_FOREACH(images_unused_list, l3, iui) \
3633 { \
3634 if ((iui) && (tween_id->id == iui->old_id)) \
3635 { \
3636 tween_id->id = iui->new_id; \
3637 break; \
3638 } \
3639 } \
3640 }
3641
3642 EINA_LIST_FOREACH_SAFE(edje_collections, l, l2, pc)
3643 {
3644 for (i = 0; i < pc->parts_count; i++)
3645 {
3646 part = pc->parts[i];
3647 if (part->type == EDJE_PART_TYPE_IMAGE)
3648 {
3649 part_desc_image = (Edje_Part_Description_Image *)part->default_desc;
3650 if (!part_desc_image) continue;
3651 PART_DESC_IMAGE_ID_UPDATE
3652 for (j = 0; j < part->other.desc_count; j++)
3653 {
3654 part_desc_image = (Edje_Part_Description_Image *)part->other.desc[j];
3655 PART_DESC_IMAGE_ID_UPDATE
3656 }
3657 }
3658 }
3659 }
3660 for (i = 0; i < edje_file->image_dir->sets_count; i++)
3661 {
3662 Eina_List *entries, *list;
3663 Edje_Image_Directory_Set_Entry *entry;
3664
3665 entries = edje_file->image_dir->sets[i].entries;
3666 EINA_LIST_FOREACH(entries, list, entry)
3667 {
3668 EINA_LIST_FOREACH(images_unused_list, l3, iui)
3669 {
3670 if ((iui) && (entry->id == iui->old_id))
3671 {
3672 entry->id = iui->new_id;
3673 break;
3674 }
3675 }
3676 }
3677 }
3678 }
3679
3680 void
data_process_lookups(void)3681 data_process_lookups(void)
3682 {
3683 Edje_Part_Collection *pc;
3684 Eina_Iterator *it;
3685 Part_Lookup *part;
3686 Program_Lookup *program;
3687 Group_Lookup *group;
3688 Image_Lookup *image;
3689 Eina_List *l2;
3690 Eina_List *l;
3691 Eina_Hash *images_in_use;
3692 char *group_name;
3693 Eina_Bool is_lua = EINA_FALSE;
3694 Image_Unused_Ids *iui;
3695
3696 /* remove all unreferenced Edje_Part_Collection */
3697 EINA_LIST_FOREACH_SAFE(edje_collections, l, l2, pc)
3698 {
3699 Edje_Part_Collection_Directory_Entry *alias;
3700 Edje_Part_Collection_Directory_Entry *find;
3701 Eina_List *l3;
3702 unsigned int id = 0;
3703 unsigned int i;
3704
3705 if (!pc->part)
3706 {
3707 ERR("A collection without a name was detected, that's not allowed.");
3708 exit(-1);
3709 }
3710
3711 find = eina_hash_find(edje_file->collection, pc->part);
3712 if (find && find->id == pc->id)
3713 {
3714 if (((Edje_Part_Collection_Parser *)pc)->inherit_only)
3715 eina_hash_del_by_data(edje_file->collection, find);
3716 else
3717 continue;
3718 }
3719
3720 EINA_LIST_FOREACH(aliases, l3, alias)
3721 if (alias->id == pc->id)
3722 continue;
3723
3724 /* This Edje_Part_Collection is not used at all */
3725 edje_collections = eina_list_remove_list(edje_collections, l);
3726 l3 = eina_list_nth_list(codes, pc->id);
3727 codes = eina_list_remove_list(codes, l3);
3728
3729 /* Unref all image used by that group */
3730 for (i = 0; i < pc->parts_count; ++i)
3731 part_description_image_cleanup(pc->parts[i]);
3732
3733 /* Correct all id */
3734 EINA_LIST_FOREACH(edje_collections, l3, pc)
3735 {
3736 Eina_List *l4;
3737 Edje_Part_Collection_Directory_Entry *de;
3738
3739 /* Some group could be removed from the collection, but still be referenced by alias */
3740 /* Update all matching alias */
3741 EINA_LIST_FOREACH(aliases, l4, alias)
3742 if (pc->id == alias->id)
3743 alias->id = id;
3744
3745 find = eina_hash_find(edje_file->collection, pc->part);
3746 if (pc->id != find->id) find = NULL;
3747
3748 de = eina_hash_find(edje_collections_lookup, &pc->id);
3749 eina_hash_set(edje_collections_lookup, &pc->id, NULL);
3750 de->id = pc->id = id++;
3751 eina_hash_set(edje_collections_lookup, &pc->id, de);
3752 if (find) find->id = pc->id;
3753 }
3754 }
3755
3756 EINA_LIST_FOREACH(edje_collections, l, pc)
3757 {
3758 unsigned int count = 0;
3759 unsigned int i;
3760
3761 if (pc->lua_script_only)
3762 is_lua = EINA_TRUE;
3763 #define PROGRAM_ID_SET(Type, Pc, It, Count) \
3764 for (It = 0; It < Pc->programs.Type ## _count; ++It) \
3765 { \
3766 Pc->programs.Type[It]->id = Count++; \
3767 }
3768
3769 PROGRAM_ID_SET(fnmatch, pc, i, count);
3770 PROGRAM_ID_SET(strcmp, pc, i, count);
3771 PROGRAM_ID_SET(strncmp, pc, i, count);
3772 PROGRAM_ID_SET(strrncmp, pc, i, count);
3773 PROGRAM_ID_SET(nocmp, pc, i, count);
3774
3775 #undef PROGRAM_ID_SET
3776 }
3777
3778 it = eina_hash_iterator_data_new(part_pc_dest_lookup);
3779 EINA_ITERATOR_FOREACH(it, part)
3780 {
3781 Edje_Part *ep;
3782 unsigned int i;
3783
3784 if (!strcmp(part->name, "-"))
3785 {
3786 data_process_part_set(part, -1);
3787 }
3788 else
3789 {
3790 char *alias, *ap;
3791
3792 alias = eina_hash_find(part->key.pc->alias, part->name);
3793 if (!alias)
3794 alias = part->name;
3795 ap = strchr(alias, EDJE_PART_PATH_SEPARATOR);
3796 if (ap)
3797 {
3798 char *tmp;
3799
3800 tmp = alloca(strlen(alias) + 1);
3801 memcpy(tmp, alias, ap - alias);
3802 tmp[ap - alias] = 0;
3803 ap += 1;
3804 alias = tmp;
3805 }
3806 for (i = 0; i < part->key.pc->parts_count; ++i)
3807 {
3808 ep = part->key.pc->parts[i];
3809
3810 if ((ep->name) && (!strcmp(ep->name, alias)))
3811 {
3812 if (data_process_part_set(part, ep->id))
3813 *part->key.dest2 = ap;
3814 break;
3815 }
3816 }
3817
3818 if ((i == part->key.pc->parts_count) && (!((Edje_Part_Collection_Parser *)part->key.pc)->inherit_only))
3819 {
3820 ERR("Unable to find part name \"%s\" needed in group '%s'.",
3821 alias, part->key.pc->part);
3822 exit(-1);
3823 }
3824 }
3825 }
3826 eina_iterator_free(it);
3827 eina_hash_free(part_dest_lookup);
3828 eina_hash_free(part_pc_dest_lookup);
3829
3830 EINA_LIST_FREE(program_lookups, program)
3831 {
3832 unsigned int i;
3833 Eina_Bool find = EINA_FALSE;
3834
3835 #define PROGRAM_MATCH(Type, Pl, It) \
3836 for (It = 0; It < Pl->pc->programs.Type ## _count; ++It) \
3837 { \
3838 Edje_Program *ep; \
3839 \
3840 ep = Pl->pc->programs.Type[It]; \
3841 \
3842 if ((Pl->anonymous && ep == Pl->u.ep) || \
3843 ((!Pl->anonymous) && (ep->name) && (!strcmp(ep->name, Pl->u.name)))) \
3844 { \
3845 *(Pl->dest) = ep->id; \
3846 find = EINA_TRUE; \
3847 break; \
3848 } \
3849 }
3850
3851 PROGRAM_MATCH(fnmatch, program, i);
3852 PROGRAM_MATCH(strcmp, program, i);
3853 PROGRAM_MATCH(strncmp, program, i);
3854 PROGRAM_MATCH(strrncmp, program, i);
3855 PROGRAM_MATCH(nocmp, program, i);
3856
3857 #undef PROGRAM_MATCH
3858
3859 if (!find)
3860 {
3861 if (!program->anonymous)
3862 ERR("Unable to find program name \"%s\".",
3863 program->u.name);
3864 else
3865 ERR("Unable to find anonymous program.");
3866 exit(-1);
3867 }
3868
3869 if (!program->anonymous)
3870 free(program->u.name);
3871 free(program);
3872 }
3873
3874 groups_sourced = eina_hash_string_superfast_new(NULL);
3875 EINA_LIST_FREE(group_lookups, group)
3876 {
3877 Edje_Part_Collection_Directory_Entry *de;
3878
3879 if (group->part)
3880 {
3881 if (group->part->type != EDJE_PART_TYPE_GROUP
3882 && group->part->type != EDJE_PART_TYPE_TEXTBLOCK
3883 && group->part->type != EDJE_PART_TYPE_BOX
3884 && group->part->type != EDJE_PART_TYPE_TABLE)
3885 goto free_group;
3886 }
3887
3888 de = eina_hash_find(edje_file->collection, group->name);
3889
3890 if (!de)
3891 {
3892 Eina_Bool found = EINA_FALSE;
3893
3894 EINA_LIST_FOREACH(aliases, l, de)
3895 if (strcmp(de->entry, group->name) == 0)
3896 {
3897 found = EINA_TRUE;
3898 break;
3899 }
3900 if (!found) de = NULL;
3901 }
3902
3903 if (!de)
3904 {
3905 ERR("Unable to find group name \"%s\".", group->name);
3906 exit(-1);
3907 }
3908
3909 eina_hash_add(groups_sourced, group->name, (void*)1);
3910 free_group:
3911 free(group->name);
3912 free(group);
3913 }
3914
3915 EINA_LIST_FREE(face_group_lookups, group_name)
3916 {
3917 Edje_Part_Collection_Directory_Entry *de;
3918
3919 de = eina_hash_find(edje_file->collection, group_name);
3920
3921 if (!de)
3922 {
3923 Eina_Bool found = EINA_FALSE;
3924
3925 EINA_LIST_FOREACH(aliases, l, de)
3926 if (strcmp(de->entry, group_name) == 0)
3927 {
3928 found = EINA_TRUE;
3929 break;
3930 }
3931 if (!found) de = NULL;
3932 }
3933
3934 if (!de)
3935 {
3936 ERR("Unable to find group name \"%s\".", group_name);
3937 exit(-1);
3938 }
3939
3940 free(group_name);
3941 }
3942
3943 images_in_use = eina_hash_string_superfast_new(NULL);
3944
3945 EINA_LIST_FREE(image_lookups, image)
3946 {
3947 Eina_Bool find = EINA_FALSE;
3948
3949 if (edje_file->image_dir)
3950 {
3951 Edje_Image_Directory_Entry *de;
3952 unsigned int i;
3953
3954 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
3955 {
3956 de = edje_file->image_dir->entries + i;
3957
3958 if ((de->entry) && (!strcmp(de->entry, image->name)))
3959 {
3960 if (de->source_type >= EDJE_IMAGE_SOURCE_TYPE_USER)
3961 *(image->dest) = -de->id - 1;
3962 else
3963 *(image->dest) = de->id;
3964 *(image->set) = EINA_FALSE;
3965 find = EINA_TRUE;
3966
3967 if (!eina_hash_find(images_in_use, image->name))
3968 eina_hash_direct_add(images_in_use, de->entry, de);
3969 break;
3970 }
3971 }
3972
3973 if (!find)
3974 {
3975 Edje_Image_Directory_Set *set;
3976
3977 for (i = 0; i < edje_file->image_dir->sets_count; ++i)
3978 {
3979 set = edje_file->image_dir->sets + i;
3980
3981 if ((set->name) && (!strcmp(set->name, image->name)))
3982 {
3983 Edje_Image_Directory_Set_Entry *child;
3984 Eina_List *lc;
3985
3986 *(image->dest) = set->id;
3987 *(image->set) = EINA_TRUE;
3988 find = EINA_TRUE;
3989
3990 EINA_LIST_FOREACH(set->entries, lc, child)
3991 if (!eina_hash_find(images_in_use, child->name))
3992 eina_hash_direct_add(images_in_use, child->name, child);
3993
3994 if (!eina_hash_find(images_in_use, image->name))
3995 eina_hash_direct_add(images_in_use, set->name, set);
3996 break;
3997 }
3998 else
3999 *(image->set) = EINA_FALSE;
4000 }
4001 }
4002 }
4003
4004 if (!find)
4005 {
4006 ERR("Unable to find image name \"%s\".", image->name);
4007 exit(-1);
4008 }
4009
4010 free(image->name);
4011 free(image);
4012 }
4013
4014 if (edje_file->image_dir && !is_lua)
4015 {
4016 Edje_Image_Directory_Entry *de, *de_last, *img;
4017 Edje_Image_Directory_Set *set;
4018 Edje_Image_Directory_Set_Entry *set_e;
4019 Eina_List *images_unused_list = NULL;
4020 unsigned int i;
4021
4022 for (i = 0; i < edje_file->image_dir->entries_count; ++i)
4023 {
4024 de = edje_file->image_dir->entries + i;
4025
4026 if (de->entry && eina_hash_find(images_in_use, de->entry))
4027 continue;
4028
4029 printf("Warning: Image '%s' not used\n", de->entry);
4030 INF("Image '%s' in resource 'edje/image/%i' will not be included as it is unused.",
4031 de->entry, de->id);
4032
4033 // so as not to write the unused images, moved last image in the
4034 // list to unused image position and check it
4035 free((void *)de->entry);
4036 de->entry = NULL;
4037 de_last = edje_file->image_dir->entries + edje_file->image_dir->entries_count - 1;
4038 iui = mem_alloc(SZ(Image_Unused_Ids));
4039 iui->old_id = de_last->id;
4040 images_unused_list = eina_list_append(images_unused_list, iui);
4041 iui->new_id = i;
4042 de_last->id = i;
4043 memcpy(de, de_last, sizeof(Edje_Image_Directory_Entry));
4044 --i; // need to check a moved image on this index
4045 edje_file->image_dir->entries_count--;
4046 img = realloc(edje_file->image_dir->entries,
4047 sizeof (Edje_Image_Directory_Entry) * edje_file->image_dir->entries_count);
4048 edje_file->image_dir->entries = img;
4049 }
4050
4051 for (i = 0; i < edje_file->image_dir->sets_count; ++i)
4052 {
4053 set = edje_file->image_dir->sets + i;
4054
4055 if (set->name && eina_hash_find(images_in_use, set->name))
4056 continue;
4057
4058 printf("Warning: Image set '%s' not used\n", set->name);
4059 EINA_LIST_FOREACH(set->entries, l, set_e)
4060 {
4061 printf(" Contains '%s' size %ix%i -> %ix%i\n",
4062 set_e->name,
4063 set_e->size.min.w, set_e->size.min.h,
4064 set_e->size.max.w, set_e->size.max.h);
4065 }
4066 /* No need to redo id's - we will warn of unused images - fix in src
4067 * Also .. this is broken and messes up id's ... so easyer - complain
4068 * to develoepr to clean up the theme...
4069 INF("Set '%s' will not be included as it is unused.", set->name);
4070
4071 free((void *)set->name);
4072 EINA_LIST_FREE(set->entries, set_e)
4073 {
4074 free((void *)set_e->name);
4075 free(set_e);
4076 }
4077 set->entries = NULL;
4078 set_last = edje_file->image_dir->sets + edje_file->image_dir->sets_count - 1;
4079 iui = mem_alloc(SZ(Image_Unused_Ids));
4080 iui->old_id = set_last->id;
4081 images_unused_list = eina_list_append(images_unused_list, iui);
4082 iui->new_id = i;
4083 set_last->id = i;
4084 memcpy(set, set_last, sizeof(Edje_Image_Directory_Set));
4085 --i;
4086 edje_file->image_dir->sets_count--;
4087 set_realloc = realloc(edje_file->image_dir->sets,
4088 sizeof(Edje_Image_Directory_Set) * edje_file->image_dir->sets_count);
4089 edje_file->image_dir->sets = set_realloc;
4090 */
4091 }
4092
4093 /* update image id in parts */
4094 if (images_unused_list) _data_image_id_update(images_unused_list);
4095 EINA_LIST_FREE(images_unused_list, iui)
4096 free(iui);
4097
4098 _data_image_sets_size_set();
4099 }
4100
4101 eina_hash_free(images_in_use);
4102 }
4103
4104 static void
data_process_string(Edje_Part_Collection * pc,const char * prefix,char * s,void (* func)(Edje_Part_Collection * pc,char * name,char * ptr,int len))4105 data_process_string(Edje_Part_Collection *pc, const char *prefix, char *s, void (*func)(Edje_Part_Collection *pc, char *name, char *ptr, int len))
4106 {
4107 char *p;
4108 char *key;
4109 int keyl;
4110 int quote, escape;
4111
4112 keyl = strlen(prefix) + 2;
4113 key = alloca(keyl + 1);
4114 if (!key) return;
4115 strcpy(key, prefix);
4116 strcat(key, ":\"");
4117 quote = 0;
4118 escape = 0;
4119 for (p = s; (p) && (*p); p++)
4120 {
4121 if (!quote)
4122 {
4123 if (*p == '\"')
4124 {
4125 quote = 1;
4126 p++;
4127 }
4128 }
4129 if (!quote)
4130 {
4131 if (!strncmp(p, key, keyl))
4132 {
4133 char *ptr;
4134 int len;
4135 int inesc = 0;
4136 char *name;
4137
4138 ptr = p;
4139 p += keyl;
4140 while ((*p))
4141 {
4142 if (!inesc)
4143 {
4144 if (*p == '\\') inesc = 1;
4145 else if (*p == '\"')
4146 {
4147 /* string concatenation, see below */
4148 if (*(p + 1) != '\"')
4149 break;
4150 else
4151 p++;
4152 }
4153 }
4154 else
4155 inesc = 0;
4156 p++;
4157 }
4158 len = p - ptr + 1;
4159 name = alloca(len);
4160 if (name)
4161 {
4162 char *pp;
4163 int i;
4164
4165 name[0] = 0;
4166 pp = ptr + keyl;
4167 inesc = 0;
4168 i = 0;
4169 while (*pp)
4170 {
4171 if (!inesc)
4172 {
4173 if (*pp == '\\') inesc = 1;
4174 else if (*pp == '\"')
4175 {
4176 /* concat strings like "foo""bar" to "foobar" */
4177 if (*(pp + 1) == '\"')
4178 pp++;
4179 else
4180 {
4181 name[i] = 0;
4182 break;
4183 }
4184 }
4185 else
4186 {
4187 name[i] = *pp;
4188 name[i + 1] = 0;
4189 i++;
4190 }
4191 }
4192 else
4193 inesc = 0;
4194 pp++;
4195 }
4196 func(pc, name, ptr, len);
4197 }
4198 }
4199 }
4200 else
4201 {
4202 if (!escape)
4203 {
4204 if (*p == '\"') quote = 0;
4205 else if (*p == '\\')
4206 escape = 1;
4207 }
4208 else if (escape)
4209 {
4210 escape = 0;
4211 }
4212 }
4213 }
4214 }
4215
4216 static void
_data_queue_part_lookup(Edje_Part_Collection * pc,char * name,char * ptr,int len)4217 _data_queue_part_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
4218 {
4219 Code_Lookup *cl;
4220
4221 cl = mem_alloc(SZ(Code_Lookup));
4222 cl->ptr = ptr;
4223 cl->len = len;
4224
4225 data_queue_part_lookup(pc, name, &(cl->val));
4226
4227 code_lookups = eina_list_append(code_lookups, cl);
4228 }
4229
4230 static void
_data_queue_program_lookup(Edje_Part_Collection * pc,char * name,char * ptr,int len)4231 _data_queue_program_lookup(Edje_Part_Collection *pc, char *name, char *ptr, int len)
4232 {
4233 Code_Lookup *cl;
4234
4235 cl = mem_alloc(SZ(Code_Lookup));
4236 cl->ptr = ptr;
4237 cl->len = len;
4238
4239 data_queue_program_lookup(pc, name, &(cl->val));
4240
4241 code_lookups = eina_list_append(code_lookups, cl);
4242 }
4243
4244 static void
_data_queue_group_lookup(Edje_Part_Collection * pc EINA_UNUSED,char * name,char * ptr EINA_UNUSED,int len EINA_UNUSED)4245 _data_queue_group_lookup(Edje_Part_Collection *pc EINA_UNUSED, char *name, char *ptr EINA_UNUSED, int len EINA_UNUSED)
4246 {
4247 data_queue_group_lookup(name, NULL);
4248 }
4249
4250 static void
_data_queue_image_pc_lookup(Edje_Part_Collection * pc EINA_UNUSED,char * name,char * ptr,int len)4251 _data_queue_image_pc_lookup(Edje_Part_Collection *pc EINA_UNUSED, char *name, char *ptr, int len)
4252 {
4253 Code_Lookup *cl;
4254
4255 cl = mem_alloc(SZ(Code_Lookup));
4256 cl->ptr = ptr;
4257 cl->len = len;
4258
4259 data_queue_image_lookup(name, &(cl->val), &(cl->set));
4260
4261 code_lookups = eina_list_append(code_lookups, cl);
4262 }
4263
4264 void
data_process_scripts(void)4265 data_process_scripts(void)
4266 {
4267 Eina_List *l, *l2;
4268
4269 for (l = codes, l2 = edje_collections; (l) && (l2); l = eina_list_next(l), l2 = eina_list_next(l2))
4270 {
4271 Edje_Part_Collection *pc;
4272 Code *cd;
4273
4274 cd = eina_list_data_get(l);
4275 pc = eina_list_data_get(l2);
4276
4277 if ((cd->shared) && (!cd->is_lua))
4278 {
4279 data_process_string(pc, "PART", cd->shared, _data_queue_part_lookup);
4280 data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);
4281 data_process_string(pc, "IMAGE", cd->shared, _data_queue_image_pc_lookup);
4282 data_process_string(pc, "GROUP", cd->shared, _data_queue_group_lookup);
4283 }
4284
4285 if (cd->programs)
4286 {
4287 Code_Program *cp;
4288 Eina_List *ll;
4289
4290 EINA_LIST_FOREACH(cd->programs, ll, cp)
4291 {
4292 if (cp->script)
4293 {
4294 data_process_string(pc, "PART", cp->script, _data_queue_part_lookup);
4295 data_process_string(pc, "PROGRAM", cp->script, _data_queue_program_lookup);
4296 data_process_string(pc, "IMAGE", cp->script, _data_queue_image_pc_lookup);
4297 data_process_string(pc, "GROUP", cp->script, _data_queue_group_lookup);
4298 }
4299 }
4300 }
4301 }
4302 }
4303
4304 void
data_process_script_lookups(void)4305 data_process_script_lookups(void)
4306 {
4307 Eina_List *l;
4308 Code_Lookup *cl;
4309
4310 EINA_LIST_FOREACH(code_lookups, l, cl)
4311 {
4312 char buf[12];
4313 int n;
4314
4315 /* FIXME !! Handle set in program */
4316 n = eina_convert_itoa(cl->val, buf);
4317 if (n > cl->len)
4318 {
4319 ERR("The unexpected happened. A numeric replacement string was larger than the original!");
4320 exit(-1);
4321 }
4322 memset(cl->ptr, ' ', cl->len);
4323 strncpy(cl->ptr, buf, n);
4324 }
4325 }
4326
4327 void
using_file(const char * filename,const char type)4328 using_file(const char *filename, const char type)
4329 {
4330 FILE *f;
4331
4332 if (depfile)
4333 {
4334 f = fopen(depfile, "ab");
4335 if (!f) return;
4336 if (type != 'O')
4337 {
4338 fprintf(f, " \\\n %s", filename);
4339 }
4340 fclose(f);
4341 }
4342 else if (watchfile)
4343 {
4344 f = fopen(watchfile, "ab");
4345 if (!f) return;
4346 if (annotate)
4347 {
4348 fprintf(f, "%c: %s\n", type, filename);
4349 }
4350 else
4351 {
4352 fputs(filename, f);
4353 fputc('\n', f);
4354 }
4355 fclose(f);
4356 }
4357 }
4358
4359 void
color_tree_root_free(void)4360 color_tree_root_free(void)
4361 {
4362 char *name;
4363
4364 EINA_LIST_FREE(color_tree_root, name)
4365 free(name);
4366 }
4367
4368 char *
color_tree_token_next(char * dst,char * src,int * ln)4369 color_tree_token_next(char *dst, char *src, int *ln)
4370 {
4371 Eina_Bool begin = EINA_FALSE, next = EINA_FALSE;
4372
4373 while (!next)
4374 {
4375 if (*src == '\0') break;
4376
4377 if (*src == '"')
4378 {
4379 if (!begin) begin = EINA_TRUE;
4380 else next = EINA_TRUE;
4381 }
4382 else if ((!begin) && ((*src == '{') || (*src == '}') || (*src == ';')))
4383 {
4384 *dst++ = *src;
4385 next = EINA_TRUE;
4386 }
4387 else if ((!begin) && (*src == '\n'))
4388 {
4389 (*ln)++;
4390 }
4391 else if (begin)
4392 {
4393 *dst++ = *src;
4394 }
4395 src++;
4396 }
4397 *dst = '\0';
4398 return src;
4399 }
4400
4401 Edje_Color_Tree_Node *
color_tree_parent_node_get(const char * color_class)4402 color_tree_parent_node_get(const char *color_class)
4403 {
4404 Edje_Color_Tree_Node *ctn;
4405 Eina_List *l, *ll;
4406 char *name;
4407
4408 EINA_LIST_FOREACH(edje_file->color_tree, l, ctn)
4409 if (ctn->color_classes)
4410 EINA_LIST_FOREACH(ctn->color_classes, ll, name)
4411 if (!strcmp(name, color_class))
4412 return ctn;
4413
4414 return NULL;
4415 }
4416
4417 void
process_color_tree(char * s,const char * f_in,int ln)4418 process_color_tree(char *s, const char *f_in, int ln)
4419 {
4420 char token[2][1024];
4421 int id = 0;
4422 Eina_Array *array;
4423 Edje_Color_Tree_Node *ctn;
4424 Eina_List *l;
4425 char *name;
4426
4427 if (!s) return;
4428
4429 array = eina_array_new(4);
4430
4431 do
4432 {
4433 s = color_tree_token_next(token[id], s, &ln);
4434
4435 if (!strcmp(token[id], "{"))
4436 {
4437 if (!token[!id][0])
4438 error_and_abort(NULL, "parse error %s:%i. color class is not set to newly opened node block.",
4439 f_in, ln - 1);
4440
4441 ctn = mem_alloc(SZ(Edje_Color_Tree_Node));
4442 ctn->name = strdup(token[!id]);
4443 ctn->color_classes = NULL;
4444
4445 edje_file->color_tree = eina_list_append(edje_file->color_tree, ctn);
4446
4447 eina_array_push(array, ctn);
4448 token[id][0] = '\0';
4449 }
4450 else if (!strcmp(token[id], "}"))
4451 {
4452 eina_array_pop(array);
4453 token[id][0] = '\0';
4454 }
4455 else if (!strcmp(token[id], ";"))
4456 {
4457 token[id][0] = '\0';
4458 }
4459 else if (*s != '\0')
4460 {
4461 if (eina_array_count(array))
4462 {
4463 if (color_tree_root)
4464 EINA_LIST_FOREACH(color_tree_root, l, name)
4465 if (!strcmp(name, token[id]))
4466 {
4467 error_and_abort(NULL, "parse error %s:%i. The color class \"%s\" already belongs to the root node.",
4468 f_in, ln - 1, token[id]);
4469 }
4470
4471 if ((ctn = color_tree_parent_node_get(token[id])))
4472 error_and_abort(NULL, "parse error %s:%i. The color class \"%s\" already belongs to the \"%s\" node.",
4473 f_in, ln - 1, token[id], ctn->name);
4474
4475 ctn = eina_array_data_get(array, eina_array_count(array) - 1);
4476 ctn->color_classes = eina_list_append(ctn->color_classes, strdup(token[id]));
4477 }
4478 else
4479 {
4480 if ((ctn = color_tree_parent_node_get(token[id])))
4481 error_and_abort(NULL, "parse error %s:%i. The color class \"%s\" already belongs to the \"%s\" node.",
4482 f_in, ln - 1, token[id], ctn->name);
4483
4484 color_tree_root = eina_list_append(color_tree_root, strdup(token[id]));
4485 }
4486 }
4487
4488 id = !id;
4489 } while (*s);
4490
4491 if (eina_array_count(array))
4492 error_and_abort(NULL, "parse error %s:%i. check pair of parens.", f_in, ln - 1);
4493
4494 eina_array_clean(array);
4495 eina_array_free(array);
4496 }
4497
4498 char
validate_hex_digit(char c)4499 validate_hex_digit(char c)
4500 {
4501 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
4502 return c;
4503
4504 ERR("%s:%i. invalid character '%c' is used in color code.",
4505 file_in, line - 1, c);
4506 exit(-1);
4507 }
4508
4509 void
convert_color_code(char * str,int * r,int * g,int * b,int * a)4510 convert_color_code(char *str, int *r, int *g, int *b, int *a)
4511 {
4512 char buf[3];
4513 int len;
4514
4515 len = strlen(str);
4516
4517 if ((str[0] != '#') || (len != 4 && len != 5 && len != 7 && len != 9))
4518 {
4519 ERR("%s:%i color code should start with '#' and have 4 or 8 digit hex number. (3 or 6 digits are allowed to omit alpha value of 255)",
4520 file_in, line - 1);
4521 exit(-1);
4522 }
4523
4524 buf[2] = '\0';
4525
4526 if (r)
4527 {
4528 if ((len == 4) || (len == 5))
4529 {
4530 buf[0] = validate_hex_digit(str[1]);
4531 buf[1] = validate_hex_digit(str[1]);
4532 }
4533 else
4534 {
4535 buf[0] = validate_hex_digit(str[1]);
4536 buf[1] = validate_hex_digit(str[2]);
4537 }
4538
4539 *r = (int)strtol(buf, NULL, 16);
4540 }
4541 if (g)
4542 {
4543 if ((len == 4) || (len == 5))
4544 {
4545 buf[0] = validate_hex_digit(str[2]);
4546 buf[1] = validate_hex_digit(str[2]);
4547 }
4548 else
4549 {
4550 buf[0] = validate_hex_digit(str[3]);
4551 buf[1] = validate_hex_digit(str[4]);
4552 }
4553
4554 *g = (int)strtol(buf, NULL, 16);
4555 }
4556 if (b)
4557 {
4558 if ((len == 4) || (len == 5))
4559 {
4560 buf[0] = validate_hex_digit(str[3]);
4561 buf[1] = validate_hex_digit(str[3]);
4562 }
4563 else
4564 {
4565 buf[0] = validate_hex_digit(str[5]);
4566 buf[1] = validate_hex_digit(str[6]);
4567 }
4568
4569 *b = (int)strtol(buf, NULL, 16);
4570 }
4571 if (a)
4572 {
4573 if ((len == 5) || (len == 9))
4574 {
4575 if (len == 5)
4576 {
4577 buf[0] = validate_hex_digit(str[4]);
4578 buf[1] = validate_hex_digit(str[4]);
4579 }
4580 else
4581 {
4582 buf[0] = validate_hex_digit(str[7]);
4583 buf[1] = validate_hex_digit(str[8]);
4584 }
4585
4586 *a = (int)strtol(buf, NULL, 16);
4587 }
4588 else
4589 {
4590 *a = 255;
4591 }
4592 }
4593
4594 free(str);
4595 }
4596
4597