aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/lib/edje_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/lib/edje_cache.c')
-rw-r--r--libraries/edje/src/lib/edje_cache.c570
1 files changed, 570 insertions, 0 deletions
diff --git a/libraries/edje/src/lib/edje_cache.c b/libraries/edje/src/lib/edje_cache.c
new file mode 100644
index 0000000..a8b355f
--- /dev/null
+++ b/libraries/edje/src/lib/edje_cache.c
@@ -0,0 +1,570 @@
1#include "edje_private.h"
2
3
4/**
5 * @cond
6 */
7
8static Eina_Hash *_edje_file_hash = NULL;
9static int _edje_file_cache_size = 16;
10static Eina_List *_edje_file_cache = NULL;
11
12static int _edje_collection_cache_size = 16;
13
14static Edje_Part_Collection *
15_edje_file_coll_open(Edje_File *edf, const char *coll)
16{
17 Edje_Part_Collection *edc = NULL;
18 Edje_Part_Collection_Directory_Entry *ce;
19 int id = -1, size = 0;
20 Eina_List *l;
21 char buf[256];
22 char *buffer;
23 void *data;
24
25 ce = eina_hash_find(edf->collection, coll);
26 if (!ce) return NULL;
27
28 if (ce->ref)
29 {
30 ce->ref->references++;
31 return ce->ref;
32 }
33
34 EINA_LIST_FOREACH(edf->collection_cache, l, edc)
35 {
36 if (!strcmp(edc->part, coll))
37 {
38 edc->references = 1;
39 ce->ref = edc;
40
41 edf->collection_cache = eina_list_remove_list(edf->collection_cache, l);
42 return ce->ref;
43 }
44 }
45
46 id = ce->id;
47 if (id < 0) return NULL;
48
49#define INIT_EMP(Tp, Sz, Ce) \
50 buffer = alloca(strlen(ce->entry) + strlen(#Tp) + 2); \
51 sprintf(buffer, "%s/%s", ce->entry, #Tp); \
52 Ce->mp.Tp = eina_mempool_add("one_big", buffer, NULL, sizeof (Sz), Ce->count.Tp); \
53 _emp_##Tp = Ce->mp.Tp;
54
55#define INIT_EMP_BOTH(Tp, Sz, Ce) \
56 INIT_EMP(Tp, Sz, Ce) \
57 Ce->mp_rtl.Tp = eina_mempool_add("one_big", buffer, NULL, \
58 sizeof (Sz), Ce->count.Tp);
59
60 INIT_EMP_BOTH(RECTANGLE, Edje_Part_Description_Common, ce);
61 INIT_EMP_BOTH(TEXT, Edje_Part_Description_Text, ce);
62 INIT_EMP_BOTH(IMAGE, Edje_Part_Description_Image, ce);
63 INIT_EMP_BOTH(PROXY, Edje_Part_Description_Proxy, ce);
64 INIT_EMP_BOTH(SWALLOW, Edje_Part_Description_Common, ce);
65 INIT_EMP_BOTH(TEXTBLOCK, Edje_Part_Description_Text, ce);
66 INIT_EMP_BOTH(GROUP, Edje_Part_Description_Common, ce);
67 INIT_EMP_BOTH(BOX, Edje_Part_Description_Box, ce);
68 INIT_EMP_BOTH(TABLE, Edje_Part_Description_Table, ce);
69 INIT_EMP_BOTH(EXTERNAL, Edje_Part_Description_External, ce);
70 INIT_EMP(part, Edje_Part, ce);
71
72 snprintf(buf, sizeof(buf), "edje/collections/%i", id);
73 edc = eet_data_read(edf->ef, _edje_edd_edje_part_collection, buf);
74 if (!edc) return NULL;
75
76 edc->references = 1;
77 edc->part = ce->entry;
78
79 /* For Edje file build with Edje 1.0, people expect text.align to be 0.0 0.0 */
80 if (edf->version <= 3 && edf->minor <= 1)
81 {
82 /* This will preserve previous rendering */
83 unsigned int i;
84
85 for (i = 0; i < edc->parts_count; ++i)
86 {
87 if (edc->parts[i]->type == EDJE_PART_TYPE_TEXTBLOCK)
88 {
89 Edje_Part_Description_Text *text;
90 unsigned int j;
91
92 text = (Edje_Part_Description_Text*) edc->parts[i]->default_desc;
93 text->text.align.x = TO_DOUBLE(0.0);
94 text->text.align.y = TO_DOUBLE(0.0);
95
96 for (j = 0; j < edc->parts[i]->other.desc_count; ++j)
97 {
98 text = (Edje_Part_Description_Text*) edc->parts[i]->other.desc[j];
99 text->text.align.x = TO_DOUBLE(0.0);
100 text->text.align.y = TO_DOUBLE(0.0);
101 }
102 }
103 }
104 }
105
106 snprintf(buf, sizeof(buf), "edje/scripts/embryo/compiled/%i", id);
107 data = eet_read(edf->ef, buf, &size);
108
109 if (data)
110 {
111 edc->script = embryo_program_new(data, size);
112 _edje_embryo_script_init(edc);
113 free(data);
114 }
115
116 snprintf(buf, sizeof(buf), "edje/scripts/lua/%i", id);
117 data = eet_read(edf->ef, buf, &size);
118
119 if (data)
120 {
121 _edje_lua2_script_load(edc, data, size);
122 free(data);
123 }
124
125 ce->ref = edc;
126
127 return edc;
128}
129
130static Edje_File *
131_edje_file_open(const char *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret)
132{
133 Edje_File *edf;
134 Edje_Part_Collection *edc;
135 Eet_File *ef;
136 struct stat st;
137
138 if (stat(file, &st) != 0)
139 {
140 *error_ret = EDJE_LOAD_ERROR_DOES_NOT_EXIST;
141 return NULL;
142 }
143
144 ef = eet_open(file, EET_FILE_MODE_READ);
145 if (!ef)
146 {
147 *error_ret = EDJE_LOAD_ERROR_UNKNOWN_FORMAT;
148 return NULL;
149 }
150 edf = eet_data_read(ef, _edje_edd_edje_file, "edje/file");
151 if (!edf)
152 {
153 *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
154 eet_close(ef);
155 return NULL;
156 }
157
158 edf->ef = ef;
159 edf->mtime = st.st_mtime;
160
161 if (edf->version != EDJE_FILE_VERSION)
162 {
163 *error_ret = EDJE_LOAD_ERROR_INCOMPATIBLE_FILE;
164 _edje_file_free(edf);
165 return NULL;
166 }
167 if (!edf->collection)
168 {
169 *error_ret = EDJE_LOAD_ERROR_CORRUPT_FILE;
170 _edje_file_free(edf);
171 return NULL;
172 }
173
174 if (edf->minor > EDJE_FILE_MINOR)
175 {
176 WRN("`%s` may use feature from a newer edje and could not show up as expected.", file);
177 }
178
179 edf->path = eina_stringshare_add(file);
180 edf->references = 1;
181
182 /* This should be done at edje generation time */
183 _edje_textblock_style_parse_and_fix(edf);
184
185 if (coll)
186 {
187 edc = _edje_file_coll_open(edf, coll);
188 if (!edc)
189 {
190 *error_ret = EDJE_LOAD_ERROR_UNKNOWN_COLLECTION;
191 }
192 if (edc_ret) *edc_ret = edc;
193 }
194
195 return edf;
196}
197
198static void
199_edje_file_dangling(Edje_File *edf)
200{
201 if (edf->dangling) return;
202 edf->dangling = EINA_TRUE;
203
204 eina_hash_del(_edje_file_hash, edf->path, edf);
205 if (!eina_hash_population(_edje_file_hash))
206 {
207 eina_hash_free(_edje_file_hash);
208 _edje_file_hash = NULL;
209 }
210}
211
212Edje_File *
213_edje_cache_file_coll_open(const char *file, const char *coll, int *error_ret, Edje_Part_Collection **edc_ret)
214{
215 Edje_File *edf;
216 Eina_List *l, *hist;
217 Edje_Part_Collection *edc;
218 Edje_Part *ep;
219 struct stat st;
220
221 if (stat(file, &st) != 0)
222 return NULL;
223
224 if (!_edje_file_hash)
225 {
226 _edje_file_hash = eina_hash_string_small_new(NULL);
227 goto open_new;
228 }
229
230 edf = eina_hash_find(_edje_file_hash, file);
231 if (edf)
232 {
233 if (edf->mtime != st.st_mtime)
234 {
235 _edje_file_dangling(edf);
236 goto open_new;
237 }
238
239 edf->references++;
240 goto open;
241 }
242
243 EINA_LIST_FOREACH(_edje_file_cache, l, edf)
244 {
245 if (!strcmp(edf->path, file))
246 {
247 if (edf->mtime != st.st_mtime)
248 {
249 _edje_file_cache = eina_list_remove_list(_edje_file_cache, l);
250 _edje_file_free(edf);
251 goto open_new;
252 }
253
254 edf->references = 1;
255 _edje_file_cache = eina_list_remove_list(_edje_file_cache, l);
256 eina_hash_add(_edje_file_hash, file, edf);
257 goto open;
258 }
259 }
260
261open_new:
262 if (!_edje_file_hash)
263 _edje_file_hash = eina_hash_string_small_new(NULL);
264
265 edf = _edje_file_open(file, coll, error_ret, edc_ret);
266 if (!edf)
267 return NULL;
268
269 eina_hash_add(_edje_file_hash, file, edf);
270 return edf;
271
272open:
273 if (!coll)
274 return edf;
275
276 edc = _edje_file_coll_open(edf, coll);
277 if (!edc)
278 {
279 *error_ret = EDJE_LOAD_ERROR_UNKNOWN_COLLECTION;
280 }
281 else
282 {
283 if (!edc->checked)
284 {
285 unsigned int j;
286
287 for (j = 0; j < edc->parts_count; ++j)
288 {
289 Edje_Part *ep2;
290
291 ep = edc->parts[j];
292
293 /* Register any color classes in this parts descriptions. */
294 hist = NULL;
295 hist = eina_list_append(hist, ep);
296 ep2 = ep;
297 while (ep2->dragable.confine_id >= 0)
298 {
299 if (ep2->dragable.confine_id >= (int) edc->parts_count)
300 {
301 ERR("confine_to above limit. invalidating it.");
302 ep2->dragable.confine_id = -1;
303 break;
304 }
305
306 ep2 = edc->parts[ep2->dragable.confine_id];
307 if (eina_list_data_find(hist, ep2))
308 {
309 ERR("confine_to loops. invalidating loop.");
310 ep2->dragable.confine_id = -1;
311 break;
312 }
313 hist = eina_list_append(hist, ep2);
314 }
315 eina_list_free(hist);
316 hist = NULL;
317 hist = eina_list_append(hist, ep);
318 ep2 = ep;
319 while (ep2->dragable.event_id >= 0)
320 {
321 Edje_Part* prev;
322
323 if (ep2->dragable.event_id >= (int) edc->parts_count)
324 {
325 ERR("event_id above limit. invalidating it.");
326 ep2->dragable.event_id = -1;
327 break;
328 }
329 prev = ep2;
330
331 ep2 = edc->parts[ep2->dragable.event_id];
332 if (!ep2->dragable.x && !ep2->dragable.y)
333 {
334 prev->dragable.event_id = -1;
335 break;
336 }
337
338 if (eina_list_data_find(hist, ep2))
339 {
340 ERR("events_to loops. invalidating loop.");
341 ep2->dragable.event_id = -1;
342 break;
343 }
344 hist = eina_list_append(hist, ep2);
345 }
346 eina_list_free(hist);
347 hist = NULL;
348 hist = eina_list_append(hist, ep);
349 ep2 = ep;
350 while (ep2->clip_to_id >= 0)
351 {
352 if (ep2->clip_to_id >= (int) edc->parts_count)
353 {
354 ERR("clip_to_id above limit. invalidating it.");
355 ep2->clip_to_id = -1;
356 break;
357 }
358
359 ep2 = edc->parts[ep2->clip_to_id];
360 if (eina_list_data_find(hist, ep2))
361 {
362 ERR("clip_to loops. invalidating loop.");
363 ep2->clip_to_id = -1;
364 break;
365 }
366 hist = eina_list_append(hist, ep2);
367 }
368 eina_list_free(hist);
369 hist = NULL;
370 }
371 edc->checked = 1;
372 }
373 }
374 if (edc_ret) *edc_ret = edc;
375
376 return edf;
377}
378
379void
380_edje_cache_coll_clean(Edje_File *edf)
381{
382 while ((edf->collection_cache) &&
383 (eina_list_count(edf->collection_cache) > (unsigned int) _edje_collection_cache_size))
384 {
385 Edje_Part_Collection_Directory_Entry *ce;
386 Edje_Part_Collection *edc;
387
388 edc = eina_list_data_get(eina_list_last(edf->collection_cache));
389 edf->collection_cache = eina_list_remove_list(edf->collection_cache, eina_list_last(edf->collection_cache));
390
391 ce = eina_hash_find(edf->collection, edc->part);
392 _edje_collection_free(edf, edc, ce);
393 }
394}
395
396void
397_edje_cache_coll_flush(Edje_File *edf)
398{
399 while (edf->collection_cache)
400 {
401 Edje_Part_Collection_Directory_Entry *ce;
402 Edje_Part_Collection *edc;
403 Eina_List *last;
404
405 last = eina_list_last(edf->collection_cache);
406 edc = eina_list_data_get(last);
407 edf->collection_cache = eina_list_remove_list(edf->collection_cache,
408 last);
409
410 ce = eina_hash_find(edf->collection, edc->part);
411 _edje_collection_free(edf, edc, ce);
412 }
413}
414
415void
416_edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc)
417{
418 Edje_Part_Collection_Directory_Entry *ce;
419
420 edc->references--;
421 if (edc->references != 0) return;
422
423 ce = eina_hash_find(edf->collection, edc->part);
424 if (!ce)
425 {
426 ERR("Something is wrong with reference count of '%s'.", edc->part);
427 }
428 else if (ce->ref)
429 {
430 ce->ref = NULL;
431
432 if (edf->dangling)
433 {
434 /* No need to keep the collection around if the file is dangling */
435 _edje_collection_free(edf, edc, ce);
436 _edje_cache_coll_flush(edf);
437 }
438 else
439 {
440 edf->collection_cache = eina_list_prepend(edf->collection_cache, edc);
441 _edje_cache_coll_clean(edf);
442 }
443 }
444}
445
446static void
447_edje_cache_file_clean(void)
448{
449 int count;
450
451 count = eina_list_count(_edje_file_cache);
452 while ((_edje_file_cache) && (count > _edje_file_cache_size))
453 {
454 Eina_List *last;
455 Edje_File *edf;
456
457 last = eina_list_last(_edje_file_cache);
458 edf = eina_list_data_get(last);
459 _edje_file_cache = eina_list_remove_list(_edje_file_cache, last);
460 _edje_file_free(edf);
461 count = eina_list_count(_edje_file_cache);
462 }
463}
464
465void
466_edje_cache_file_unref(Edje_File *edf)
467{
468 edf->references--;
469 if (edf->references != 0) return;
470
471 if (edf->dangling)
472 {
473 _edje_file_free(edf);
474 return;
475 }
476
477 eina_hash_del(_edje_file_hash, edf->path, edf);
478 if (!eina_hash_population(_edje_file_hash))
479 {
480 eina_hash_free(_edje_file_hash);
481 _edje_file_hash = NULL;
482 }
483 _edje_file_cache = eina_list_prepend(_edje_file_cache, edf);
484 _edje_cache_file_clean();
485}
486
487void
488_edje_file_cache_shutdown(void)
489{
490 edje_file_cache_flush();
491}
492
493
494
495/**
496 * @endcond
497 */
498
499/*============================================================================*
500 * Global *
501 *============================================================================*/
502
503/*============================================================================*
504 * API *
505 *============================================================================*/
506
507
508EAPI void
509edje_file_cache_set(int count)
510{
511 if (count < 0) count = 0;
512 _edje_file_cache_size = count;
513 _edje_cache_file_clean();
514}
515
516
517EAPI int
518edje_file_cache_get(void)
519{
520 return _edje_file_cache_size;
521}
522
523
524EAPI void
525edje_file_cache_flush(void)
526{
527 int ps;
528
529 ps = _edje_file_cache_size;
530 _edje_file_cache_size = 0;
531 _edje_cache_file_clean();
532 _edje_file_cache_size = ps;
533}
534
535
536EAPI void
537edje_collection_cache_set(int count)
538{
539 Eina_List *l;
540 Edje_File *edf;
541
542 if (count < 0) count = 0;
543 _edje_collection_cache_size = count;
544 EINA_LIST_FOREACH(_edje_file_cache, l, edf)
545 _edje_cache_coll_clean(edf);
546 /* FIXME: freach in file hash too! */
547}
548
549
550EAPI int
551edje_collection_cache_get(void)
552{
553 return _edje_collection_cache_size;
554}
555
556
557EAPI void
558edje_collection_cache_flush(void)
559{
560 int ps;
561 Eina_List *l;
562 Edje_File *edf;
563
564 ps = _edje_collection_cache_size;
565 _edje_collection_cache_size = 0;
566 EINA_LIST_FOREACH(_edje_file_cache, l, edf)
567 _edje_cache_coll_flush(edf);
568 /* FIXME: freach in file hash too! */
569 _edje_collection_cache_size = ps;
570}