Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_textblock_styles.c
1 #include "edje_private.h"
2
3 static int
4 _edje_font_is_embedded(Edje_File *edf, char *font)
5 {
6    if (!eina_hash_find(edf->fonts, font)) return 0;
7    return 1;
8 }
9
10 static void
11 _edje_format_param_parse(char *item, char **key, char **val)
12 {
13    char *p, *k, *v;
14
15    p = strchr(item, '=');
16    k = malloc(p - item + 1);
17    strncpy(k, item, p - item);
18    k[p - item] = 0;
19    *key = k;
20    p++;
21    v = strdup(p);
22    *val = v;
23 }
24
25 static char *
26 _edje_format_parse(const char **s)
27 {
28    char *item, *ds;
29    const char *p, *ss;
30    const char *s1 = NULL;
31    const char *s2 = NULL;
32
33    p = *s;
34    if ((!p) || (*p == 0)) return NULL;
35    for (;;)
36      {
37         if (!s1)
38           {
39              if (*p != ' ') s1 = p;
40              if (*p == 0) break;
41           }
42         else if (!s2)
43           {
44              if ((p > *s) && (p[-1] != '\\'))
45                {
46                   if (*p == ' ') s2 = p;
47                }
48              if (*p == 0) s2 = p;
49           }
50         p++;
51         if (s1 && s2)
52           {
53              item = malloc(s2 - s1 + 1);
54              if (item)
55                {
56                   for (ds = item, ss = s1; ss < s2; ss++, ds++)
57                     {
58                        if ((*ss == '\\') && (ss < (s2 - 1))) ss++;
59                        *ds = *ss;
60                     }
61                   *ds = 0;
62                }
63              *s = s2;
64              return item;
65           }
66      }
67    *s = p;
68    return NULL;
69 }
70
71 static int
72 _edje_format_is_param(char *item)
73 {
74    if (strchr(item, '=')) return 1;
75    return 0;
76 }
77
78 static char *
79 _edje_format_reparse(Edje_File *edf, const char *str, Edje_Style_Tag **tag_ret)
80 {
81    Eina_Strbuf *txt, *tmp = NULL;
82    char *s2, *item, *ret;
83    const char *s;
84
85    txt = eina_strbuf_new();
86    s = str;
87    while ((item = _edje_format_parse(&s)))
88      {
89         if (_edje_format_is_param(item))
90           {
91              char *key = NULL, *val = NULL;
92
93              _edje_format_param_parse(item, &key, &val);
94              if (!strcmp(key, "font_source"))
95                {
96                   /* dont allow font sources */
97                }
98              else if (!strcmp(key, "text_class"))
99                {
100                   if (tag_ret)
101                     (*tag_ret)->text_class = eina_stringshare_add(val);
102                }
103              else if (!strcmp(key, "font_size"))
104                {
105                   if (tag_ret)
106                     (*tag_ret)->font_size = atof(val);
107                }
108              else if (!strcmp(key, "font")) /* Fix fonts */
109                {
110                   if (tag_ret)
111                     {
112                        if (_edje_font_is_embedded(edf, val))
113                          {
114                             if (!tmp)
115                               tmp = eina_strbuf_new();
116                             eina_strbuf_append(tmp, "edje/fonts/");
117                             eina_strbuf_append(tmp, val);
118                             (*tag_ret)->font = eina_stringshare_add(eina_strbuf_string_get(tmp));
119                             eina_strbuf_reset(tmp);
120                          }
121                        else
122                          {
123                             (*tag_ret)->font = eina_stringshare_add(val);
124                          }
125                     }
126                }
127              else /* Otherwise add to tag buffer */
128                {
129                   s2 = eina_str_escape(item);
130                   if (s2)
131                     {
132                        if (eina_strbuf_length_get(txt)) eina_strbuf_append(txt, " ");
133                        eina_strbuf_append(txt, s2);
134                        free(s2);
135                     }
136                }
137              free(key);
138              free(val);
139           }
140         else
141           {
142              if (eina_strbuf_length_get(txt)) eina_strbuf_append(txt, " ");
143              eina_strbuf_append(txt, item);
144           }
145         free(item);
146      }
147    if (tmp)
148      eina_strbuf_free(tmp);
149    ret = eina_strbuf_string_steal(txt);
150    eina_strbuf_free(txt);
151    return ret;
152 }
153
154 /* Update all evas_styles which are in an edje
155  *
156  * @param ed    The edje containing styles which need to be updated
157  */
158 void
159 _edje_textblock_style_all_update(Edje *ed)
160 {
161    Eina_List *l, *ll;
162    Edje_Style *stl;
163    Eina_Strbuf *txt = NULL;
164
165    if (!ed->file) return;
166
167    EINA_LIST_FOREACH(ed->file->styles, l, stl)
168      {
169         Edje_Style_Tag *tag;
170         Edje_Text_Class *tc;
171         int found = 0;
172         char *fontset = NULL, *fontsource = NULL;
173
174         /* Make sure the style is already defined */
175         if (!stl->style) break;
176
177         /* Make sure the style contains a text_class */
178         EINA_LIST_FOREACH(stl->tags, ll, tag)
179           {
180              if (tag->text_class)
181                {
182                   found = 1;
183                   break;
184                }
185           }
186
187         /* No text classes , goto next style */
188         if (!found) continue;
189         found = 0;
190         if (!txt)
191           txt = eina_strbuf_new();
192
193         if (_edje_fontset_append)
194           fontset = eina_str_escape(_edje_fontset_append);
195         fontsource = eina_str_escape(ed->file->path);
196
197         /* Build the style from each tag */
198         EINA_LIST_FOREACH(stl->tags, ll, tag)
199           {
200              if (!tag->key) continue;
201
202              /* Add Tag Key */
203              eina_strbuf_append(txt, tag->key);
204              eina_strbuf_append(txt, "='");
205
206              /* Configure fonts from text class if it exists */
207              tc = _edje_text_class_find(ed, tag->text_class);
208
209              /* Add and Ha`ndle tag parsed data */
210              eina_strbuf_append(txt, tag->value);
211
212              if (!strcmp(tag->key, "DEFAULT"))
213                {
214                   if (fontset)
215                     {
216                        eina_strbuf_append(txt, " ");
217                        eina_strbuf_append(txt, "font_fallbacks=");
218                        eina_strbuf_append(txt, fontset);
219                     }
220                   eina_strbuf_append(txt, " ");
221                   eina_strbuf_append(txt, "font_source=");
222                   eina_strbuf_append(txt, fontsource);
223                }
224              if (tag->font_size != 0)
225                {
226                   char font_size[32];
227
228                   if (tc && tc->size)
229                     snprintf(font_size, sizeof(font_size), "%f", (double) _edje_text_size_calc(tag->font_size, tc));
230                   else
231                     snprintf(font_size, sizeof(font_size), "%f", tag->font_size);
232
233                   eina_strbuf_append(txt, " ");
234                   eina_strbuf_append(txt, "font_size=");
235                   eina_strbuf_append(txt, font_size);
236                }
237              /* Add font name last to save evas from multiple loads */
238              if (tag->font)
239                {
240                   const char *f;
241
242                   eina_strbuf_append(txt, " ");
243                   eina_strbuf_append(txt, "font=");
244
245                   f = (tc && tc->font) ? tc->font : tag->font;
246                   eina_strbuf_append_escaped(txt, f);
247                }
248
249              eina_strbuf_append(txt, "'");
250           }
251         if (fontset) free(fontset);
252         if (fontsource) free(fontsource);
253
254         /* Configure the style */
255         evas_textblock_style_set(stl->style, eina_strbuf_string_get(txt));
256         eina_strbuf_reset(txt);
257      }
258    if (txt)
259      eina_strbuf_free(txt);
260 }
261
262 void
263 _edje_textblock_styles_add(Edje *ed)
264 {
265    Eina_List *l, *ll;
266    Edje_Style *stl;
267
268    if (!ed->file) return;
269
270    EINA_LIST_FOREACH(ed->file->styles, l, stl)
271      {
272         Edje_Style_Tag *tag;
273
274         /* Make sure the style contains the text_class */
275         EINA_LIST_FOREACH(stl->tags, ll, tag)
276           {
277             if (!tag->text_class) continue;
278             _edje_text_class_member_add(ed, tag->text_class);
279           }
280      }
281 }
282
283 void
284 _edje_textblock_styles_del(Edje *ed)
285 {
286    Eina_List *l, *ll;
287    Edje_Style *stl;
288
289    if (!ed->file) return;
290
291    EINA_LIST_FOREACH(ed->file->styles, l, stl)
292      {
293         Edje_Style_Tag *tag;
294
295         /* Make sure the style contains the text_class */
296         EINA_LIST_FOREACH(stl->tags, ll, tag)
297           {
298              if (!tag->text_class) continue;
299              _edje_text_class_member_del(ed, tag->text_class);
300           }
301      }
302 }
303
304 /* When we get to here the edje file had been read into memory
305  * the name of the style is established as well as the name and
306  * data for the tags.  This function will create the Evas_Style
307  * object for each style. The style is composed of a base style
308  * followed by a list of tags.
309  */
310 void
311 _edje_textblock_style_parse_and_fix(Edje_File *edf)
312 {
313    Eina_Strbuf *txt = NULL;
314    Eina_List *l, *ll;
315    Edje_Style *stl;
316
317    EINA_LIST_FOREACH(edf->styles, l, stl)
318      {
319         Edje_Style_Tag *tag;
320         char *fontset = NULL, *fontsource = NULL, *ts;
321
322         if (stl->style) break;
323
324         if (!txt)
325           txt = eina_strbuf_new();
326
327         stl->style = evas_textblock_style_new();
328         evas_textblock_style_set(stl->style, NULL);
329
330         if (_edje_fontset_append)
331           fontset = eina_str_escape(_edje_fontset_append);
332         fontsource = eina_str_escape(edf->path);
333
334         /* Build the style from each tag */
335         EINA_LIST_FOREACH(stl->tags, ll, tag)
336           {
337              if (!tag->key) continue;
338
339              /* Add Tag Key */
340              eina_strbuf_append(txt, tag->key);
341              eina_strbuf_append(txt, "='");
342
343              ts = _edje_format_reparse(edf, tag->value, &(tag));
344
345              /* Add and Handle tag parsed data */
346              if (ts)
347                {
348                   if (eet_dictionary_string_check(eet_dictionary_get(edf->ef), tag->value) == 0)
349                     eina_stringshare_del(tag->value);
350                   tag->value = eina_stringshare_add(ts);
351                   eina_strbuf_append(txt, tag->value);
352                   free(ts);
353                }
354
355              if (!strcmp(tag->key, "DEFAULT"))
356                {
357                   if (fontset)
358                     {
359                        eina_strbuf_append(txt, " ");
360                        eina_strbuf_append(txt, "font_fallbacks=");
361                        eina_strbuf_append(txt, fontset);
362                     }
363                   eina_strbuf_append(txt, " ");
364                   eina_strbuf_append(txt, "font_source=");
365                   eina_strbuf_append(txt, fontsource);
366                }
367              if (tag->font_size > 0)
368                {
369                   char font_size[32];
370
371                   snprintf(font_size, sizeof(font_size), "%f", tag->font_size);
372                   eina_strbuf_append(txt, " ");
373                   eina_strbuf_append(txt, "font_size=");
374                   eina_strbuf_append(txt, font_size);
375                }
376              /* Add font name last to save evas from multiple loads */
377              if (tag->font)
378                {
379                   eina_strbuf_append(txt, " ");
380                   eina_strbuf_append(txt, "font=");
381                   eina_strbuf_append_escaped(txt, tag->font);
382                }
383              eina_strbuf_append(txt, "'");
384           }
385         if (fontset) free(fontset);
386         if (fontsource) free(fontsource);
387
388         /* Configure the style */
389         evas_textblock_style_set(stl->style, eina_strbuf_string_get(txt));
390         eina_strbuf_reset(txt);
391      }
392    if (txt)
393      eina_strbuf_free(txt);
394 }
395
396 void
397 _edje_textblock_style_cleanup(Edje_File *edf)
398 {
399    while (edf->styles)
400      {
401         Edje_Style *stl;
402
403         stl = edf->styles->data;
404         edf->styles = eina_list_remove_list(edf->styles, edf->styles);
405         while (stl->tags)
406           {
407              Edje_Style_Tag *tag;
408
409              tag = stl->tags->data;
410              stl->tags = eina_list_remove_list(stl->tags, stl->tags);
411              if (edf->free_strings)
412                {
413                   if (tag->key) eina_stringshare_del(tag->key);
414 /*                FIXME: Find a proper way to handle it. */
415                   if (tag->value) eina_stringshare_del(tag->value);
416                   if (tag->text_class) eina_stringshare_del(tag->text_class);
417                   if (tag->font) eina_stringshare_del(tag->font);
418                }
419              free(tag);
420           }
421         if (edf->free_strings && stl->name) eina_stringshare_del(stl->name);
422         if (stl->style) evas_textblock_style_free(stl->style);
423         free(stl);
424      }
425 }