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