efl

Форк
0
/
edje_cache.c 
975 строк · 27.3 Кб
1
#include "edje_private.h"
2

3
Eina_Hash *_edje_file_hash = NULL;
4
Eina_Hash *_edje_id_hash = NULL;
5

6
static Eina_Hash *_edje_requires_pending;
7
static int _edje_file_cache_size = 16;
8
static Eina_List *_edje_file_cache = NULL;
9

10
static int _edje_collection_cache_size = 16;
11

12
EAPI void
13
edje_cache_emp_alloc(Edje_Part_Collection_Directory_Entry *ce)
14
{
15
   /* Init Eina Mempools this is also used in edje_pick.c */
16
   char *buffer;
17
   ce->mp = calloc(1, sizeof(Edje_Part_Collection_Directory_Entry_Mp));
18
   if (!ce->mp) return;
19

20
#define INIT_EMP(Tp, Sz, Ce) \
21
  buffer = alloca(strlen(ce->entry) + strlen(#Tp) + 2); \
22
  sprintf(buffer, "%s/%s", ce->entry, #Tp); \
23
  Ce->mp->mp.Tp = eina_mempool_add("one_big", buffer, NULL, sizeof (Sz), Ce->count.Tp); \
24
  _emp_##Tp = Ce->mp->mp.Tp;
25

26
#define INIT_EMP_BOTH(Tp, Sz, Ce) \
27
  INIT_EMP(Tp, Sz, Ce) \
28
  Ce->mp->mp_rtl.Tp = eina_mempool_add("one_big", buffer, NULL, \
29
                                       sizeof(Sz), Ce->count.Tp);
30

31
  INIT_EMP_BOTH(RECTANGLE, Edje_Part_Description_Common, ce);
32
  INIT_EMP_BOTH(TEXT, Edje_Part_Description_Text, ce);
33
  INIT_EMP_BOTH(IMAGE, Edje_Part_Description_Image, ce);
34
  INIT_EMP_BOTH(PROXY, Edje_Part_Description_Proxy, ce);
35
  INIT_EMP_BOTH(SWALLOW, Edje_Part_Description_Common, ce);
36
  INIT_EMP_BOTH(TEXTBLOCK, Edje_Part_Description_Text, ce);
37
  INIT_EMP_BOTH(GROUP, Edje_Part_Description_Common, ce);
38
  INIT_EMP_BOTH(BOX, Edje_Part_Description_Box, ce);
39
  INIT_EMP_BOTH(TABLE, Edje_Part_Description_Table, ce);
40
  INIT_EMP_BOTH(EXTERNAL, Edje_Part_Description_External, ce);
41
  INIT_EMP_BOTH(SPACER, Edje_Part_Description_Common, ce);
42
  INIT_EMP_BOTH(SNAPSHOT, Edje_Part_Description_Snapshot, ce);
43
  INIT_EMP_BOTH(VECTOR, Edje_Part_Description_Vector, ce);
44
  INIT_EMP(part, Edje_Part, ce);
45
}
46

47
EAPI void
48
edje_cache_emp_free(Edje_Part_Collection_Directory_Entry *ce)
49
{  /* Free Eina Mempools this is also used in edje_pick.c */
50
   /* Destroy all part and description. */
51
   ce->ref = NULL;
52

53
   if (!ce->mp) return;
54
   eina_mempool_del(ce->mp->mp.RECTANGLE);
55
   eina_mempool_del(ce->mp->mp.TEXT);
56
   eina_mempool_del(ce->mp->mp.IMAGE);
57
   eina_mempool_del(ce->mp->mp.PROXY);
58
   eina_mempool_del(ce->mp->mp.SWALLOW);
59
   eina_mempool_del(ce->mp->mp.TEXTBLOCK);
60
   eina_mempool_del(ce->mp->mp.GROUP);
61
   eina_mempool_del(ce->mp->mp.BOX);
62
   eina_mempool_del(ce->mp->mp.TABLE);
63
   eina_mempool_del(ce->mp->mp.EXTERNAL);
64
   eina_mempool_del(ce->mp->mp.SPACER);
65
   eina_mempool_del(ce->mp->mp.SNAPSHOT);
66
   eina_mempool_del(ce->mp->mp.VECTOR);
67
   eina_mempool_del(ce->mp->mp.part);
68
   memset(&ce->mp->mp, 0, sizeof(ce->mp->mp));
69

70
   eina_mempool_del(ce->mp->mp_rtl.RECTANGLE);
71
   eina_mempool_del(ce->mp->mp_rtl.TEXT);
72
   eina_mempool_del(ce->mp->mp_rtl.IMAGE);
73
   eina_mempool_del(ce->mp->mp_rtl.PROXY);
74
   eina_mempool_del(ce->mp->mp_rtl.SWALLOW);
75
   eina_mempool_del(ce->mp->mp_rtl.TEXTBLOCK);
76
   eina_mempool_del(ce->mp->mp_rtl.GROUP);
77
   eina_mempool_del(ce->mp->mp_rtl.BOX);
78
   eina_mempool_del(ce->mp->mp_rtl.TABLE);
79
   eina_mempool_del(ce->mp->mp_rtl.EXTERNAL);
80
   eina_mempool_del(ce->mp->mp_rtl.SPACER);
81
   eina_mempool_del(ce->mp->mp_rtl.SNAPSHOT);
82
   eina_mempool_del(ce->mp->mp_rtl.VECTOR);
83
   memset(&ce->mp->mp_rtl, 0, sizeof(ce->mp->mp_rtl));
84

85
   free(ce->mp);
86
}
87

88
void
89
_edje_programs_patterns_init(Edje_Part_Collection *edc)
90
{
91
   Edje_Signals_Sources_Patterns *ssp = &edc->patterns.programs;
92
   Edje_Program **all;
93
   unsigned int i, j;
94

95
   if (ssp->signals_patterns)
96
     return;
97

98
   static signed char dump_programs = -1;
99

100
   if (dump_programs == -1)
101
     {
102
        if (getenv("EDJE_DUMP_PROGRAMS")) dump_programs = 1;
103
        else dump_programs = 0;
104
     }
105
   if (dump_programs == 1)
106
     {
107
        INF("Group '%s' programs:", edc->part);
108
#define EDJE_DUMP_PROGRAM(Section)                    \
109
  for (i = 0; i < edc->programs.Section##_count; i++) \
110
    INF(#Section " for ('%s', '%s')", edc->programs.Section[i]->signal, edc->programs.Section[i]->source);
111

112
        EDJE_DUMP_PROGRAM(strcmp);
113
        EDJE_DUMP_PROGRAM(strncmp);
114
        EDJE_DUMP_PROGRAM(strrncmp);
115
        EDJE_DUMP_PROGRAM(fnmatch);
116
        EDJE_DUMP_PROGRAM(nocmp);
117
     }
118

119
   edje_match_program_hash_build(edc->programs.strcmp,
120
                                 edc->programs.strcmp_count,
121
                                 &ssp->exact_match);
122

123
   j = edc->programs.strncmp_count
124
     + edc->programs.strrncmp_count
125
     + edc->programs.fnmatch_count
126
     + edc->programs.nocmp_count;
127
   if (j == 0) return;
128

129
   all = malloc(sizeof (Edje_Program *) * j);
130
   if (!all) return;
131
   j = 0;
132

133
   /* FIXME: Build specialized data type for each case */
134
#define EDJE_LOAD_PROGRAMS_ADD(Array, Edc, It, Git, All)                \
135
   for (It = 0; It < Edc->programs.Array##_count; ++It, ++Git)          \
136
     All[Git] = Edc->programs.Array[It];
137

138
   EDJE_LOAD_PROGRAMS_ADD(fnmatch, edc, i, j, all);
139
   EDJE_LOAD_PROGRAMS_ADD(strncmp, edc, i, j, all);
140
   EDJE_LOAD_PROGRAMS_ADD(strrncmp, edc, i, j, all);
141
   /* FIXME: Do a special pass for that one */
142
   EDJE_LOAD_PROGRAMS_ADD(nocmp, edc, i, j, all);
143

144
   ssp->u.programs.globing = all;
145
   ssp->u.programs.count = j;
146
   ssp->signals_patterns = edje_match_programs_signal_init(all, j);
147
   ssp->sources_patterns = edje_match_programs_source_init(all, j);
148
}
149

150
static inline void
151
_edje_part_collection_fix(Edje_Part_Collection *edc)
152
{
153
   if (edc->checked) return;
154

155
   edc->checked = 1;
156

157
   unsigned int j;
158
   Edje_Part *ep;
159
   Eina_Array hist;
160

161
   eina_array_step_set(&hist, sizeof(Eina_Array), 5);
162

163
   for (j = 0; j < edc->parts_count; ++j)
164
     {
165
        Edje_Part *ep2;
166
        ep = edc->parts[j];
167

168
        /* Register any color classes in this parts descriptions. */
169
        eina_array_push(&hist, ep);
170
        ep2 = ep;
171
        while (ep2->dragable.confine_id >= 0)
172
          {
173
             if (ep2->dragable.confine_id >= (int)edc->parts_count)
174
               {
175
                  ERR("confine_to above limit. invalidating it.");
176
                  ep2->dragable.confine_id = -1;
177
                  break;
178
               }
179

180
             ep2 = edc->parts[ep2->dragable.confine_id];
181
             if (eina_array_find(&hist, ep2, NULL))
182
               {
183
                  ERR("confine_to loops. invalidating loop.");
184
                  ep2->dragable.confine_id = -1;
185
                  break;
186
               }
187
             eina_array_push(&hist, ep2);
188
          }
189
        eina_array_clean(&hist);
190

191
        eina_array_push(&hist, ep);
192
        ep2 = ep;
193
        while (ep2->dragable.event_id >= 0)
194
          {
195
             Edje_Part *prev;
196

197
             if (ep2->dragable.event_id >= (int)edc->parts_count)
198
               {
199
                  ERR("event_id above limit. invalidating it.");
200
                  ep2->dragable.event_id = -1;
201
                  break;
202
               }
203
             prev = ep2;
204

205
             ep2 = edc->parts[ep2->dragable.event_id];
206
             /* events_to may be used only with dragable */
207
             if (!ep2->dragable.x && !ep2->dragable.y)
208
               {
209
                  prev->dragable.event_id = -1;
210
                  break;
211
               }
212

213
             if (eina_array_find(&hist, ep2, NULL))
214
               {
215
                  ERR("events_to loops. invalidating loop.");
216
                  ep2->dragable.event_id = -1;
217
                  break;
218
               }
219
             eina_array_push(&hist, ep2);
220
          }
221
        eina_array_clean(&hist);
222

223
        eina_array_push(&hist, ep);
224
        ep2 = ep;
225
        while (ep2->clip_to_id >= 0)
226
          {
227
             if (ep2->clip_to_id >= (int)edc->parts_count)
228
               {
229
                  ERR("clip_to_id above limit. invalidating it.");
230
                  ep2->clip_to_id = -1;
231
                  break;
232
               }
233

234
             ep2 = edc->parts[ep2->clip_to_id];
235
             if (eina_array_find(&hist, ep2, NULL))
236
               {
237
                  ERR("clip_to loops. invalidating loop.");
238
                  ep2->clip_to_id = -1;
239
                  break;
240
               }
241
             eina_array_push(&hist, ep2);
242
          }
243
        eina_array_clean(&hist);
244
     }
245
     eina_array_flush(&hist);
246
}
247

248
static Edje_Part_Collection *
249
_edje_file_coll_open(Edje_File *edf, const char *coll)
250
{
251
   Edje_Part_Collection *edc = NULL;
252
   Edje_Part_Collection_Directory_Entry *ce;
253
   int id = -1, size = 0;
254
   unsigned int n;
255
   Eina_List *l;
256
   char buf[256];
257
   void *data;
258

259
   ce = eina_hash_find(edf->collection, coll);
260
   if (!ce) return NULL;
261

262
   if (ce->ref)
263
     {
264
        ce->ref->references++;
265
        return ce->ref;
266
     }
267

268
   EINA_LIST_FOREACH(edf->collection_cache, l, edc)
269
     {
270
        if (!strcmp(edc->part, coll))
271
          {
272
             edc->references = 1;
273
             ce->ref = edc;
274

275
             edf->collection_cache = eina_list_remove_list(edf->collection_cache, l);
276
             return ce->ref;
277
          }
278
     }
279

280
   id = ce->id;
281
   if (id < 0) return NULL;
282

283
   edje_cache_emp_alloc(ce);
284
   snprintf(buf, sizeof(buf), "edje/collections/%i", id);
285
   edc = eet_data_read(edf->ef, _edje_edd_edje_part_collection, buf);
286
   if (!edc) return NULL;
287

288
   edc->references = 1;
289
   edc->part = ce->entry;
290

291
   /* For Edje file build with Edje 1.0 */
292
   if (edf->version <= 3 && edf->minor <= 1)
293
     {
294
        /* This will preserve previous rendering */
295
        unsigned int i;
296

297
        /* people expect signal to not be broadcasted */
298
        edc->broadcast_signal = EINA_FALSE;
299

300
        /* people expect text.align to be 0.0 0.0 */
301
        for (i = 0; i < edc->parts_count; ++i)
302
          {
303
             if (edc->parts[i]->type == EDJE_PART_TYPE_TEXTBLOCK)
304
               {
305
                  Edje_Part_Description_Text *text;
306
                  unsigned int j;
307

308
                  text = (Edje_Part_Description_Text *)edc->parts[i]->default_desc;
309
                  text->text.align.x = TO_DOUBLE(0.0);
310
                  text->text.align.y = TO_DOUBLE(0.0);
311

312
                  for (j = 0; j < edc->parts[i]->other.desc_count; ++j)
313
                    {
314
                       text = (Edje_Part_Description_Text *)edc->parts[i]->other.desc[j];
315
                       text->text.align.x = TO_DOUBLE(0.0);
316
                       text->text.align.y = TO_DOUBLE(0.0);
317
                    }
318
               }
319
          }
320
     }
321

322
   snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", id);
323
   data = eet_read(edf->ef, buf, &size);
324

325
   if (data)
326
     {
327
        edc->script = embryo_program_new(data, size);
328
        _edje_embryo_script_init(edc);
329
        free(data);
330
     }
331

332
   snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", id);
333
   data = eet_read(edf->ef, buf, &size);
334

335
   if (data)
336
     {
337
        _edje_lua2_script_load(edc, data, size);
338
        free(data);
339
     }
340

341
   ce->ref = edc;
342

343
   _edje_programs_patterns_init(edc);
344

345
   n = edc->programs.fnmatch_count +
346
     edc->programs.strcmp_count +
347
     edc->programs.strncmp_count +
348
     edc->programs.strrncmp_count +
349
     edc->programs.nocmp_count;
350

351
   if (n > 0)
352
     {
353
        Edje_Program *pr;
354
        unsigned int i;
355

356
        edc->patterns.table_programs = malloc(sizeof(Edje_Program *) * n);
357
        if (edc->patterns.table_programs)
358
          {
359
             edc->patterns.table_programs_size = n;
360

361
#define EDJE_LOAD_BUILD_TABLE(Array, Edc, It, Tmp)                      \
362
             for (It = 0; It < Edc->programs.Array##_count; ++It)       \
363
               {                                                        \
364
                  Tmp = Edc->programs.Array[It];                        \
365
                  Edc->patterns.table_programs[Tmp->id] = Tmp;          \
366
                  if (!Edc->need_seat && Tmp->signal && !strncmp(Tmp->signal, "seat,", 5)) \
367
                    Edc->need_seat = EINA_TRUE;                         \
368
               }
369

370
             EDJE_LOAD_BUILD_TABLE(fnmatch, edc, i, pr);
371
             EDJE_LOAD_BUILD_TABLE(strcmp, edc, i, pr);
372
             EDJE_LOAD_BUILD_TABLE(strncmp, edc, i, pr);
373
             EDJE_LOAD_BUILD_TABLE(strrncmp, edc, i, pr);
374
             EDJE_LOAD_BUILD_TABLE(nocmp, edc, i, pr);
375
          }
376
     }
377

378
   /* Search for the use of allowed seat used by part if we still do not know if seat are needed. */
379
   if (!edc->need_seat)
380
     {
381
        unsigned int i;
382

383
        for (i = 0; i < edc->parts_count; i++)
384
          {
385
             Edje_Part *part = edc->parts[i];
386

387
             if (part->allowed_seats)
388
               {
389
                  edc->need_seat = EINA_TRUE;
390
                  break;
391
               }
392
          }
393
     }
394

395
   _edje_part_collection_fix(edc);
396

397
   return edc;
398
}
399

400
void
401
_edje_extract_mo_files(Edje_File *edf)
402
{
403
   Eina_Strbuf *mo_id_str;
404
   const void *data;
405
   const char *cache_path;
406
   const char *filename;
407
   unsigned int crc;
408
   time_t t;
409
   size_t sz;
410
   unsigned int i;
411
   int len;
412

413
   cache_path = efreet_cache_home_get();
414

415
   t = eina_file_mtime_get(edf->f);
416
   sz = eina_file_size_get(edf->f);
417
   filename = eina_file_filename_get(edf->f);
418
   crc = eina_crc(filename, strlen(filename), 0xffffffff, EINA_TRUE);
419

420
   snprintf(edf->fid, sizeof(edf->fid), "%lld-%lld-%x",
421
            (long long int)t,
422
            (long long int)sz,
423
            crc);
424

425
   mo_id_str = eina_strbuf_new();
426

427
   for (i = 0; i < edf->mo_dir->mo_entries_count; i++)
428
     {
429
        Edje_Mo *mo_entry;
430
        char out[PATH_MAX + PATH_MAX + 128];
431
        char outdir[PATH_MAX];
432
        char *sub_str;
433
        char *mo_src;
434

435
        mo_entry = &edf->mo_dir->mo_entries[i];
436

437
        eina_strbuf_append_printf(mo_id_str,
438
                                  "edje/mo/%i/%s/LC_MESSAGES",
439
                                  mo_entry->id,
440
                                  mo_entry->locale);
441
        data = eet_read_direct(edf->ef,
442
                               eina_strbuf_string_get(mo_id_str),
443
                               &len);
444

445
        if (data)
446
          {
447
             snprintf(outdir, sizeof(outdir),
448
                      "%s/edje/%s/LC_MESSAGES",
449
                      cache_path, mo_entry->locale);
450
             ecore_file_mkpath(outdir);
451
             mo_src = strdup(mo_entry->mo_src);
452
             sub_str = strstr(mo_src, ".po");
453

454
             if (sub_str)
455
               sub_str[1] = 'm';
456

457
             snprintf(out, sizeof(out), "%s/%s-%s",
458
                      outdir, edf->fid, mo_src);
459
             if (ecore_file_exists(out))
460
               {
461
                  if (edf->mtime > ecore_file_mod_time(out))
462
                    ecore_file_remove(out);
463
               }
464
             if (!ecore_file_exists(out))
465
               {
466
                  FILE *f;
467

468
                  f = fopen(out, "wb");
469
                  if (f)
470
                    {
471
                       if (fwrite(data, len, 1, f) != 1)
472
                         ERR("Could not write mo: %s: %s", out, strerror(errno));
473
                       fclose(f);
474
                    }
475
                  else
476
                    ERR("Could not open for writing mo: %s: %s", out, strerror(errno));
477
               }
478
             free(mo_src);
479
          }
480

481
        eina_strbuf_reset(mo_id_str);
482
     }
483

484
   eina_strbuf_free(mo_id_str);
485
}
486

487
// XXX: this is not pretty. some oooooold edje files do not store strings
488
// in their dictionary for hashes. this works around crashes loading such
489
// files
490
extern size_t  _edje_data_string_mapping_size;
491
extern void   *_edje_data_string_mapping;
492

493
static Edje_File *
494
_edje_file_open(const Eina_File *f, int *error_ret, time_t mtime, Eina_Bool coll)
495
{
496
   Edje_Color_Tree_Node *ctn;
497
   Edje_Color_Class *cc;
498
   Edje_Text_Class *tc;
499
   Edje_Size_Class *sc;
500
   Edje_Style      *stl;
501
   Edje_File *edf;
502
   Eina_List *l, *ll;
503
   Eet_File *ef;
504
   char *name;
505
   void *mapping;
506
   size_t mapping_size;
507

508
   ef = eet_mmap(f);
509
   if (!ef)
510
     {
511
        *error_ret = EDJE_LOAD_ERROR_UNKNOWN_FORMAT;
512
        return NULL;
513
     }
514
   // XXX: ancient edje file workaround
515
   mapping = eina_file_map_all((Eina_File *)f, EINA_FILE_SEQUENTIAL);
516
   if (mapping)
517
     {
518
        mapping_size = eina_file_size_get(f);
519
        _edje_data_string_mapping = mapping;
520
        _edje_data_string_mapping_size = mapping_size;
521
     }
522
   edf = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
523
   // XXX: ancient edje file workaround
524
   if (mapping)
525
     {
526
        eina_file_map_free((Eina_File *)f, mapping);
527
        _edje_data_string_mapping = NULL;
528
     }
529
   if (!edf)
530
     {
531
        *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
532
        eet_close(ef);
533
        return NULL;
534
     }
535

536
   edf->f = eina_file_dup(f);
537
   edf->ef = ef;
538
   edf->mtime = mtime;
539

540
   if (edf->version != EDJE_FILE_VERSION)
541
     {
542
        *error_ret = EDJE_LOAD_ERROR_INCOMPATIBLE_FILE;
543
        _edje_file_free(edf);
544
        return NULL;
545
     }
546
   if (!edf->collection && coll)
547
     {
548
        *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
549
        _edje_file_free(edf);
550
        return NULL;
551
     }
552

553
   if (edf->minor > EDJE_FILE_MINOR)
554
     {
555
        WRN("`%s` may use feature from a newer edje and could not show up as expected.",
556
            eina_file_filename_get(f));
557
     }
558
   if (edf->base_scale <= ZERO)
559
     {
560
        edf->base_scale = FROM_INT(1);
561
        WRN("The base_scale can not be a 0.0. It is changed the default value(1.0)");
562
     }
563

564
   /* Set default efl_version if there is no version information */
565
   if ((edf->efl_version.major == 0) && (edf->efl_version.minor == 0))
566
     {
567
        edf->efl_version.major = 1;
568
        edf->efl_version.minor = 18;
569
     }
570

571
   edf->path = eina_stringshare_add(eina_file_filename_get(f));
572
   edf->references = 1;
573

574
   /* This should be done at edje generation time */
575
   _edje_file_textblock_style_parse_and_fix(edf);
576

577
   edf->style_hash = eina_hash_string_small_new(NULL);
578
   EINA_LIST_FOREACH(edf->styles, l, stl)
579
     if (stl->name)
580
       eina_hash_direct_add(edf->style_hash, stl->name, stl);
581

582
   edf->color_tree_hash = eina_hash_string_small_new(NULL);
583
   EINA_LIST_FOREACH(edf->color_tree, l, ctn)
584
     EINA_LIST_FOREACH(ctn->color_classes, ll, name)
585
       eina_hash_add(edf->color_tree_hash, name, ctn);
586

587
   edf->color_hash = eina_hash_string_small_new(NULL);
588
   EINA_LIST_FOREACH(edf->color_classes, l, cc)
589
     if (cc->name)
590
       eina_hash_direct_add(edf->color_hash, cc->name, cc);
591

592
   edf->text_hash = eina_hash_string_small_new(NULL);
593
   EINA_LIST_FOREACH(edf->text_classes, l, tc)
594
     {
595
        if (tc->name)
596
          eina_hash_direct_add(edf->text_hash, tc->name, tc);
597

598
        if (tc->font)
599
          tc->font = eina_stringshare_add(tc->font);
600
     }
601

602
   edf->size_hash = eina_hash_string_small_new(NULL);
603
   EINA_LIST_FOREACH(edf->size_classes, l, sc)
604
     if (sc->name)
605
       eina_hash_direct_add(edf->size_hash, sc->name, sc);
606

607
   if (edf->requires_count)
608
     {
609
        unsigned int i;
610
        Edje_File *required_edf;
611
        char **requires = (char**)edf->requires;
612

613
        /* EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING returns an mmapped blob, not stringshares */
614
        edf->requires = malloc(edf->requires_count * sizeof(char*));
615
        for (i = 0; i < edf->requires_count; i++)
616
          {
617
             char *str = (char*)requires[i];
618

619
             edf->requires[i] = eina_stringshare_add(str);
620
             required_edf = eina_hash_find(_edje_id_hash, edf->requires[i]);
621
             if (required_edf)
622
               {
623
                  required_edf->references++;
624
                  continue;
625
               }
626
             ERR("edje file '%s' REQUIRES file '%s' which is not loaded", edf->path, edf->requires[i]);
627
             if (!_edje_requires_pending)
628
               _edje_requires_pending = eina_hash_stringshared_new(NULL);
629
             eina_hash_list_append(_edje_requires_pending, edf->requires[i], edf);
630
          }
631
        free(requires);
632
     }
633
   if (_edje_requires_pending && edf->id)
634
     {
635
        l = eina_hash_set(_edje_requires_pending, edf->id, NULL);
636

637
        edf->references += eina_list_count(l);
638
        eina_list_free(l);
639

640
        if (!eina_hash_population(_edje_requires_pending))
641
          {
642
             eina_hash_free(_edje_requires_pending);
643
             _edje_requires_pending = NULL;
644
          }
645
     }
646

647
   if (edf->external_dir)
648
     {
649
        unsigned int i;
650

651
        for (i = 0; i < edf->external_dir->entries_count; ++i)
652
          edje_module_load(edf->external_dir->entries[i].entry);
653
     }
654

655
   // this call is unnecessary as we are doing same opeartion
656
   // inside _edje_textblock_style_parse_and_fix() function
657
   // remove ??
658
   //_edje_textblock_style_all_update(ed);
659

660
   if (edf->mo_dir)
661
     _edje_extract_mo_files(edf);
662

663
   return edf;
664
}
665

666
#if 0
667
// FIXME: find a way to remove dangling file earlier
668
static void
669
_edje_file_dangling(Edje_File *edf)
670
{
671
   if (edf->dangling) return;
672
   edf->dangling = EINA_TRUE;
673

674
   eina_hash_del(_edje_file_hash, &edf->f, edf);
675
   if (!eina_hash_population(_edje_file_hash))
676
     {
677
        eina_hash_free(_edje_file_hash);
678
        _edje_file_hash = NULL;
679
     }
680
}
681

682
#endif
683

684
static inline void
685
_edje_file_cache_init()
686
{
687
   if (!_edje_id_hash)
688
     _edje_id_hash = eina_hash_stringshared_new(NULL);
689
   if (!_edje_file_hash)
690
     _edje_file_hash = eina_hash_pointer_new(NULL);
691
}
692

693
static inline Edje_File*
694
_edje_file_cache_trash_pop(const Eina_File *file)
695
{
696
   Edje_File *edf;
697
   Eina_List *l;
698

699
   EINA_LIST_FOREACH(_edje_file_cache, l, edf)
700
     {
701
        if (edf->f == file)
702
          {
703
             edf->references = 1;
704
             _edje_file_cache = eina_list_remove_list(_edje_file_cache, l);
705
             eina_hash_direct_add(_edje_file_hash, &edf->f, edf);
706
             return edf;
707
          }
708
     }
709
   return NULL;
710
}
711

712
Edje_File*
713
_edje_file_cache_find(const Eina_File *file)
714
{
715
   Edje_File *edf;
716

717
   // initialize cache.
718
   _edje_file_cache_init();
719

720
   // serach in the file_hash.
721
   edf = eina_hash_find(_edje_file_hash, &file);
722
   if (edf)
723
     {
724
        edf->references++;
725
        return edf;
726
     }
727

728
   // search in the trash list
729
   return _edje_file_cache_trash_pop(file);
730
}
731

732
static inline void
733
_edje_file_cache_add(Edje_File *edf)
734
{
735
   eina_hash_direct_add(_edje_file_hash, &edf->f, edf);
736
   if (edf->id)
737
     eina_hash_list_append(_edje_id_hash, edf->id, edf);
738
}
739

740
Edje_File *
741
_edje_cache_file_coll_open(const Eina_File *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret, Edje *ed EINA_UNUSED)
742
{
743
   Edje_File *edf;
744
   Edje_Part_Collection *edc;
745

746
   edf = _edje_file_cache_find(file);
747

748
   if (!edf)
749
     {
750
        edf = _edje_file_open(file, error_ret, eina_file_mtime_get(file), !!coll);
751
        if (!edf) return NULL;
752
        _edje_file_cache_add(edf);
753
     }
754

755
   if (!coll)
756
     return edf;
757

758
   edc = _edje_file_coll_open(edf, coll);
759
   if (!edc)
760
     *error_ret = EDJE_LOAD_ERROR_UNKNOWN_COLLECTION;
761

762
   if (edc_ret) *edc_ret = edc;
763

764
   return edf;
765
}
766

767
void
768
_edje_cache_coll_clean(Edje_File *edf)
769
{
770
   while ((edf->collection_cache) &&
771
          (eina_list_count(edf->collection_cache) > (unsigned int)_edje_collection_cache_size))
772
     {
773
        Edje_Part_Collection_Directory_Entry *ce;
774
        Edje_Part_Collection *edc;
775

776
        edc = eina_list_data_get(eina_list_last(edf->collection_cache));
777
        edf->collection_cache = eina_list_remove_list(edf->collection_cache, eina_list_last(edf->collection_cache));
778

779
        ce = eina_hash_find(edf->collection, edc->part);
780
        _edje_collection_free(edf, edc, ce);
781
     }
782
}
783

784
void
785
_edje_cache_coll_flush(Edje_File *edf)
786
{
787
   while (edf->collection_cache)
788
     {
789
        Edje_Part_Collection_Directory_Entry *ce;
790
        Edje_Part_Collection *edc;
791
        Eina_List *last;
792

793
        last = eina_list_last(edf->collection_cache);
794
        edc = eina_list_data_get(last);
795
        edf->collection_cache = eina_list_remove_list(edf->collection_cache,
796
                                                      last);
797

798
        ce = eina_hash_find(edf->collection, edc->part);
799
        _edje_collection_free(edf, edc, ce);
800
     }
801
}
802

803
void
804
_edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc)
805
{
806
   Edje_Part_Collection_Directory_Entry *ce;
807

808
   edc->references--;
809
   if (edc->references != 0) return;
810

811
   ce = eina_hash_find(edf->collection, edc->part);
812
   if (!ce)
813
     {
814
        ERR("Something is wrong with reference count of '%s'.", edc->part);
815
     }
816
   else if (ce->ref)
817
     {
818
        ce->ref = NULL;
819

820
        if (edf->dangling)
821
          {
822
             /* No need to keep the collection around if the file is dangling */
823
             _edje_collection_free(edf, edc, ce);
824
             _edje_cache_coll_flush(edf);
825
          }
826
        else
827
          {
828
             edf->collection_cache = eina_list_prepend(edf->collection_cache, edc);
829
             _edje_cache_coll_clean(edf);
830
          }
831
     }
832
}
833

834
static void
835
_edje_cache_file_clean(void)
836
{
837
   int count;
838

839
   count = eina_list_count(_edje_file_cache);
840
   while ((_edje_file_cache) && (count > _edje_file_cache_size))
841
     {
842
        Eina_List *last;
843
        Edje_File *edf;
844

845
        last = eina_list_last(_edje_file_cache);
846
        edf = eina_list_data_get(last);
847
        _edje_file_cache = eina_list_remove_list(_edje_file_cache, last);
848
        _edje_file_free(edf);
849
        count = eina_list_count(_edje_file_cache);
850
     }
851
}
852

853
EAPI void
854
_edje_cache_file_unref(Edje_File *edf)
855
{
856
   edf->references--;
857
   if (edf->references != 0) return;
858

859
   if (edf->requires_count)
860
     {
861
        unsigned int i;
862

863
        for (i = 0; i < edf->requires_count; i++)
864
          {
865
             Edje_File *required_edf = eina_hash_find(_edje_id_hash, edf->requires[i]);
866

867
             if (required_edf)
868
               _edje_cache_file_unref(edf);
869
             else if (_edje_requires_pending)
870
               {
871
                  eina_hash_list_remove(_edje_requires_pending, edf->requires[i], edf);
872
                  if (!eina_hash_population(_edje_requires_pending))
873
                    {
874
                       eina_hash_free(_edje_requires_pending);
875
                       _edje_requires_pending = NULL;
876
                    }
877
               }
878
          }
879
     }
880

881
   if (edf->dangling)
882
     {
883
        _edje_file_free(edf);
884
        return;
885
     }
886

887
   if (edf->id)
888
     eina_hash_list_remove(_edje_id_hash, edf->id, edf);
889
   if (!eina_hash_population(_edje_id_hash))
890
     {
891
        eina_hash_free(_edje_id_hash);
892
        _edje_id_hash = NULL;
893
     }
894
   eina_hash_del(_edje_file_hash, &edf->f, edf);
895
   if (!eina_hash_population(_edje_file_hash))
896
     {
897
        eina_hash_free(_edje_file_hash);
898
        _edje_file_hash = NULL;
899
     }
900
   _edje_file_cache = eina_list_prepend(_edje_file_cache, edf);
901
   _edje_cache_file_clean();
902
}
903

904
void
905
_edje_file_cache_shutdown(void)
906
{
907
   edje_file_cache_flush();
908
}
909

910
/*============================================================================*
911
*                                 Global                                     *
912
*============================================================================*/
913

914
/*============================================================================*
915
*                                   API                                      *
916
*============================================================================*/
917

918
EAPI void
919
edje_file_cache_set(int count)
920
{
921
   if (count < 0) count = 0;
922
   _edje_file_cache_size = count;
923
   _edje_cache_file_clean();
924
}
925

926
EAPI int
927
edje_file_cache_get(void)
928
{
929
   return _edje_file_cache_size;
930
}
931

932
EAPI void
933
edje_file_cache_flush(void)
934
{
935
   int ps;
936

937
   ps = _edje_file_cache_size;
938
   _edje_file_cache_size = 0;
939
   _edje_cache_file_clean();
940
   _edje_file_cache_size = ps;
941
}
942

943
EAPI void
944
edje_collection_cache_set(int count)
945
{
946
   Eina_List *l;
947
   Edje_File *edf;
948

949
   if (count < 0) count = 0;
950
   _edje_collection_cache_size = count;
951
   EINA_LIST_FOREACH(_edje_file_cache, l, edf)
952
     _edje_cache_coll_clean(edf);
953
   /* FIXME: freach in file hash too! */
954
}
955

956
EAPI int
957
edje_collection_cache_get(void)
958
{
959
   return _edje_collection_cache_size;
960
}
961

962
EAPI void
963
edje_collection_cache_flush(void)
964
{
965
   int ps;
966
   Eina_List *l;
967
   Edje_File *edf;
968

969
   ps = _edje_collection_cache_size;
970
   _edje_collection_cache_size = 0;
971
   EINA_LIST_FOREACH(_edje_file_cache, l, edf)
972
     _edje_cache_coll_flush(edf);
973
   /* FIXME: freach in file hash too! */
974
   _edje_collection_cache_size = ps;
975
}
976

977

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.