1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <ctype.h>
12 #include <Ecore_Getopt.h>
13
14 #include "edje_cc.h"
15 #include "edje_private.h"
16
17 #define EDJE_PICK_HELP_STRING \
18 "\nEdje Pick - the \"edj\" merging tool.\n\
19 ===================================\n\n\
20 Use Edje Pick to compose a single edj file \
21 by selecting groups from edj files.\n\n\
22 Use Edje Pick as follows:\n\
23 Include files with \'--include\' file-name\n\
24 Follow the included file-name by names of selected groups from this file.\n\
25 To select a group use: \'--group\' group-name.\n\n\
26 You must specify merged file name with \'--output\' file-name.\n\
27 Use '--verbose' switch to get detailed log.\n\n\
28 To produce 3rd file \'out.edj\' that composed of:\n\
29 Group \'test\' from \'ex1.edj\' and \'test2\', \'test3\', from \'ex2.edj\'\n\
30 edje_pick -i ex1.edj -g test -i ex2.edj -g test2 -g test3 -o out.edj\n\n\
31 By using \'--append\' whole file content is selected.\n\
32 No need to specify selected groups with this switch.\n\
33 Note that selected group with will override group with the same name\n\
34 from appended-file when using \'--append\' switch.\n\n\
35 Example, the command:\n\
36 edje_pick -a theme1.edj -i default.edj -g elm/button/base/default \
37 -g elm/check/base/default -o hybrid.edj\n\n\
38 will produce a 3rd theme file \'hybrid.edj\',\n\
39 composed of all theme1.edj components.\n\
40 Replacing the button and check with widgets taken from default theme.\n\
41 (Given that theme1.edj button, check group-name are as in default.edj)\n"
42
43 struct _Edje_Pick_Id
44 {
45 int old_id;
46 int new_id;
47 Eina_Bool used;
48 };
49 typedef struct _Edje_Pick_Id Edje_Pick_Id;
50
51 struct _Edje_Pick_File_Params
52 {
53 const char *name;
54 Eina_List *groups;
55 Edje_File *edf; /* Keeps all file data after reading */
56 Eina_Bool append; /* Take everything from this file */
57
58 /* We hold list of IDs for each file */
59 Eina_List *scriptlist;
60 Eina_List *luascriptlist;
61 Eina_List *imagelist;
62 Eina_List *imagesetlist; /* List of IDs (Edje_Pick_Data) for image sets */
63 Eina_List *vectorlist;
64 Eina_List *samplelist;
65 Eina_List *tonelist;
66 Eina_List *vibrationlist;
67 Eina_List *fontlist;
68 };
69 typedef struct _Edje_Pick_File_Params Edje_Pick_File_Params;
70
71 struct _Edje_Pick_Data
72 {
73 const char *filename; /* Image, Sample File Name */
74 void *entry; /* used to build output file dir FIXME: REMOVE THIS */
75 void *data; /* Data as taken from input file */
76
77 int size;
78 Edje_Pick_Id id;
79 };
80 typedef struct _Edje_Pick_Data Edje_Pick_Data;
81
82 struct _Edje_Pick_Tone
83 {
84 Edje_Sound_Tone *tone;
85 Eina_Bool used;
86 };
87 typedef struct _Edje_Pick_Tone Edje_Pick_Tone;
88
89 struct _Edje_Pick_Font
90 {
91 Edje_Font *f;
92
93 void *data; /* Font data as take from source edj file */
94 int size; /* data size */
95 Eina_Bool used;
96 };
97 typedef struct _Edje_Pick_Font Edje_Pick_Font;
98
99 struct _Edje_Pick
100 {
101 Eina_Bool v; /* Verbose */
102 Edje_Pick_File_Params *current_file;
103 };
104 typedef struct _Edje_Pick Edje_Pick;
105
106 static Edje_Pick context = { EINA_FALSE, NULL };
107
108 #define VERBOSE(COMMAND) if (context.v) { COMMAND; }
109
110 enum _Edje_Pick_Status
111 {
112 EDJE_PICK_NO_ERROR,
113 EDJE_PICK_OUT_FILENAME_MISSING,
114 EDJE_PICK_FAILED_OPEN_INP,
115 EDJE_PICK_FAILED_READ_INP,
116 EDJE_PICK_GROUP_NOT_FOUND,
117 EDJE_PICK_IMAGE_NOT_FOUND,
118 EDJE_PICK_SAMPLE_NOT_FOUND,
119 EDJE_PICK_INCLUDE_MISSING,
120 EDJE_PICK_GROUP_MISSING,
121 EDJE_PICK_PARSE_FAILED,
122 EDJE_PICK_HELP_SHOWN,
123 EDJE_PICK_DUP_GROUP
124 };
125 typedef enum _Edje_Pick_Status Edje_Pick_Status;
126
127 static void
_edje_pick_args_show(Eina_List * ifs,char * out)128 _edje_pick_args_show(Eina_List *ifs, char *out)
129 { /* Print command-line arguments after parsing phase */
130 Edje_Pick_File_Params *p;
131 Eina_List *l;
132 char *g;
133
134 EINA_LOG_INFO("Got args for <%d> input files.\n", eina_list_count(ifs));
135
136 EINA_LIST_FOREACH(ifs, l, p)
137 {
138 Eina_List *ll;
139
140 if (p->append)
141 printf("\nFile name: %s\n\tGroups: ALL (append mode)\n", p->name);
142 else
143 {
144 printf("\nFile name: %s\n\tGroups:\n", p->name);
145 EINA_LIST_FOREACH(p->groups, ll, g)
146 printf("\t\t%s\n", g);
147 }
148 }
149
150 EINA_LOG_INFO("\nOutput file name was <%s>\n", out);
151 }
152
153 static void
_edje_pick_data_free(Eina_List * l)154 _edje_pick_data_free(Eina_List *l)
155 {
156 Edje_Pick_Data *ep;
157
158 EINA_LIST_FREE(l, ep)
159 {
160 if (ep->filename) eina_stringshare_del(ep->filename);
161 free(ep->data);
162 free(ep);
163 }
164 }
165
166 static void
_edje_pick_out_file_free(Edje_File * out_file)167 _edje_pick_out_file_free(Edje_File *out_file)
168 {
169 if (out_file)
170 {
171 /* Free output file memory allocation */
172 if (out_file->ef)
173 eet_close(out_file->ef);
174
175 if (out_file->external_dir)
176 {
177 if (out_file->external_dir->entries)
178 free(out_file->external_dir->entries);
179
180 free(out_file->external_dir);
181 }
182
183 if (out_file->image_dir)
184 {
185 if (out_file->image_dir->entries)
186 free(out_file->image_dir->entries);
187
188 free(out_file->image_dir);
189 }
190
191 if (out_file->sound_dir)
192 {
193 if (out_file->sound_dir->samples)
194 free(out_file->sound_dir->samples);
195
196 if (out_file->sound_dir->tones)
197 free(out_file->sound_dir->tones);
198
199 free(out_file->sound_dir);
200 }
201 if (out_file->vibration_dir)
202 {
203 if (out_file->vibration_dir->samples)
204 free(out_file->vibration_dir->samples);
205
206 free(out_file->vibration_dir);
207 }
208
209 eina_list_free(out_file->color_classes);
210 eina_hash_free_cb_set(out_file->collection, free);
211 eina_hash_free(out_file->collection);
212 eina_stringshare_del(out_file->compiler);
213
214 free(out_file);
215 }
216 }
217
218 static int
_edje_pick_cleanup(Eina_List * ifs,Edje_File * out_file,Edje_Pick_Status s)219 _edje_pick_cleanup(Eina_List *ifs, Edje_File *out_file, Edje_Pick_Status s)
220 {
221 Edje_Pick_File_Params *p;
222 Edje_Pick_Font *ft;
223 void *n;
224
225 _edje_pick_out_file_free(out_file);
226
227 EINA_LIST_FREE(ifs, p)
228 {
229 EINA_LIST_FREE(p->groups, n)
230 eina_stringshare_del(n);
231
232 _edje_pick_data_free(p->scriptlist);
233 p->scriptlist = NULL;
234
235 _edje_pick_data_free(p->luascriptlist);
236 p->luascriptlist = NULL;
237
238 _edje_pick_data_free(p->imagelist);
239 p->imagelist = NULL;
240
241 _edje_pick_data_free(p->vectorlist);
242 p->vectorlist = NULL;
243
244 _edje_pick_data_free(p->imagesetlist);
245 p->imagesetlist = NULL;
246
247 _edje_pick_data_free(p->samplelist);
248
249 EINA_LIST_FREE(p->tonelist, n)
250 free(n);
251
252 if (p->edf)
253 _edje_cache_file_unref(p->edf);
254
255 EINA_LIST_FREE(p->fontlist, ft)
256 {
257 Edje_Font *st = ft->f;
258
259 eina_stringshare_del(st->name);
260 eina_stringshare_del(st->file);
261 free(ft->data);
262 free(st);
263 free(ft);
264 }
265
266 free(p);
267 }
268
269 switch (s)
270 {
271 case EDJE_PICK_OUT_FILENAME_MISSING:
272 EINA_LOG_ERR("Output file name missing.\n");
273 break;
274
275 case EDJE_PICK_FAILED_OPEN_INP:
276 EINA_LOG_ERR("Failed to open input file.\n");
277 break;
278
279 case EDJE_PICK_FAILED_READ_INP:
280 EINA_LOG_ERR("Failed to read input file.\n");
281 break;
282
283 case EDJE_PICK_DUP_GROUP:
284 EINA_LOG_ERR("Can't fetch groups with identical name from various files.\n");
285 break;
286
287 case EDJE_PICK_INCLUDE_MISSING:
288 EINA_LOG_ERR("Cannot select groups when no input file included.\n");
289 break;
290
291 case EDJE_PICK_GROUP_MISSING:
292 EINA_LOG_ERR("Group name missing for include file.\n");
293 break;
294
295 case EDJE_PICK_PARSE_FAILED:
296 EINA_LOG_ERR("Command parsing failed.\n");
297 break;
298
299 default:
300 return s;
301 }
302
303 _edje_edd_shutdown();
304 eet_shutdown();
305 return s;
306 }
307
308 /* Look for group name in all input files that are not d1 */
309 static int
_group_name_in_other_file(Eina_List * inp_files,void * d1,void * d2)310 _group_name_in_other_file(Eina_List *inp_files, void *d1, void *d2)
311 {
312 Edje_Pick_File_Params *inp_file = d1;
313 char *group = d2; /* Group name to search */
314 Eina_List *f;
315 Edje_Pick_File_Params *current_file;
316
317 EINA_LIST_FOREACH(inp_files, f, current_file)
318 if (inp_file != current_file)
319 if (eina_list_search_unsorted(current_file->groups,
320 (Eina_Compare_Cb)strcmp,
321 group))
322 return 1;
323
324 return 0; /* Not found */
325 }
326
327 static int
_edje_pick_command_line_parse(int argc,char ** argv,Eina_List ** ifs,char ** ofn)328 _edje_pick_command_line_parse(int argc, char **argv,
329 Eina_List **ifs, char **ofn)
330 { /* On return ifs is Input Files List, ofn is Output File Name */
331 Eina_List *gpf = NULL; /* List including counters of groups-per-file */
332 Eina_List *a_files = NULL;
333 Eina_List *i_files = NULL;
334 Eina_List *l;
335 Eina_List *ll;
336 Eina_List *cg;
337 Eina_List *groups = NULL;
338 char *output_filename = NULL;
339 Edje_Pick_File_Params *current_inp = NULL;
340 Eina_List *files = NULL; /* List of input files */
341 int *c = NULL;
342 char *str = NULL;
343 int k;
344 Eina_Bool show_help = EINA_FALSE;
345
346 /* Define args syntax */
347 #define IS_GROUP(x) ((!strcmp(x, "-g")) || (!strcmp(x, "--group")))
348 #define IS_INCLUDE(x) ((!strcmp(x, "-i")) || (!strcmp(x, "--include")))
349 #define IS_HELP(x) ((!strcmp(x, "-h")) || (!strcmp(x, "--help")))
350 static const Ecore_Getopt optdesc = {
351 "edje_pick",
352 NULL,
353 "0.0",
354 "(C) 2012 Enlightenment",
355 "Public domain?",
356 "Edje Pick - the \"edj\" merging tool.",
357
358 EINA_TRUE,
359 {
360 ECORE_GETOPT_STORE_TRUE('v', "verbose", "Verbose"),
361 ECORE_GETOPT_STORE('o', "output", "Output File",
362 ECORE_GETOPT_TYPE_STR),
363 ECORE_GETOPT_APPEND_METAVAR('a', "append", "Append File",
364 "STRING", ECORE_GETOPT_TYPE_STR),
365 ECORE_GETOPT_APPEND_METAVAR('i', "include", "Include File",
366 "STRING", ECORE_GETOPT_TYPE_STR),
367 ECORE_GETOPT_APPEND_METAVAR('g', "group", "Add Group",
368 "STRING", ECORE_GETOPT_TYPE_STR),
369 ECORE_GETOPT_HELP('h', "help"),
370 ECORE_GETOPT_SENTINEL
371 }
372 };
373
374 Ecore_Getopt_Value values[] = {
375 ECORE_GETOPT_VALUE_BOOL(context.v),
376 ECORE_GETOPT_VALUE_STR(output_filename),
377 ECORE_GETOPT_VALUE_LIST(a_files),
378 ECORE_GETOPT_VALUE_LIST(i_files),
379 ECORE_GETOPT_VALUE_LIST(groups),
380 ECORE_GETOPT_VALUE_NONE
381 };
382
383 /* START - Read command line args */
384 c = NULL;
385 for (k = 1; k < argc; k++)
386 { /* Run through args, count how many groups per file */
387 if (IS_GROUP(argv[k]))
388 {
389 if (!c)
390 return _edje_pick_cleanup(files, NULL,
391 EDJE_PICK_INCLUDE_MISSING);
392
393 (*c)++;
394 continue;
395 }
396
397 if (IS_INCLUDE(argv[k]))
398 {
399 c = calloc(1, sizeof(int));
400 gpf = eina_list_append(gpf, c);
401 continue;
402 }
403
404 show_help |= IS_HELP(argv[k]);
405 }
406
407 if (show_help)
408 puts(EDJE_PICK_HELP_STRING);
409
410 if (ecore_getopt_parse(&optdesc, values, argc, argv) < 0)
411 {
412 EINA_LIST_FREE(gpf, c)
413 free(c);
414
415 return _edje_pick_cleanup(files, NULL, EDJE_PICK_PARSE_FAILED);
416 }
417
418 if (show_help)
419 {
420 EINA_LIST_FREE(gpf, c)
421 free(c);
422
423 ecore_getopt_list_free(i_files);
424 ecore_getopt_list_free(groups);
425 return _edje_pick_cleanup(files, NULL, EDJE_PICK_HELP_SHOWN);
426 }
427
428 if (context.v) /* Changed to INFO if verbose */
429 eina_log_level_set(EINA_LOG_LEVEL_INFO);
430
431 EINA_LIST_FOREACH(a_files, l, str)
432 {
433 current_inp = calloc(1, sizeof(*current_inp));
434 current_inp->append = EINA_TRUE;
435 current_inp->name = eina_stringshare_add(str);
436 files = eina_list_append(files, current_inp);
437 }
438 ecore_getopt_list_free(a_files);
439
440 ll = gpf;
441 cg = groups;
442 EINA_LIST_FOREACH(i_files, l, str)
443 { /* Now match groups from groups-list with included files */
444 current_inp = calloc(1, sizeof(*current_inp));
445 current_inp->name = eina_stringshare_add(str);
446 files = eina_list_append(files, current_inp);
447 c = eina_list_data_get(ll);
448 if (c)
449 {
450 while (*c)
451 {
452 char *g_name;
453 if (!cg)
454 {
455 EINA_LIST_FREE(gpf, c)
456 free(c);
457
458 ecore_getopt_list_free(i_files);
459 ecore_getopt_list_free(groups);
460 return _edje_pick_cleanup(files, NULL,
461 EDJE_PICK_GROUP_MISSING);
462 }
463
464 g_name = eina_list_data_get(cg);
465 if (_group_name_in_other_file(files, current_inp, g_name))
466 return _edje_pick_cleanup(files, NULL, EDJE_PICK_DUP_GROUP);
467
468 if (!eina_list_search_unsorted(current_inp->groups,
469 (Eina_Compare_Cb)strcmp, g_name))
470 current_inp->groups = eina_list_append(
471 current_inp->groups, eina_stringshare_add(g_name));
472
473 cg = eina_list_next(cg);
474 (*c)--;
475 }
476 }
477 ll = eina_list_next(ll);
478 }
479
480 EINA_LIST_FREE(gpf, c)
481 free(c);
482
483 ecore_getopt_list_free(i_files);
484 ecore_getopt_list_free(groups);
485
486 if (!output_filename)
487 return _edje_pick_cleanup(files, NULL, EDJE_PICK_OUT_FILENAME_MISSING);
488 /* END - Read command line args */
489
490 /* Set output params, return OK */
491 *ifs = files;
492 *ofn = output_filename;
493 return EDJE_PICK_NO_ERROR;
494 }
495
496 static void
_edje_pick_external_dir_update(Edje_File * o,Edje_File * edf)497 _edje_pick_external_dir_update(Edje_File *o, Edje_File *edf)
498 {
499 if (edf->external_dir && edf->external_dir->entries_count)
500 {
501 /* Add external-dir entries */
502 unsigned int total = 0;
503 unsigned int base = 0;
504 Edje_External_Directory_Entry *entries;
505
506 if (o->external_dir)
507 base = total = o->external_dir->entries_count;
508 else
509 o->external_dir = calloc(1, sizeof(*(o->external_dir)));
510
511 total += edf->external_dir->entries_count;
512
513 entries = realloc(o->external_dir->entries,
514 total * sizeof(Edje_External_Directory_Entry));
515 if (!entries)
516 {
517 EINA_LOG_ERR("Out of memory in realloc()");
518 return;
519 }
520 o->external_dir->entries = entries;
521
522 memcpy(&o->external_dir->entries[base], edf->external_dir->entries,
523 edf->external_dir->entries_count *
524 sizeof(Edje_External_Directory_Entry));
525
526 o->external_dir->entries_count = total;
527 }
528 }
529
530 static Edje_File *
_edje_pick_output_prepare(Edje_File * o,Edje_File * edf,char * name)531 _edje_pick_output_prepare(Edje_File *o, Edje_File *edf, char *name)
532 {
533 /* Allocate and prepare header memory buffer */
534 if (!o)
535 {
536 o = calloc(1, sizeof(Edje_File));
537 o->compiler = eina_stringshare_add("edje_cc");
538 o->version = edf->version;
539 o->minor = edf->minor;
540 o->feature_ver = edf->feature_ver;
541 o->base_scale = edf->base_scale;
542 o->collection = eina_hash_string_small_new(NULL);
543 o->data = eina_hash_string_small_new(NULL);
544 o->fonts = eina_hash_string_small_new(NULL);
545
546 /* Open output file */
547 o->ef = eet_open(name, EET_FILE_MODE_WRITE);
548 }
549 else
550 {
551 if (o->version != edf->version)
552 {
553 EINA_LOG_WARN("Warning: Merging files of various version.\n");
554 if (o->version < edf->version)
555 o->version = edf->version;
556 }
557
558 if (o->minor != edf->minor)
559 {
560 EINA_LOG_WARN("Warning: Merging files of various minor.\n");
561 if (o->minor < edf->minor)
562 o->minor = edf->minor;
563 }
564
565 if (o->feature_ver != edf->feature_ver)
566 {
567 EINA_LOG_WARN("Warning: Merging files of various feature_ver.\n");
568 if (o->feature_ver < edf->feature_ver)
569 o->feature_ver = edf->feature_ver;
570 }
571 if (NEQ(o->base_scale, edf->base_scale))
572 {
573 EINA_LOG_ERR("Error: Merging files of various base scale. Base scale of the files should be same.\n");
574 free(o);
575 return NULL;
576 }
577 }
578
579 _edje_pick_external_dir_update(o, edf);
580 return o;
581 }
582
583 static void
_edje_pick_header_alias_parent_add(Edje_File * out_file,Edje_File * edf,Edje_Part_Collection_Directory_Entry * ce,Edje_Part_Collection_Directory_Entry * ce_out)584 _edje_pick_header_alias_parent_add(Edje_File *out_file, Edje_File *edf, Edje_Part_Collection_Directory_Entry *ce, Edje_Part_Collection_Directory_Entry *ce_out)
585 {
586 Edje_Part_Collection_Directory_Entry *ce_cor, *ce_new, *ce_f;
587 Eina_Iterator *i;
588
589 if (!ce->group_alias) return;
590
591 i = eina_hash_iterator_data_new(edf->collection);
592 EINA_ITERATOR_FOREACH(i, ce_cor)
593 {
594 /* find the alias parent group */
595 if ((ce->id == ce_cor->id) && (!ce_cor->group_alias))
596 {
597 ce_f = eina_hash_find(out_file->collection, ce_cor->entry);
598 if (!ce_f)
599 {
600 ce_new = malloc(sizeof(*ce_new));
601 memcpy(ce_new, ce_cor, sizeof(*ce_new));
602 ce_new->id = ce_out->id;
603 eina_hash_direct_add(out_file->collection, ce_new->entry, ce_new);
604 }
605 else
606 {
607 ce_out->id = ce_f->id;
608 }
609 }
610 }
611 eina_iterator_free(i);
612 }
613
614 static Eina_List *
_edje_pick_header_dependencies_check(Edje_File * out_file,Edje_File * edf,Eina_List * groups,Edje_Part_Collection_Directory_Entry * ce,int * current_id)615 _edje_pick_header_dependencies_check(Edje_File *out_file, Edje_File *edf, Eina_List *groups, Edje_Part_Collection_Directory_Entry *ce, int *current_id)
616 {
617 char buf[1024];
618 Edje_Part_Collection *edc;
619 Edje_Part *part;
620 unsigned int i, j;
621 Edje_Pack_Element *item;
622 Eina_List *dep_list = NULL, *dep_list_inner = NULL;
623
624 edje_cache_emp_alloc(ce);
625
626 snprintf(buf, sizeof(buf), "edje/collections/%i", ce->id);
627 EINA_LOG_INFO("Trying to read group <%s>\n", buf);
628 edc = eet_data_read(edf->ef, _edje_edd_edje_part_collection, buf);
629 if (!edc)
630 {
631 EINA_LOG_ERR("Failed to read group <%s> id <%d>\n", ce->entry, ce->id);
632 goto exit;
633 }
634 #define GROUP_CHECK_AND_ADD(NAME) \
635 if (NAME) \
636 { \
637 Edje_Part_Collection_Directory_Entry *ce_cor; \
638 if (eina_list_search_unsorted(groups, (void *)strcmp, NAME)) goto exit; \
639 ce_cor = eina_hash_find(edf->collection, NAME); \
640 if (!eina_hash_find(out_file->collection, ce_cor->entry)) \
641 { \
642 dep_list_inner = _edje_pick_header_dependencies_check(out_file, edf, groups, ce_cor, current_id); \
643 dep_list = eina_list_merge(dep_list, dep_list_inner); \
644 } \
645 if ((ce_cor) && (!eina_hash_find(out_file->collection, NAME))) \
646 { \
647 Edje_Part_Collection_Directory_Entry *ce_out; \
648 ce_out = malloc(sizeof(*ce_out)); \
649 memcpy(ce_out, ce_cor, sizeof(*ce_out)); \
650 ce_out->id = *current_id; \
651 if (ce_out->group_alias) \
652 _edje_pick_header_alias_parent_add(out_file, edf, ce, ce_out); \
653 EINA_LOG_INFO("Changing ID of group <%d> to <%d>\n", ce->id, ce_out->id); \
654 eina_hash_direct_add(out_file->collection, ce_out->entry, ce_out); \
655 (*current_id)++; \
656 dep_list = eina_list_append(dep_list, eina_stringshare_add(ce_out->entry)); \
657 } \
658 }
659
660 for (i = 0; i < edc->parts_count; i++)
661 {
662 part = edc->parts[i];
663 GROUP_CHECK_AND_ADD(part->source);
664 GROUP_CHECK_AND_ADD(part->source2);
665 GROUP_CHECK_AND_ADD(part->source3);
666 GROUP_CHECK_AND_ADD(part->source4);
667 GROUP_CHECK_AND_ADD(part->source5);
668 GROUP_CHECK_AND_ADD(part->source6);
669 for (j = 0; j < part->items_count; j++)
670 {
671 item = part->items[j];
672 GROUP_CHECK_AND_ADD(item->source);
673 }
674 }
675
676 exit:
677 edje_cache_emp_free(ce);
678 return dep_list;
679 #undef GROUP_CHECK_AND_ADD
680 }
681
682 static int
_edje_pick_data_update(Edje_File * out_file,Edje_File * edf)683 _edje_pick_data_update(Edje_File *out_file, Edje_File *edf)
684 {
685 Eina_Bool status = EDJE_PICK_NO_ERROR;
686 Eina_Iterator *i;
687 Eina_Stringshare *key, *value;
688
689 i = eina_hash_iterator_key_new(edf->data);
690 EINA_ITERATOR_FOREACH(i, key)
691 {
692 if (eina_hash_find(out_file->data, key)) continue;
693 value = eina_hash_find(edf->data, key);
694 eina_hash_direct_add(out_file->data, key, value);
695 }
696
697 return status;
698 }
699
700 static int
_edje_pick_header_make(Edje_File * out_file,Edje_File * edf,Eina_List * ifs)701 _edje_pick_header_make(Edje_File *out_file, Edje_File *edf, Eina_List *ifs)
702 {
703 static int current_group_id = 0;
704 Edje_Part_Collection_Directory_Entry *ce;
705 Eina_Bool status = EDJE_PICK_NO_ERROR;
706 Eina_List *l, *alist = NULL;
707 char *name1 = NULL;
708 Eina_List *deps = NULL, *dep_list = NULL;
709 Eina_Iterator *i;
710
711 /* Build file header */
712 if (context.current_file->append)
713 {
714 i = eina_hash_iterator_key_new(edf->collection);
715 EINA_ITERATOR_FOREACH(i, name1) /* Run through all keys */
716 {
717 Edje_Part_Collection_Directory_Entry *ce_out;
718
719 /* Use ALL groups from this file */
720 /* Test that no duplicate-group name for files in append mode */
721 /* Done here because we don't read EDC before parse cmd line */
722 /* We SKIP group of file in append-mode if we got this group */
723 /* from file in include mode. */
724 if (_group_name_in_other_file(ifs, context.current_file, name1))
725 continue; /* Skip group of file in append mode */
726
727 ce = eina_hash_find(edf->collection, name1);
728 ce_out = malloc(sizeof(*ce_out));
729 memcpy(ce_out, ce, sizeof(*ce_out));
730 if (ce_out->group_alias)
731 alist = eina_list_append(alist, eina_stringshare_add(name1));
732
733 ce_out->id = current_group_id;
734 current_group_id++;
735
736 eina_hash_direct_add(out_file->collection, ce_out->entry, ce_out);
737
738 /* Add this group to groups to handle for this file */
739 context.current_file->groups = eina_list_append(
740 context.current_file->groups, eina_stringshare_add(name1));
741 }
742
743 eina_iterator_free(i);
744 EINA_LIST_FOREACH(alist, l, name1)
745 {
746 Edje_Part_Collection_Directory_Entry *ce_cor;
747
748 ce = eina_hash_find(edf->collection, name1);
749 i = eina_hash_iterator_data_new(edf->collection);
750 EINA_ITERATOR_FOREACH(i, ce_cor)
751 {
752 if ((ce->id == ce_cor->id) && (!ce_cor->group_alias))
753 break;
754 }
755 ce = eina_hash_find(out_file->collection, ce_cor->entry);
756 ce_cor = eina_hash_find(out_file->collection, name1);
757 ce_cor->id = ce->id;
758 eina_iterator_free(i);
759 }
760 EINA_LIST_FREE(alist, name1)
761 eina_stringshare_del(name1);
762 }
763 else
764 {
765 EINA_LIST_FOREACH(context.current_file->groups, l, name1)
766 {
767 /* Verify group found then add to ouput file header */
768 ce = eina_hash_find(edf->collection, name1);
769
770 if (!ce)
771 {
772 EINA_LOG_ERR("Group <%s> was not found in <%s> file.\n",
773 name1, context.current_file->name);
774 status = EDJE_PICK_GROUP_NOT_FOUND;
775 }
776 else
777 {
778 Edje_Part_Collection_Directory_Entry *ce_out;
779
780 /* Add this groups to hash, with filname pefix for entries */
781 ce_out = malloc(sizeof(*ce_out));
782
783 memcpy(ce_out, ce, sizeof(*ce_out));
784 ce_out->id = current_group_id;
785 if (ce_out->group_alias)
786 _edje_pick_header_alias_parent_add(out_file, edf, ce, ce_out);
787 EINA_LOG_INFO("Changing ID of group <%d> to <%d>\n", ce->id, ce_out->id);
788 current_group_id++;
789
790 eina_hash_direct_add(out_file->collection, ce_out->entry,
791 ce_out);
792 dep_list = _edje_pick_header_dependencies_check(out_file, edf, context.current_file->groups, ce, ¤t_group_id);
793 if (!deps) deps = dep_list;
794 else deps = eina_list_merge(deps, dep_list);
795 }
796 }
797 EINA_LIST_FREE(deps, name1)
798 context.current_file->groups = eina_list_append(context.current_file->groups, name1);
799 }
800
801 return status;
802 }
803
804 static int
_old_id_cmp(const void * d1,const void * d2)805 _old_id_cmp(const void *d1, const void *d2)
806 {
807 /* Find currect ID struct */
808 return ((Edje_Pick_Data *)d1)->id.old_id - ((intptr_t)d2);
809 }
810
811 static int
_new_id_cmp(const void * d1,const void * d2)812 _new_id_cmp(const void *d1, const void *d2)
813 {
814 /* Find currect ID struct */
815 return ((Edje_Pick_Data *)d1)->id.new_id - ((intptr_t)d2);
816 }
817
818 static int
_edje_pick_new_id_get(Eina_List * id_list,int id,Eina_Bool set_used)819 _edje_pick_new_id_get(Eina_List *id_list, int id, Eina_Bool set_used)
820 {
821 if (id >= 0)
822 {
823 Edje_Pick_Data *p_id = eina_list_search_unsorted(id_list,
824 _old_id_cmp,
825 (void *)(intptr_t)id);
826
827 if (p_id)
828 {
829 if (set_used)
830 p_id->id.used = EINA_TRUE;
831
832 return p_id->id.new_id;
833 }
834 }
835
836 return id;
837 }
838
839 static int
_edje_pick_image_new_id_get(Eina_List * id_list,int id)840 _edje_pick_image_new_id_get(Eina_List *id_list, int id)
841 {
842 if (id >= 0)
843 {
844 Edje_Pick_Data *p_id = eina_list_search_unsorted(id_list,
845 _old_id_cmp,
846 (void *)(intptr_t)id);
847 if (p_id) return p_id->id.new_id;
848 }
849
850 return -1;
851 }
852
853 static int
_edje_pick_image_old_id_get(Eina_List * id_list,int id)854 _edje_pick_image_old_id_get(Eina_List *id_list, int id)
855 {
856 if (id >= 0)
857 {
858 Edje_Pick_Data *p_id = eina_list_search_unsorted(id_list,
859 _new_id_cmp,
860 (void *)(intptr_t)id);
861 if (p_id) return p_id->id.old_id;
862 }
863
864 return -1;
865 }
866
867 static int
_edje_pick_images_copy(Edje_File * edf,Edje_File * o)868 _edje_pick_images_copy(Edje_File *edf, Edje_File *o)
869 {
870 int old_id;
871 Eina_Bool status = EDJE_PICK_NO_ERROR;
872 Eina_List *l, *l1;
873 Edje_Pick_Data *image, *set, *vector;
874
875 if (edf->image_dir)
876 {
877 if (edf->image_dir->entries) /* Copy image dir entries of current file */
878 {
879 Edje_Image_Directory_Entry *entries = NULL;
880
881 EINA_LIST_FOREACH(context.current_file->imagelist, l, image)
882 {
883 if (image->id.used)
884 {
885 o->image_dir->entries_count += 1;
886
887 /* alloc mem first time or re-allocate again (bigger array) */
888 entries = realloc(o->image_dir->entries,
889 o->image_dir->entries_count *
890 sizeof(Edje_Image_Directory_Entry));
891 if (!entries)
892 {
893 EINA_LOG_ERR("Out of memory in realloc()");
894 return EDJE_PICK_IMAGE_NOT_FOUND;
895 }
896 o->image_dir->entries = entries;
897
898 old_id = _edje_pick_image_old_id_get(
899 context.current_file->imagelist, o->image_dir->entries_count - 1);
900 /* Concatenate current file entries to re-allocated array */
901 memcpy(&o->image_dir->entries[o->image_dir->entries_count - 1],
902 &edf->image_dir->entries[old_id],
903 sizeof(Edje_Image_Directory_Entry));
904 o->image_dir->entries[o->image_dir->entries_count - 1].id = image->id.new_id;
905 }
906 }
907 }
908
909 if (edf->image_dir->sets) /* Copy image dir sets of current file */
910 {
911 Edje_Image_Directory_Set *sets;
912
913 EINA_LIST_FOREACH(context.current_file->imagesetlist, l, set)
914 {
915 if (set->id.used)
916 {
917 Edje_Image_Directory_Set_Entry *e;
918
919 o->image_dir->sets_count += 1;
920 /* alloc mem first time or re-allocate again (bigger array) */
921 sets = realloc(o->image_dir->sets,
922 o->image_dir->sets_count *
923 sizeof(Edje_Image_Directory_Set));
924 if (!sets)
925 {
926 EINA_LOG_ERR("Out of memory in realloc()");
927 return EDJE_PICK_IMAGE_NOT_FOUND;
928 }
929 o->image_dir->sets = sets;
930
931 old_id = _edje_pick_image_old_id_get(
932 context.current_file->imagesetlist, o->image_dir->sets_count - 1);
933 /* Concatenate current file sets to re-allocated array */
934 memcpy(&o->image_dir->sets[o->image_dir->sets_count - 1],
935 &edf->image_dir->sets[old_id],
936 sizeof(Edje_Image_Directory_Set));
937 o->image_dir->sets[o->image_dir->sets_count - 1].id = set->id.new_id;
938
939 EINA_LIST_FOREACH(o->image_dir->sets[o->image_dir->sets_count - 1].entries, l1, e)
940 e->id = _edje_pick_image_new_id_get(
941 context.current_file->imagelist,
942 e->id);
943 }
944 }
945 }
946
947 if (edf->image_dir->vectors) /* Copy vector dir entries of current file */
948 {
949 Edje_Vector_Directory_Entry *vectors = NULL;
950
951 EINA_LIST_FOREACH(context.current_file->vectorlist, l, vector)
952 {
953 if (vector->id.used)
954 {
955 o->image_dir->vectors_count += 1;
956
957 /* alloc mem first time or re-allocate again (bigger array) */
958 vectors = realloc(o->image_dir->vectors,
959 o->image_dir->vectors_count *
960 sizeof(Edje_Vector_Directory_Entry));
961 if (!vectors)
962 {
963 EINA_LOG_ERR("Out of memory in realloc()");
964 return EDJE_PICK_IMAGE_NOT_FOUND;
965 }
966 o->image_dir->vectors = vectors;
967
968 old_id = _edje_pick_image_old_id_get(
969 context.current_file->vectorlist, o->image_dir->vectors_count - 1);
970 /* Concatenate current file vectors to re-allocated array */
971 memcpy(&o->image_dir->vectors[o->image_dir->vectors_count - 1],
972 &edf->image_dir->vectors[old_id],
973 sizeof(Edje_Vector_Directory_Entry));
974 o->image_dir->vectors[o->image_dir->vectors_count - 1].id = vector->id.new_id;
975 }
976 }
977 }
978 }
979
980 return status;
981 }
982
983 static int
_edje_pick_sounds_add(Edje_File * edf)984 _edje_pick_sounds_add(Edje_File *edf)
985 {
986 char buf[1024];
987 int size, k;
988 void *data;
989 Eina_Bool status = EDJE_PICK_NO_ERROR;
990 static int current_sample_id = 0;
991
992 if (edf->sound_dir) /* Copy Sounds */
993 {
994 for (k = 0; k < (int)edf->sound_dir->samples_count; k++)
995 {
996 Edje_Sound_Sample *sample = &edf->sound_dir->samples[k];
997
998 snprintf(buf, sizeof(buf), "edje/sounds/%i", sample->id);
999 VERBOSE(EINA_LOG_INFO("Trying to read <%s>\n", sample->snd_src));
1000
1001 data = eet_read(edf->ef, buf, &size);
1002 if (size)
1003 {
1004 Edje_Pick_Data *smpl = malloc(sizeof(*smpl));
1005 smpl->filename = eina_stringshare_add(sample->snd_src);
1006 smpl->data = data;
1007 smpl->size = size;
1008 smpl->entry = (void *)sample; /* for output file sound dir */
1009 smpl->id.old_id = sample->id;
1010 sample->id = smpl->id.new_id = current_sample_id;
1011 smpl->id.used = EINA_FALSE;
1012
1013 VERBOSE(EINA_LOG_INFO("Read <%s> sample data <%p> size <%d>\n",
1014 buf, smpl->data, smpl->size));
1015
1016 current_sample_id++;
1017 context.current_file->samplelist =
1018 eina_list_append(context.current_file->samplelist, smpl);
1019 }
1020 else
1021 {
1022 EINA_LOG_ERR("Sample <%s> was not found in <%s> file.\n",
1023 sample->name, context.current_file->name);
1024 status = EDJE_PICK_SAMPLE_NOT_FOUND;
1025 /* Should that really be freed? Or is some other handling needed? */
1026 free(data);
1027 }
1028 }
1029
1030 for (k = 0; k < (int)edf->sound_dir->tones_count; k++)
1031 {
1032 /* Save all tones as well */
1033 Edje_Pick_Tone *t = malloc(sizeof(*t));
1034
1035 t->tone = &edf->sound_dir->tones[k];
1036 /* Update ID to new ID */
1037 t->tone->id = _edje_pick_new_id_get(context.current_file->samplelist, /* From samplelist */
1038 t->tone->id, EINA_FALSE);
1039
1040 t->used = EINA_FALSE;
1041 context.current_file->tonelist = eina_list_append(context.current_file->tonelist, t);
1042 }
1043 }
1044
1045 return status;
1046 }
1047
1048 static int
_edje_pick_vibrations_add(Edje_File * edf)1049 _edje_pick_vibrations_add(Edje_File *edf)
1050 {
1051 char buf[1024];
1052 int size, k;
1053 void *data;
1054 Eina_Bool status = EDJE_PICK_NO_ERROR;
1055 static int current_sample_id = 0;
1056
1057 if (edf->vibration_dir) /* Copy Sounds */
1058 {
1059 for (k = 0; k < (int)edf->vibration_dir->samples_count; k++)
1060 {
1061 Edje_Vibration_Sample *sample = &edf->vibration_dir->samples[k];
1062
1063 snprintf(buf, sizeof(buf), "edje/vibrations/%i", sample->id);
1064 VERBOSE(EINA_LOG_INFO("Trying to read <%s>\n", sample->name));
1065
1066 data = eet_read(edf->ef, buf, &size);
1067 if (size)
1068 {
1069 Edje_Pick_Data *smpl = malloc(sizeof(*smpl));
1070 smpl->filename = eina_stringshare_add(sample->name);
1071 smpl->data = data;
1072 smpl->size = size;
1073 smpl->entry = (void *)sample; /* for output file vibration dir */
1074 smpl->id.old_id = sample->id;
1075 sample->id = smpl->id.new_id = current_sample_id;
1076 smpl->id.used = EINA_FALSE;
1077
1078 VERBOSE(EINA_LOG_INFO("Read <%s> sample data <%p> size <%d>\n",
1079 buf, smpl->data, smpl->size));
1080
1081 current_sample_id++;
1082 context.current_file->vibrationlist =
1083 eina_list_append(context.current_file->vibrationlist, smpl);
1084 }
1085 else
1086 {
1087 EINA_LOG_ERR("Sample <%s> was not found in <%s> file.\n",
1088 sample->name, context.current_file->name);
1089 status = EDJE_PICK_SAMPLE_NOT_FOUND;
1090 /* Should that really be freed? Or is some other handling needed? */
1091 free(data);
1092 }
1093 }
1094 }
1095
1096 return status;
1097 }
1098
1099 static int
_font_cmp(const void * d1,const void * d2)1100 _font_cmp(const void *d1, const void *d2)
1101 {
1102 const Edje_Font *f1 = d1;
1103 const Edje_Font *f2 = d2;
1104
1105 /* Same font if (d1->name == d2->name) AND (d1->file == d2->file) */
1106 return strcmp(f1->name, f2->name) |
1107 strcmp(f1->file, f2->file);
1108 }
1109
1110 static int
_Edje_Pick_Fonts_add(Edje_File * out_file,Edje_File * edf)1111 _Edje_Pick_Fonts_add(Edje_File *out_file, Edje_File *edf)
1112 {
1113 Eina_Iterator *it;
1114 Edje_Font *f;
1115 char buf[1024];
1116
1117 if (!edf->fonts) return -1;
1118
1119 it = eina_hash_iterator_data_new(edf->fonts);
1120 if (!it) return -1;
1121
1122 EINA_ITERATOR_FOREACH(it, f)
1123 {
1124 if (!eina_list_search_unsorted(context.current_file->fontlist, _font_cmp, f))
1125 continue;
1126 /* Add only fonts that are NOT regestered in our list */
1127 Edje_Pick_Font *ft = malloc(sizeof(*ft));
1128 Edje_Font *st = malloc(sizeof(*st));
1129 ft->size = 0;
1130
1131 st->name = (char *)eina_stringshare_add(f->name);
1132 st->file = (char *)eina_stringshare_add(f->file);
1133
1134 snprintf(buf, sizeof(buf), "edje/fonts/%s", f->name);
1135 VERBOSE(EINA_LOG_INFO("Trying to read <%s>\n", f->name));
1136 ft->data = eet_read(edf->ef, buf, &ft->size);
1137 if (!ft->size)
1138 {
1139 eina_stringshare_del(st->name);
1140 eina_stringshare_del(st->file);
1141 free(st);
1142 free(ft);
1143 VERBOSE(EINA_LOG_INFO("Enable to read <%s>. Skip.\n", f->name));
1144 continue;
1145 }
1146
1147 ft->f = st;
1148 ft->used = EINA_TRUE; /* TODO: Fix this later */
1149 context.current_file->fontlist = eina_list_append(context.current_file->fontlist, ft);
1150 eina_hash_direct_add(out_file->fonts, st->name, st);
1151 }
1152
1153 eina_iterator_free(it);
1154
1155 return EDJE_PICK_NO_ERROR;
1156 }
1157
1158 static int
_edje_pick_scripts_add(Edje_File * edf,int id,int new_id)1159 _edje_pick_scripts_add(Edje_File *edf, int id, int new_id)
1160 {
1161 int size;
1162 void *data;
1163 char buf[1024];
1164
1165 /* Copy Script */
1166 snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", id);
1167 data = eet_read(edf->ef, buf, &size);
1168 if (size)
1169 {
1170 Edje_Pick_Data *s = calloc(1, sizeof(*s));
1171
1172 s->data = data;
1173 s->size = size;
1174 s->id.old_id = id;
1175 s->id.new_id = new_id;
1176 s->id.used = EINA_TRUE;
1177
1178 VERBOSE(EINA_LOG_INFO("Read embryo script <%s> data <%p> size <%d>\n",
1179 buf, s->data, s->size));
1180 context.current_file->scriptlist = eina_list_append(context.current_file->scriptlist, s);
1181 }
1182 else
1183 {
1184 /* Should that really be freed? Or is some other handling needed? */
1185 free(data);
1186 }
1187
1188 return EDJE_PICK_NO_ERROR;
1189 }
1190
1191 static int
_edje_pick_lua_scripts_add(Edje_File * edf,int id,int new_id)1192 _edje_pick_lua_scripts_add(Edje_File *edf, int id, int new_id)
1193 {
1194 int size;
1195 void *data;
1196 char buf[1024];
1197
1198 /* Copy Script */
1199 snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", id);
1200 data = eet_read(edf->ef, buf, &size);
1201 if (size)
1202 {
1203 Edje_Pick_Data *s = calloc(1, sizeof(*s));
1204
1205 s->data = data;
1206 s->size = size;
1207 s->id.old_id = id;
1208 s->id.new_id = new_id;
1209 s->id.used = EINA_TRUE;
1210
1211 VERBOSE(EINA_LOG_INFO("Read lua script <%s> data <%p> size <%d>\n",
1212 buf, s->data, s->size));
1213 context.current_file->luascriptlist = eina_list_append(context.current_file->luascriptlist, s);
1214 }
1215 else
1216 {
1217 /* Should that really be freed? Or is some other handling needed? */
1218 free(data);
1219 }
1220
1221 return EDJE_PICK_NO_ERROR;
1222 }
1223
1224 static int
_edje_pick_image_entry_add(int id,Edje_File * edf,Edje_File * o)1225 _edje_pick_image_entry_add(int id, Edje_File *edf, Edje_File *o)
1226 {
1227 char buf[1024];
1228 int size;
1229 void *data;
1230 static int current_img_id = -1;
1231
1232 int new_id = _edje_pick_image_new_id_get(context.current_file->imagelist, id);
1233 if (new_id >= 0) return new_id;
1234
1235 if (edf->image_dir)
1236 {
1237 if (!o->image_dir) /* First time only */
1238 o->image_dir = calloc(1, sizeof(*(o->image_dir)));
1239
1240 if (edf->image_dir->entries) /* Copy Images */
1241 {
1242 Edje_Image_Directory_Entry *img = &edf->image_dir->entries[id];
1243
1244 snprintf(buf, sizeof(buf), "edje/images/%i", img->id);
1245 VERBOSE(EINA_LOG_INFO("Trying to read <%s>\n", img->entry));
1246 data = eet_read(edf->ef, buf, &size);
1247 if (size) /* Advance image ID and register this in imagelist */
1248 {
1249 current_img_id++;
1250 Edje_Pick_Data *image = malloc(sizeof(*image));
1251
1252 image->filename = eina_stringshare_add(img->entry);
1253 image->data = data;
1254 image->size = size;
1255 image->entry = (void *)img; /* for output file image dir */
1256 image->id.old_id = img->id;
1257 img->id = image->id.new_id = current_img_id;
1258 image->id.used = EINA_TRUE;
1259
1260 VERBOSE(EINA_LOG_INFO("Read image <%s> data <%p> size <%d>, new_id : %d\n",
1261 buf, image->data, image->size, image->id.new_id));
1262
1263 context.current_file->imagelist = eina_list_append(
1264 context.current_file->imagelist, image);
1265 }
1266 else
1267 {
1268 if (img->entry)
1269 {
1270 EINA_LOG_ERR("Image <%s> was not found in <%s> file.\n",
1271 img->entry, context.current_file->name);
1272 }
1273 else
1274 {
1275 EINA_LOG_ERR("Image entry <%s> was not found in <%s> file.\n", buf, context.current_file->name);
1276 }
1277 /* Should that really be freed? Or is some other handling needed? */
1278 free(data);
1279 }
1280 }
1281 }
1282
1283 return current_img_id;
1284 }
1285
1286 static int
_edje_pick_image_set_add(int id,Edje_File * edf,Edje_File * o)1287 _edje_pick_image_set_add(int id, Edje_File *edf, Edje_File *o)
1288 {
1289 static int current_set_id = -1;
1290 Edje_Image_Directory_Set_Entry *ent;
1291 Eina_List *l;
1292
1293 int new_id = _edje_pick_image_new_id_get(context.current_file->imagesetlist, id);
1294 if (new_id >= 0) return new_id;
1295
1296 if (edf->image_dir)
1297 {
1298 if (!o->image_dir) /* First time only */
1299 o->image_dir = calloc(1, sizeof(*(o->image_dir)));
1300
1301 if (edf->image_dir->sets) /* Fix IDs in sets to new assigned IDs of entries */
1302 {
1303 current_set_id++;
1304 Edje_Pick_Data *set = calloc(1, sizeof(*set));
1305 set->id.old_id = edf->image_dir->sets[id].id;
1306 set->id.new_id = current_set_id;
1307 set->id.used = EINA_TRUE;
1308
1309 /* Save IDs in set-list, used in Desc update later */
1310 context.current_file->imagesetlist = eina_list_append(
1311 context.current_file->imagesetlist, set);
1312 EINA_LIST_FOREACH(edf->image_dir->sets[id].entries, l, ent)
1313 {
1314 _edje_pick_image_entry_add(ent->id, edf, o);
1315 }
1316 }
1317 }
1318
1319 return current_set_id;
1320 }
1321
1322 static int
_edje_pick_vector_entry_add(int id,Edje_File * edf,Edje_File * o)1323 _edje_pick_vector_entry_add(int id, Edje_File *edf, Edje_File *o)
1324 {
1325 char buf[1024];
1326 int size;
1327 void *data;
1328 static int current_vg_id = -1;
1329
1330 int new_id = _edje_pick_image_new_id_get(context.current_file->vectorlist, id);
1331 if (new_id >= 0) return new_id;
1332
1333 if (edf->image_dir)
1334 {
1335 if (!o->image_dir) /* First time only */
1336 o->image_dir = calloc(1, sizeof(*(o->image_dir)));
1337
1338 if (edf->image_dir->vectors) /* Copy Vectors */
1339 {
1340 Edje_Vector_Directory_Entry *vg = &edf->image_dir->vectors[id];
1341
1342 snprintf(buf, sizeof(buf), "edje/vectors/%i", vg->id);
1343 VERBOSE(EINA_LOG_INFO("Trying to read <%s>\n", vg->entry));
1344 data = eet_read(edf->ef, buf, &size);
1345 if (size) /* Advance vector ID and register this in vectorlist */
1346 {
1347 current_vg_id++;
1348 Edje_Pick_Data *vector = malloc(sizeof(*vector));
1349
1350 vector->filename = eina_stringshare_add(vg->entry);
1351 vector->data = data;
1352 vector->size = size;
1353 vector->entry = (void *)vg; /* for output file vector dir */
1354 vector->id.old_id = vg->id;
1355 vg->id = vector->id.new_id = current_vg_id;
1356 vector->id.used = EINA_TRUE;
1357
1358 VERBOSE(EINA_LOG_INFO("Read vector <%s> data <%p> size <%d>, new_id : %d\n",
1359 buf, vector->data, vector->size, vector->id.new_id));
1360
1361 context.current_file->vectorlist = eina_list_append(
1362 context.current_file->vectorlist, vector);
1363 }
1364 else
1365 {
1366 if (vg->entry)
1367 {
1368 EINA_LOG_ERR("Vector <%s> was not found in <%s> file.\n",
1369 vg->entry, context.current_file->name);
1370 }
1371 else
1372 {
1373 EINA_LOG_ERR("Vector entry <%s> was not found in <%s> file.\n", buf, context.current_file->name);
1374 }
1375 /* Should that really be freed? Or is some other handling needed? */
1376 free(data);
1377 }
1378 }
1379 }
1380
1381 return current_vg_id;
1382 }
1383
1384 static void
_edje_pick_images_desc_update(Edje_Part_Description_Image * desc,Edje_File * edf,Edje_File * o)1385 _edje_pick_images_desc_update(Edje_Part_Description_Image *desc, Edje_File *edf, Edje_File *o)
1386 {
1387 /* Update all IDs of images in descs */
1388 if (desc)
1389 {
1390 unsigned int k;
1391 int new_id = (desc->image.set) ?
1392 _edje_pick_image_set_add(desc->image.id, edf, o) :
1393 _edje_pick_image_entry_add(desc->image.id, edf, o);
1394
1395 desc->image.id = new_id;
1396
1397 for (k = 0; k < desc->image.tweens_count; k++)
1398 {
1399 new_id = (desc->image.set) ?
1400 _edje_pick_image_set_add(desc->image.tweens[k]->id, edf, o) :
1401 _edje_pick_image_entry_add(desc->image.tweens[k]->id, edf, o);
1402
1403 desc->image.tweens[k]->id = new_id;
1404 }
1405 }
1406 }
1407
1408 static void
_edje_pick_vectors_desc_update(Edje_Part_Description_Vector * desc,Edje_File * edf,Edje_File * o)1409 _edje_pick_vectors_desc_update(Edje_Part_Description_Vector *desc, Edje_File *edf, Edje_File *o)
1410 {
1411 /* Update all IDs of vectors in descs */
1412 if (desc)
1413 {
1414 int new_id = _edje_pick_vector_entry_add(desc->vg.id, edf, o);
1415
1416 desc->vg.id = new_id;
1417 }
1418 }
1419
1420 static void
_edje_pick_styles_desc_update(Edje_Part_Description_Text * desc,Edje_File * edf,Edje_File * o)1421 _edje_pick_styles_desc_update(Edje_Part_Description_Text *desc, Edje_File *edf, Edje_File *o)
1422 {
1423 Eina_List *l;
1424 Edje_Style *stl;
1425 const char *style;
1426
1427 if (desc)
1428 {
1429 style = desc->text.style.str;
1430
1431 if (style)
1432 {
1433 EINA_LIST_FOREACH(edf->styles, l, stl)
1434 if ((stl->name) && (!strcmp(stl->name, style)))
1435 o->styles = eina_list_append(o->styles, stl);
1436 }
1437 }
1438 }
1439
1440 static void
_edje_pick_color_class_desc_update(Edje_Part_Description_Common * desc,Edje_File * edf,Edje_File * o)1441 _edje_pick_color_class_desc_update(Edje_Part_Description_Common *desc, Edje_File *edf, Edje_File *o)
1442 {
1443 Eina_List *l;
1444 Edje_Color_Class *cc;
1445 const char *color_class;
1446
1447 if (desc)
1448 {
1449 color_class = desc->color_class;
1450
1451 if (color_class)
1452 {
1453 EINA_LIST_FOREACH(edf->color_classes, l, cc)
1454 if ((cc->name) && (!strcmp(cc->name, color_class)))
1455 o->color_classes = eina_list_append(o->color_classes, cc);
1456 }
1457 }
1458 }
1459
1460 static void
_edje_pick_resources_process(Edje_Part_Collection * edc,Edje_File * edf,Edje_File * o)1461 _edje_pick_resources_process(Edje_Part_Collection *edc, Edje_File *edf, Edje_File *o)
1462 {
1463 /* Find what imagees are used, update IDs, mark as USED */
1464 /* Find what styles and color classes are used */
1465 unsigned int i, k;
1466
1467 for (i = 0; i < edc->parts_count; i++)
1468 {
1469 /* Scan all parts, locate what resources used */
1470 Edje_Part *part = edc->parts[i];
1471
1472 /* Update all color class in ALL descs of this part */
1473 _edje_pick_color_class_desc_update((Edje_Part_Description_Common *)part->default_desc, edf, o);
1474
1475 for (k = 0; k < part->other.desc_count; k++)
1476 _edje_pick_color_class_desc_update((Edje_Part_Description_Common *)part->other.desc[k], edf, o);
1477
1478 if (part->type == EDJE_PART_TYPE_IMAGE)
1479 {
1480 /* Update IDs of all images in ALL descs of this part */
1481 _edje_pick_images_desc_update((Edje_Part_Description_Image *)part->default_desc, edf, o);
1482
1483 for (k = 0; k < part->other.desc_count; k++)
1484 _edje_pick_images_desc_update((Edje_Part_Description_Image *)part->other.desc[k], edf, o);
1485 }
1486 else if (part->type == EDJE_PART_TYPE_VECTOR)
1487 {
1488 /* Update IDs of all vectors in ALL descs of this part */
1489 _edje_pick_vectors_desc_update((Edje_Part_Description_Vector *)part->default_desc, edf, o);
1490
1491 for (k = 0; k < part->other.desc_count; k++)
1492 _edje_pick_vectors_desc_update((Edje_Part_Description_Vector *)part->other.desc[k], edf, o);
1493 }
1494 else if (part->type == EDJE_PART_TYPE_TEXT || part->type == EDJE_PART_TYPE_TEXTBLOCK)
1495 {
1496 /* Update all styles in ALL descs of this part */
1497 _edje_pick_styles_desc_update((Edje_Part_Description_Text *)part->default_desc, edf, o);
1498
1499 for (k = 0; k < part->other.desc_count; k++)
1500 _edje_pick_styles_desc_update((Edje_Part_Description_Text *)part->other.desc[k], edf, o);
1501 }
1502 }
1503 }
1504
1505 static int
_sample_cmp(const void * d1,const void * d2)1506 _sample_cmp(const void *d1, const void *d2)
1507 {
1508 /* Locate sample by name */
1509 if (d2)
1510 {
1511 Edje_Sound_Sample *sample = ((Edje_Pick_Data *)d1)->entry;
1512
1513 return strcmp(sample->name, d2);
1514 }
1515
1516 return 1;
1517 }
1518
1519 static int
_tone_cmp(const void * d1,const void * d2)1520 _tone_cmp(const void *d1, const void *d2)
1521 {
1522 /* Locate tone by name */
1523 if (d2)
1524 {
1525 Edje_Sound_Tone *tone = ((Edje_Pick_Tone *)d1)->tone;
1526
1527 return strcmp(tone->name, d2);
1528 }
1529
1530 return 1;
1531 }
1532
1533 static void
_edje_pick_program_update(Edje_Program * prog)1534 _edje_pick_program_update(Edje_Program *prog)
1535 {
1536 Edje_Pick_Data *p;
1537 Edje_Pick_Tone *t;
1538
1539 /* Scan for used samples, update samples IDs */
1540 p = eina_list_search_unsorted(context.current_file->samplelist,
1541 (Eina_Compare_Cb)_sample_cmp,
1542 prog->sample_name);
1543
1544 /* Sample is used by program, should be saved */
1545 if (p)
1546 p->id.used = EINA_TRUE;
1547
1548 /* handle tones as well */
1549 t = eina_list_search_unsorted(context.current_file->tonelist,
1550 (Eina_Compare_Cb)_tone_cmp,
1551 prog->tone_name);
1552
1553 /* Tone is used by program, should be saved */
1554 if (t)
1555 t->used = EINA_TRUE;
1556 }
1557
1558 static int
_edje_pick_programs_process(Edje_Part_Collection * edc)1559 _edje_pick_programs_process(Edje_Part_Collection *edc)
1560 {
1561 /* This wil mark which samples are used and should be saved */
1562 unsigned int i;
1563
1564 for (i = 0; i < edc->programs.fnmatch_count; i++)
1565 _edje_pick_program_update(edc->programs.fnmatch[i]);
1566
1567 for (i = 0; i < edc->programs.strcmp_count; i++)
1568 _edje_pick_program_update(edc->programs.strcmp[i]);
1569
1570 for (i = 0; i < edc->programs.strncmp_count; i++)
1571 _edje_pick_program_update(edc->programs.strncmp[i]);
1572
1573 for (i = 0; i < edc->programs.strrncmp_count; i++)
1574 _edje_pick_program_update(edc->programs.strrncmp[i]);
1575
1576 for (i = 0; i < edc->programs.nocmp_count; i++)
1577 _edje_pick_program_update(edc->programs.nocmp[i]);
1578
1579 return EDJE_PICK_NO_ERROR;
1580 }
1581
1582 static int
_edje_pick_collection_process(Edje_Part_Collection * edc,Edje_File * edf,Edje_File * o)1583 _edje_pick_collection_process(Edje_Part_Collection *edc, Edje_File *edf, Edje_File *o)
1584 {
1585 /* Update all IDs, NAMES in current collection */
1586 Edje_Part_Collection_Directory_Entry *ce;
1587
1588 ce = eina_hash_find(o->collection, edc->part);
1589 edc->id = ce->id;
1590
1591 _edje_pick_resources_process(edc, edf, o);
1592 _edje_pick_programs_process(edc);
1593
1594 return EDJE_PICK_NO_ERROR;
1595 }
1596
1597 static void
_edje_pick_sound_dir_compose(Eina_List * samples,Eina_List * tones,Edje_File * o)1598 _edje_pick_sound_dir_compose(Eina_List *samples, Eina_List *tones, Edje_File *o)
1599 { /* Compose sound_dir array from all used samples, tones */
1600 if (samples)
1601 {
1602 Edje_Sound_Sample *sample;
1603 Edje_Sound_Sample *p;
1604 Eina_List *l;
1605
1606 o->sound_dir = calloc(1, sizeof(*(o->sound_dir)));
1607 o->sound_dir->samples = malloc(eina_list_count(samples) *
1608 sizeof(Edje_Sound_Sample));
1609
1610 p = o->sound_dir->samples;
1611 EINA_LIST_FOREACH(samples, l, sample)
1612 {
1613 memcpy(p, sample, sizeof(Edje_Sound_Sample));
1614 p++;
1615 }
1616
1617 o->sound_dir->samples_count = eina_list_count(samples);
1618
1619 if (tones)
1620 {
1621 Edje_Sound_Tone *tone;
1622 Edje_Sound_Tone *t;
1623
1624 o->sound_dir->tones = malloc(eina_list_count(tones) *
1625 sizeof(Edje_Sound_Tone));
1626
1627 t = o->sound_dir->tones;
1628 EINA_LIST_FOREACH(tones, l, tone)
1629 {
1630 memcpy(t, tone, sizeof(Edje_Sound_Tone));
1631 t++;
1632 }
1633
1634 o->sound_dir->tones_count = eina_list_count(tones);
1635 }
1636 }
1637 }
1638
1639 static void
_edje_pick_vibration_dir_compose(Eina_List * vibrations,Edje_File * o)1640 _edje_pick_vibration_dir_compose(Eina_List *vibrations, Edje_File *o)
1641 { /* Compose vibrationdir array from all used vibrations */
1642 if (vibrations)
1643 {
1644 Edje_Vibration_Sample *sample;
1645 Edje_Vibration_Sample *p;
1646 Eina_List *l;
1647
1648 o->vibration_dir = calloc(1, sizeof(*(o->vibration_dir)));
1649 o->vibration_dir->samples = malloc(eina_list_count(vibrations) *
1650 sizeof(Edje_Vibration_Sample));
1651
1652 p = o->vibration_dir->samples;
1653 EINA_LIST_FOREACH(vibrations, l, sample)
1654 {
1655 memcpy(p, sample, sizeof(Edje_Vibration_Sample));
1656 p++;
1657 }
1658
1659 o->vibration_dir->samples_count = eina_list_count(vibrations);
1660 }
1661 }
1662
1663 int
main(int argc,char ** argv)1664 main(int argc, char **argv)
1665 {
1666 char *name1, *output_filename = NULL;
1667 Eina_List *inp_files = NULL;
1668 int comp_mode = EET_COMPRESSION_DEFAULT;
1669 Edje_File *out_file = NULL;
1670 Eina_List *images = NULL;
1671 Eina_List *samples = NULL;
1672 Eina_List *tones = NULL;
1673 Eina_List *vibrations = NULL;
1674
1675 Edje_Part_Collection *edc;
1676 Edje_Part_Collection_Directory_Entry *ce;
1677 Eet_File *ef;
1678 Eina_List *f, *l;
1679 char buf[1024];
1680 int k, bytes;
1681
1682 ecore_app_no_system_modules();
1683
1684 eina_init();
1685 eet_init();
1686 ecore_init();
1687 _edje_edd_init();
1688 eina_log_level_set(EINA_LOG_LEVEL_WARN); /* Changed to INFO if verbose */
1689
1690 k = _edje_pick_command_line_parse(argc, argv, &inp_files, &output_filename);
1691 if ( k != EDJE_PICK_NO_ERROR)
1692 return k;
1693
1694 _edje_pick_args_show(inp_files, output_filename);
1695
1696 /* START - Main loop scanning input files */
1697 EINA_LIST_FOREACH(inp_files, f, context.current_file)
1698 {
1699 Edje_File *edf;
1700
1701 ef = eet_open(context.current_file->name, EET_FILE_MODE_READ);
1702 if (!ef)
1703 return _edje_pick_cleanup(inp_files, out_file,
1704 EDJE_PICK_FAILED_OPEN_INP);
1705
1706 edf = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
1707 if (!edf)
1708 return _edje_pick_cleanup(inp_files, out_file,
1709 EDJE_PICK_FAILED_READ_INP);
1710
1711 context.current_file->edf = edf;
1712 edf->ef = ef;
1713
1714 out_file = _edje_pick_output_prepare(out_file, edf, output_filename);
1715 if (!out_file)
1716 {
1717 _edje_cache_file_unref(edf);
1718 eet_close(ef);
1719 return _edje_pick_cleanup(inp_files, out_file, k);
1720 }
1721
1722 k = _edje_pick_header_make(out_file, edf, inp_files);
1723 if (k != EDJE_PICK_NO_ERROR)
1724 {
1725 _edje_cache_file_unref(edf);
1726 eet_close(ef);
1727 return _edje_pick_cleanup(inp_files, out_file, k);
1728 }
1729
1730 /* Build lists of all samples and fonts of input files */
1731 _edje_pick_sounds_add(edf); /* Add Sounds to samplelist */
1732 _edje_pick_vibrations_add(edf); /* Add Vibrations to samplelist */
1733
1734 _edje_pick_data_update(out_file, edf);
1735
1736 /* Process Groups */
1737 EINA_LIST_FOREACH(context.current_file->groups, l, name1)
1738 { /* Read group info */
1739 ce = eina_hash_find(edf->collection, name1);
1740 if (!ce || (ce->id < 0))
1741 {
1742 EINA_LOG_ERR("Failed to find group <%s> id\n", name1);
1743 _edje_cache_file_unref(edf);
1744 return _edje_pick_cleanup(inp_files, out_file,
1745 EDJE_PICK_GROUP_NOT_FOUND);
1746 }
1747
1748 VERBOSE(EINA_LOG_INFO("Copy group: <%s>\n", name1));
1749
1750 edje_cache_emp_alloc(ce);
1751
1752 snprintf(buf, sizeof(buf), "edje/collections/%i", ce->id);
1753 EINA_LOG_INFO("Trying to read group <%s>\n", buf);
1754 edc = eet_data_read(edf->ef, _edje_edd_edje_part_collection, buf);
1755 if (!edc)
1756 {
1757 EINA_LOG_ERR("Failed to read group <%s> id <%d>\n", name1, ce->id);
1758 _edje_cache_file_unref(edf);
1759 return _edje_pick_cleanup(inp_files, out_file,
1760 EDJE_PICK_GROUP_NOT_FOUND);
1761 }
1762
1763 /* Update IDs */
1764 _edje_pick_collection_process(edc, edf, out_file);
1765
1766 /* Build lists of all scripts with new IDs */
1767 _edje_pick_scripts_add(edf, ce->id, edc->id);
1768 _edje_pick_lua_scripts_add(edf, ce->id, edc->id);
1769
1770 {
1771 /* Write the group to output file using new id */
1772 snprintf(buf, sizeof(buf),
1773 "edje/collections/%i", edc->id);
1774 bytes = eet_data_write(out_file->ef,
1775 _edje_edd_edje_part_collection,
1776 buf, edc, comp_mode);
1777 EINA_LOG_INFO("Wrote <%d> bytes for group <%s>\n", bytes, buf);
1778 }
1779
1780 free(edc);
1781 edje_cache_emp_free(ce);
1782 eet_close(ef);
1783 }
1784
1785 _edje_pick_images_copy(edf, out_file); /* Add Images to imagelist */
1786 _edje_cache_file_unref(edf);
1787 _Edje_Pick_Fonts_add(out_file, edf); /* Add fonts from file to fonts list */
1788
1789 /* We SKIP writing source, just can't compose it */
1790 /* FIXME: use Edje_Edit code to generate source */
1791 } /* END - Main loop scanning input files */
1792
1793 /* Write rest of output */
1794
1795 EINA_LIST_FOREACH(inp_files, f, context.current_file)
1796 {
1797 /* Write Scripts from ALL files */
1798 Edje_Pick_Data *s;
1799 Edje_Pick_Tone *tn;
1800 Edje_Pick_Font *fn;
1801 Eina_List *t;
1802
1803 EINA_LIST_FOREACH(context.current_file->scriptlist, t, s)
1804 {
1805 /* Write Scripts */
1806 snprintf(buf, sizeof(buf),
1807 "edje/scripts/embryo/compiled/%i", s->id.new_id);
1808 VERBOSE(EINA_LOG_INFO("wrote embryo scr <%s> data <%p> size <%d>\n",
1809 buf, s->data, s->size));
1810 eet_write(out_file->ef, buf, s->data, s->size, comp_mode);
1811 }
1812
1813 EINA_LIST_FOREACH(context.current_file->luascriptlist, t, s)
1814 {
1815 /* Write Lua Scripts */
1816 snprintf(buf, sizeof(buf),
1817 "edje/scripts/lua/%i", s->id.new_id);
1818 VERBOSE(EINA_LOG_INFO("wrote lua scr <%s> data <%p> size <%d>\n",
1819 buf, s->data, s->size));
1820 eet_write(out_file->ef, buf, s->data, s->size, comp_mode);
1821 }
1822
1823 EINA_LIST_FOREACH(context.current_file->imagelist, t, s)
1824 {
1825 if (context.current_file->append || s->id.used)
1826 {
1827 snprintf(buf, sizeof(buf), "edje/images/%i", s->id.new_id);
1828 eet_write(out_file->ef, buf, s->data, s->size, EINA_TRUE);
1829 VERBOSE(EINA_LOG_INFO("Wrote <%s> image data <%p> size <%d>\n", buf, s->data, s->size));
1830 }
1831 }
1832
1833 EINA_LIST_FOREACH(context.current_file->vectorlist, t, s)
1834 {
1835 if (context.current_file->append || s->id.used)
1836 {
1837 snprintf(buf, sizeof(buf), "edje/vectors/%i", s->id.new_id);
1838 eet_write(out_file->ef, buf, s->data, s->size, EINA_TRUE);
1839 VERBOSE(EINA_LOG_INFO("Wrote <%s> vector data <%p> size <%d>\n", buf, s->data, s->size));
1840 }
1841 }
1842
1843 EINA_LIST_FOREACH(context.current_file->fontlist, t, fn)
1844 {
1845 if (context.current_file->append || fn->used)
1846 {
1847 snprintf(buf, sizeof(buf), "edje/fonts/%s", fn->f->name);
1848 eet_write(out_file->ef, buf, fn->data, fn->size, EINA_TRUE);
1849 VERBOSE(EINA_LOG_INFO("Wrote <%s> fonts data <%p> size <%d>\n", buf, fn->data, fn->size));
1850 }
1851 }
1852
1853 EINA_LIST_FOREACH(context.current_file->samplelist, l, s)
1854 {
1855 if (context.current_file->append || s->id.used) /* Write only used samples */
1856 {
1857 samples = eina_list_append(samples, s->entry);
1858
1859 snprintf(buf, sizeof(buf), "edje/sounds/%i",
1860 s->id.new_id);
1861 eet_write(out_file->ef, buf,
1862 s->data, s->size, EET_COMPRESSION_NONE);
1863 VERBOSE(EINA_LOG_INFO("Wrote <%s> sample data <%p> size <%d>\n",
1864 buf, s->data, s->size));
1865 }
1866 }
1867
1868 EINA_LIST_FOREACH(context.current_file->tonelist, l, tn)
1869 {
1870 if (context.current_file->append || tn->used)
1871 tones = eina_list_append(tones, tn->tone);
1872 }
1873
1874 EINA_LIST_FOREACH(context.current_file->vibrationlist, l, s)
1875 {
1876 if (context.current_file->append || s->id.used) /* Write only used vibrations */
1877 {
1878 vibrations = eina_list_append(vibrations, s->entry);
1879
1880 snprintf(buf, sizeof(buf), "edje/vibrations/%i",
1881 s->id.new_id);
1882 eet_write(out_file->ef, buf,
1883 s->data, s->size, EINA_TRUE);
1884 VERBOSE(EINA_LOG_INFO("Wrote <%s> vibration data <%p> size <%d>\n",
1885 buf, s->data, s->size));
1886 }
1887 }
1888 }
1889
1890 _edje_pick_sound_dir_compose(samples, tones, out_file);
1891 _edje_pick_vibration_dir_compose(vibrations, out_file);
1892
1893 /* Write file header after processing all groups */
1894 if (out_file)
1895 {
1896 bytes = eet_data_write(out_file->ef, _edje_edd_edje_file, "edje/file",
1897 out_file, comp_mode);
1898 VERBOSE(EINA_LOG_INFO("Wrote <%d> bytes for file header.\n", bytes));
1899 }
1900
1901 eina_list_free(images);
1902 eina_list_free(samples);
1903 eina_list_free(tones);
1904
1905 if (output_filename)
1906 printf("Wrote <%s> output file.\n", output_filename);
1907
1908 return _edje_pick_cleanup(inp_files, out_file, EDJE_PICK_NO_ERROR);
1909 }
1910
1911