summaryrefslogtreecommitdiff
path: root/legacy/evas
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2011-08-01 08:20:52 +0000
committerTom Hacohen <tom@stosb.com>2011-08-01 08:20:52 +0000
commit9ba3e192a5af8e49586c9622e52441e04909c353 (patch)
tree56892f67ce9174789ab952b91bc335ba921b1204 /legacy/evas
parent7239b6894f650a78bd14294126abfbb0563445fa (diff)
Evas font+textblock: Stopped using FcNameParse, parse ourselves.
FcNameParse is pretty bad, not only that it's pretty bad, it doesn't work well in some cases. Also this makes our lives a lot easier since we want to allow overriding style/weight/width and etc from markup. We now parse the "font" markup ourselves, populating a font description structure that we created, and then override values in it as needed. SVN revision: 61936
Diffstat (limited to 'legacy/evas')
-rw-r--r--legacy/evas/src/lib/canvas/evas_font_dir.c313
-rw-r--r--legacy/evas/src/lib/canvas/evas_object_text.c37
-rw-r--r--legacy/evas/src/lib/canvas/evas_object_textblock.c192
-rw-r--r--legacy/evas/src/lib/include/evas_private.h70
4 files changed, 390 insertions, 222 deletions
diff --git a/legacy/evas/src/lib/canvas/evas_font_dir.c b/legacy/evas/src/lib/canvas/evas_font_dir.c
index 0a248ccd74..e07dc9da6e 100644
--- a/legacy/evas/src/lib/canvas/evas_font_dir.c
+++ b/legacy/evas/src/lib/canvas/evas_font_dir.c
@@ -26,9 +26,9 @@ typedef struct _Fndat Fndat;
26 26
27struct _Fndat 27struct _Fndat
28{ 28{
29 const char *name; 29 Evas_Font_Description *fdesc;
30 const char *source; 30 const char *source;
31 int size; 31 Evas_Font_Size size;
32 Evas_Font_Set *font; 32 Evas_Font_Set *font;
33 int ref; 33 int ref;
34 Font_Rend_Flags wanted_rend; 34 Font_Rend_Flags wanted_rend;
@@ -136,7 +136,7 @@ evas_fonts_zero_free(Evas *evas)
136 136
137 EINA_LIST_FREE(fonts_zero, fd) 137 EINA_LIST_FREE(fonts_zero, fd)
138 { 138 {
139 if (fd->name) eina_stringshare_del(fd->name); 139 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
140 if (fd->source) eina_stringshare_del(fd->source); 140 if (fd->source) eina_stringshare_del(fd->source);
141 evas->engine.func->font_free(evas->engine.data.output, fd->font); 141 evas->engine.func->font_free(evas->engine.data.output, fd->font);
142#ifdef HAVE_FONTCONFIG 142#ifdef HAVE_FONTCONFIG
@@ -160,7 +160,7 @@ evas_fonts_zero_presure(Evas *evas)
160 if (fd->ref != 0) break; 160 if (fd->ref != 0) break;
161 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero); 161 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
162 162
163 if (fd->name) eina_stringshare_del(fd->name); 163 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
164 if (fd->source) eina_stringshare_del(fd->source); 164 if (fd->source) eina_stringshare_del(fd->source);
165 evas->engine.func->font_free(evas->engine.data.output, fd->font); 165 evas->engine.func->font_free(evas->engine.data.output, fd->font);
166#ifdef HAVE_FONTCONFIG 166#ifdef HAVE_FONTCONFIG
@@ -200,7 +200,7 @@ evas_font_free(Evas *evas, void *font)
200 if (fd->ref != 0) break; 200 if (fd->ref != 0) break;
201 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero); 201 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
202 202
203 if (fd->name) eina_stringshare_del(fd->name); 203 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
204 if (fd->source) eina_stringshare_del(fd->source); 204 if (fd->source) eina_stringshare_del(fd->source);
205 evas->engine.func->font_free(evas->engine.data.output, fd->font); 205 evas->engine.func->font_free(evas->engine.data.output, fd->font);
206#ifdef HAVE_FONTCONFIG 206#ifdef HAVE_FONTCONFIG
@@ -254,54 +254,242 @@ evas_load_fontconfig(Evas *evas, FcFontSet *set, int size,
254} 254}
255#endif 255#endif
256 256
257static Eina_Bool 257struct _FcPattern {
258_font_style_name_match(const char *font_name, const char *style_name) 258 int num;
259 int size;
260 intptr_t elts_offset;
261 int ref;
262};
263
264#ifdef HAVE_FONTCONFIG
265/* In sync with Evas_Font_Style, Evas_Font_Weight and Evas_Font_Width */
266static int _fc_slant_map[] =
267{
268 FC_SLANT_ROMAN,
269 FC_SLANT_OBLIQUE,
270 FC_SLANT_ITALIC
271};
272
273static int _fc_weight_map[] =
274{
275 FC_WEIGHT_NORMAL,
276 FC_WEIGHT_THIN,
277 FC_WEIGHT_ULTRALIGHT,
278 FC_WEIGHT_LIGHT,
279 FC_WEIGHT_BOOK,
280 FC_WEIGHT_MEDIUM,
281 FC_WEIGHT_SEMIBOLD,
282 FC_WEIGHT_BOLD,
283 FC_WEIGHT_ULTRABOLD,
284 FC_WEIGHT_BLACK,
285 FC_WEIGHT_EXTRABLACK
286};
287
288# ifdef FC_WIDTH
289static int _fc_width_map[] =
290{
291 FC_WIDTH_NORMAL,
292 FC_WIDTH_ULTRACONDENSED,
293 FC_WIDTH_EXTRACONDENSED,
294 FC_WIDTH_CONDENSED,
295 FC_WIDTH_SEMICONDENSED,
296 FC_WIDTH_SEMIEXPANDED,
297 FC_WIDTH_EXPANDED,
298 FC_WIDTH_EXTRAEXPANDED,
299 FC_WIDTH_ULTRAEXPANDED
300};
301# endif
302
303#endif
304
305struct _Style_Map
306{
307 const char *name;
308 int type;
309};
310typedef struct _Style_Map Style_Map;
311
312static Style_Map _style_width_map[] =
313{
314 {"normal", EVAS_FONT_WIDTH_NORMAL},
315 {"ultracondensed", EVAS_FONT_WIDTH_ULTRACONDENSED},
316 {"extracondensed", EVAS_FONT_WIDTH_EXTRACONDENSED},
317 {"condensed", EVAS_FONT_WIDTH_CONDENSED},
318 {"semicondensed", EVAS_FONT_WIDTH_SEMICONDENSED},
319 {"semiexpanded", EVAS_FONT_WIDTH_SEMIEXPANDED},
320 {"expanded", EVAS_FONT_WIDTH_EXPANDED},
321 {"extraexpanded", EVAS_FONT_WIDTH_EXTRAEXPANDED},
322 {"ultraexpanded", EVAS_FONT_WIDTH_ULTRAEXPANDED},
323};
324
325static Style_Map _style_weight_map[] =
259{ 326{
260 char *style_key = NULL; 327 {"normal", EVAS_FONT_WEIGHT_NORMAL},
328 {"thin", EVAS_FONT_WEIGHT_THIN},
329 {"ultralight", EVAS_FONT_WEIGHT_ULTRALIGHT},
330 {"light", EVAS_FONT_WEIGHT_LIGHT},
331 {"book", EVAS_FONT_WEIGHT_BOOK},
332 {"medium", EVAS_FONT_WEIGHT_MEDIUM},
333 {"semibold", EVAS_FONT_WEIGHT_SEMIBOLD},
334 {"bold", EVAS_FONT_WEIGHT_BOLD},
335 {"ultrabold", EVAS_FONT_WEIGHT_ULTRABOLD},
336 {"black", EVAS_FONT_WEIGHT_BLACK},
337 {"extrablack", EVAS_FONT_WEIGHT_EXTRABLACK}
338};
261 339
262 style_key = strchr(font_name, ':'); 340static Style_Map _style_slant_map[] =
263 if (!style_key) return EINA_FALSE; 341{
264 if (strlen(style_key) > 2) style_key++; 342 {"normal", EVAS_FONT_SLANT_NORMAL},
265 if (strstr(style_key, "style=")) 343 {"oblique", EVAS_FONT_SLANT_OBLIQUE},
344 {"italic", EVAS_FONT_SLANT_ITALIC}
345};
346
347#define _STYLE_MAP_LEN(x) (sizeof(x) / sizeof(*(x)))
348/**
349 * @internal
350 * Find a certain attribute from the map in the style.
351 * @return the index of the found one.
352 */
353static int
354_evas_font_style_find_internal(const char *style, const char *style_end,
355 Style_Map _map[], size_t map_len)
356{
357 size_t i;
358 while (style < style_end)
266 { 359 {
267 if (!strcmp(style_name, "Italic")) 360 for (i = 0 ; i < map_len ; i++)
268 { 361 {
269 if (strstr(style_key, "Italic") 362 size_t len;
270 || strstr(style_key, "italic") 363 const char *cur = _map[i].name;
271 || strstr(style_key, "Cursiva") 364 len = strlen(cur);
272 || strstr(style_key, "cursiva") 365 if (!strncasecmp(style, cur, len) &&
273 || strstr(style_key, "Oblique") 366 (!cur[len] || (cur[len] == ' ')))
274 || strstr(style_key, "oblique")) 367 {
275 return EINA_TRUE; 368 return _map[i].type;
276 else 369 }
277 return EINA_FALSE;
278 } 370 }
279 else if (!strcmp(style_name, "Bold")) 371 style = strchr(style, ' ');
372 if (!style)
373 break;
374
375 while (*style && (*style == ' '))
376 style++;
377 }
378 return 0;
379}
380
381int
382evas_font_style_find(const char *start, const char *end,
383 Evas_Font_Style style)
384{
385#define _RET_STYLE(x) \
386 return _evas_font_style_find_internal(start, end, \
387 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
388 switch (style)
389 {
390 case EVAS_FONT_STYLE_SLANT:
391 _RET_STYLE(slant);
392 case EVAS_FONT_STYLE_WEIGHT:
393 _RET_STYLE(weight);
394 case EVAS_FONT_STYLE_WIDTH:
395 _RET_STYLE(width);
396 default:
397 return 0;
398 }
399#undef _RET_STYLE
400}
401
402void
403evas_font_desc_unref(Evas_Font_Description *fdesc)
404{
405 if (--(fdesc->ref) == 0)
406 {
407 eina_stringshare_del(fdesc->name);
408 free(fdesc);
409 }
410}
411
412Evas_Font_Description *
413evas_font_desc_ref(Evas_Font_Description *fdesc)
414{
415 fdesc->ref++;
416 return fdesc;
417}
418
419Evas_Font_Description *
420evas_font_desc_new(void)
421{
422 Evas_Font_Description *fdesc;
423 fdesc = calloc(1, sizeof(*fdesc));
424 fdesc->ref = 1;
425 fdesc->new = EINA_TRUE;
426
427 return fdesc;
428}
429
430Evas_Font_Description *
431evas_font_desc_dup(const Evas_Font_Description *fdesc)
432{
433 Evas_Font_Description *new;
434 new = evas_font_desc_new();
435 memcpy(new, fdesc, sizeof(*new));
436 new->ref = 1;
437 new->new = EINA_TRUE;
438 new->name = eina_stringshare_ref(new->name);
439
440 return new;
441}
442
443int
444evas_font_desc_cmp(const Evas_Font_Description *a,
445 const Evas_Font_Description *b)
446{
447 /* FIXME: Do actual comparison, i.e less than and bigger than. */
448 return !((a->name == b->name) && (a->weight == b->weight) &&
449 (a->slant == b->slant) && (a->width == b->width) &&
450 (a->lang == b->lang));
451}
452
453void
454evas_font_name_parse(Evas_Font_Description *fdesc, const char *name)
455{
456 const char *end;
457
458 end = strchr(name, ':');
459 if (!end)
460 fdesc->name = eina_stringshare_add(name);
461 else
462 fdesc->name = eina_stringshare_add_length(name, end - name);
463
464 while (end)
465 {
466 const char *tend;
467 name = end;
468 end = strchr(end + 1, ':');
469 if (!end)
470 tend = name + strlen(name);
471 else
472 tend = end;
473
474 if (!strncmp(name, ":style=", 7))
280 { 475 {
281 if (strstr(style_key, "Bold") 476#define _SET_STYLE(x) \
282 || strstr(style_key, "bold") 477 fdesc->x = _evas_font_style_find_internal(name + 7, tend, \
283 || strstr(style_key, "Negreta") 478 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
284 || strstr(style_key, "negreta")) 479 _SET_STYLE(slant);
285 return EINA_TRUE; 480 _SET_STYLE(weight);
286 else 481 _SET_STYLE(width);
287 return EINA_FALSE; 482#undef _SET_STYLE
483 }
484 else if (!strncmp(name, ":lang=", 6))
485 {
486 /* FIXME: handle lang. */
288 } 487 }
289 else
290 return EINA_FALSE;
291 } 488 }
292 else
293 return EINA_FALSE;
294} 489}
295 490
296struct _FcPattern {
297 int num;
298 int size;
299 intptr_t elts_offset;
300 int ref;
301};
302
303void * 491void *
304evas_font_load(Evas *evas, const char *name, const char *source, int size) 492evas_font_load(Evas *evas, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size)
305{ 493{
306#ifdef HAVE_FONTCONFIG 494#ifdef HAVE_FONTCONFIG
307 FcPattern *p_nm = NULL; 495 FcPattern *p_nm = NULL;
@@ -314,24 +502,25 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
314 char *nm; 502 char *nm;
315 Font_Rend_Flags wanted_rend = 0; 503 Font_Rend_Flags wanted_rend = 0;
316 504
317 if (!name) return NULL; 505 if (!fdesc) return NULL;
318 if (name[0] == 0) return NULL; 506 fdesc->new = EINA_FALSE;
319 507
320 if (_font_style_name_match(name, "Italic")) 508 if (fdesc->slant != EVAS_FONT_SLANT_NORMAL)
321 wanted_rend |= FONT_REND_ITALIC; 509 wanted_rend |= FONT_REND_ITALIC;
322 if (_font_style_name_match(name, "Bold")) 510 if (fdesc->weight == EVAS_FONT_WEIGHT_BOLD)
323 wanted_rend |= FONT_REND_BOLD; 511 wanted_rend |= FONT_REND_BOLD;
324 512
325 evas_font_init(); 513 evas_font_init();
326 514
327 EINA_LIST_FOREACH(fonts_cache, l, fd) 515 EINA_LIST_FOREACH(fonts_cache, l, fd)
328 { 516 {
329 if (!strcmp(name, fd->name)) 517 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
330 { 518 {
331 if (((!source) && (!fd->source)) || 519 if (((!source) && (!fd->source)) ||
332 ((source) && (fd->source) && (!strcmp(source, fd->source)))) 520 ((source) && (fd->source) && (!strcmp(source, fd->source))))
333 { 521 {
334 if ((size == fd->size) && (wanted_rend == fd->wanted_rend)) 522 if ((size == fd->size) &&
523 (wanted_rend == fd->wanted_rend))
335 { 524 {
336 fonts_cache = eina_list_promote_list(fonts_cache, l); 525 fonts_cache = eina_list_promote_list(fonts_cache, l);
337 fd->ref++; 526 fd->ref++;
@@ -351,12 +540,13 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
351 540
352 EINA_LIST_FOREACH(fonts_zero, l, fd) 541 EINA_LIST_FOREACH(fonts_zero, l, fd)
353 { 542 {
354 if (!strcmp(name, fd->name)) 543 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
355 { 544 {
356 if (((!source) && (!fd->source)) || 545 if (((!source) && (!fd->source)) ||
357 ((source) && (fd->source) && (!strcmp(source, fd->source)))) 546 ((source) && (fd->source) && (!strcmp(source, fd->source))))
358 { 547 {
359 if ((size == fd->size) && (wanted_rend == fd->wanted_rend)) 548 if ((size == fd->size) &&
549 (wanted_rend == fd->wanted_rend))
360 { 550 {
361 fonts_zero = eina_list_remove_list(fonts_zero, l); 551 fonts_zero = eina_list_remove_list(fonts_zero, l);
362 fonts_cache = eina_list_prepend(fonts_cache, fd); 552 fonts_cache = eina_list_prepend(fonts_cache, fd);
@@ -375,7 +565,7 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
375 } 565 }
376 } 566 }
377 567
378 fonts = evas_font_set_get(name); 568 fonts = evas_font_set_get(fdesc->name);
379 EINA_LIST_FOREACH(fonts, l, nm) /* Load each font in append */ 569 EINA_LIST_FOREACH(fonts, l, nm) /* Load each font in append */
380 { 570 {
381 if (l == fonts || !font) /* First iteration OR no font */ 571 if (l == fonts || !font) /* First iteration OR no font */
@@ -510,7 +700,16 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
510 { 700 {
511 FcResult res; 701 FcResult res;
512 702
513 p_nm = FcNameParse((FcChar8 *)name); 703 p_nm = FcPatternBuild (NULL,
704 FC_WEIGHT, FcTypeInteger, _fc_weight_map[fdesc->weight],
705 FC_SLANT, FcTypeInteger, _fc_slant_map[fdesc->slant],
706#ifdef FC_WIDTH
707 FC_WIDTH, FcTypeInteger, _fc_width_map[fdesc->width],
708#endif
709 NULL);
710 /* FIXME: Handle font fallbacks!!! */
711 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) fdesc->name);
712
514 FcConfigSubstitute(NULL, p_nm, FcMatchPattern); 713 FcConfigSubstitute(NULL, p_nm, FcMatchPattern);
515 FcDefaultSubstitute(p_nm); 714 FcDefaultSubstitute(p_nm);
516 715
@@ -518,17 +717,12 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
518 set = FcFontSort(NULL, p_nm, FcTrue, NULL, &res); 717 set = FcFontSort(NULL, p_nm, FcTrue, NULL, &res);
519 if (!set) 718 if (!set)
520 { 719 {
521 ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", name); 720 ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", fdesc->name);
522 FcPatternDestroy(p_nm); 721 FcPatternDestroy(p_nm);
523 p_nm = NULL; 722 p_nm = NULL;
524 } 723 }
525 else 724 else
526 { 725 {
527 // FIXME: this i think is a bugfix for a rare bug... but i'm
528 // not sure 100%. it seems that way from fc. if trim is set
529 // to FcTrue...
530 // ok - not a bugfix... but there is something going on somewhere that's weird?
531// FcPatternReference(p_nm); /* we have to reference count the pat */
532 font = evas_load_fontconfig(evas, set, size, wanted_rend); 726 font = evas_load_fontconfig(evas, set, size, wanted_rend);
533 } 727 }
534 } 728 }
@@ -538,9 +732,8 @@ evas_font_load(Evas *evas, const char *name, const char *source, int size)
538 fd = calloc(1, sizeof(Fndat)); 732 fd = calloc(1, sizeof(Fndat));
539 if (fd) 733 if (fd)
540 { 734 {
541 fd->name = eina_stringshare_add(name); 735 fd->fdesc = evas_font_desc_ref(fdesc);
542 if (source) fd->source = eina_stringshare_add(source); 736 if (source) fd->source = eina_stringshare_add(source);
543 fd->size = size;
544 fd->font = font; 737 fd->font = font;
545 fd->wanted_rend = wanted_rend; 738 fd->wanted_rend = wanted_rend;
546 fd->ref = 1; 739 fd->ref = 1;
diff --git a/legacy/evas/src/lib/canvas/evas_object_text.c b/legacy/evas/src/lib/canvas/evas_object_text.c
index 48b0193047..cd0511d915 100644
--- a/legacy/evas/src/lib/canvas/evas_object_text.c
+++ b/legacy/evas/src/lib/canvas/evas_object_text.c
@@ -19,6 +19,7 @@ struct _Evas_Object_Text
19 struct { 19 struct {
20 const char *utf8_text; /* The text exposed to the API */ 20 const char *utf8_text; /* The text exposed to the API */
21 const char *font; 21 const char *font;
22 Evas_Font_Description *fdesc;
22 const char *source; 23 const char *source;
23 Evas_Font_Size size; 24 Evas_Font_Size size;
24 struct { 25 struct {
@@ -345,7 +346,7 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
345{ 346{
346 Evas_Object_Text *o; 347 Evas_Object_Text *o;
347 int is, was = 0, pass = 0; 348 int is, was = 0, pass = 0;
348 int same_font = 0; 349 Evas_Font_Description *fdesc;
349 350
350 if ((!font) || (size <= 0)) return; 351 if ((!font) || (size <= 0)) return;
351 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); 352 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
@@ -356,11 +357,22 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
356 return; 357 return;
357 MAGIC_CHECK_END(); 358 MAGIC_CHECK_END();
358 359
359 if ((o->cur.font) && (font) && (!strcmp(o->cur.font, font))) 360 fdesc = evas_font_desc_new();
361 evas_font_name_parse(fdesc, font);
362 if (o->cur.fdesc && !evas_font_desc_cmp(fdesc, o->cur.fdesc) &&
363 (size == o->cur.size))
360 { 364 {
361 same_font = 1; 365 evas_font_desc_unref(fdesc);
362 if (size == o->cur.size) return; 366 return;
363 } 367 }
368
369 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
370 o->cur.fdesc = fdesc;
371
372 o->cur.size = size;
373 eina_stringshare_replace(&o->cur.font, font);
374 o->prev.font = NULL;
375
364 if (obj->layer->evas->events_frozen <= 0) 376 if (obj->layer->evas->events_frozen <= 0)
365 { 377 {
366 pass = evas_event_passes_through(obj); 378 pass = evas_event_passes_through(obj);
@@ -381,19 +393,9 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
381 evas_font_free(obj->layer->evas, o->font); 393 evas_font_free(obj->layer->evas, o->font);
382 o->font = NULL; 394 o->font = NULL;
383 } 395 }
384 if (!same_font) 396
385 { 397 o->font = evas_font_load(obj->layer->evas, o->cur.fdesc, o->cur.source,
386 /* 398 (int)(((double) o->cur.size) * obj->cur.scale));
387 if (o->cur.font) eina_stringshare_del(o->cur.font);
388 if (font) o->cur.font = eina_stringshare_add(font);
389 else o->cur.font = NULL;
390 */
391 eina_stringshare_replace(&o->cur.font, font);
392 o->prev.font = NULL;
393 }
394 o->cur.size = size;
395 o->font = evas_font_load(obj->layer->evas, o->cur.font, o->cur.source,
396 (int)(((double)o->cur.size) * obj->cur.scale));
397 if (o->font) 399 if (o->font)
398 { 400 {
399 o->ascent = ENFN->font_ascent_get(ENDT, o->font); 401 o->ascent = ENFN->font_ascent_get(ENDT, o->font);
@@ -1441,6 +1443,7 @@ evas_object_text_free(Evas_Object *obj)
1441 if (o->items) _evas_object_text_items_clear(o); 1443 if (o->items) _evas_object_text_items_clear(o);
1442 if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text); 1444 if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
1443 if (o->cur.font) eina_stringshare_del(o->cur.font); 1445 if (o->cur.font) eina_stringshare_del(o->cur.font);
1446 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
1444 if (o->cur.source) eina_stringshare_del(o->cur.source); 1447 if (o->cur.source) eina_stringshare_del(o->cur.source);
1445 if (o->font) evas_font_free(obj->layer->evas, o->font); 1448 if (o->font) evas_font_free(obj->layer->evas, o->font);
1446#ifdef BIDI_SUPPORT 1449#ifdef BIDI_SUPPORT
diff --git a/legacy/evas/src/lib/canvas/evas_object_textblock.c b/legacy/evas/src/lib/canvas/evas_object_textblock.c
index f2c97f9b63..a6863211f8 100644
--- a/legacy/evas/src/lib/canvas/evas_object_textblock.c
+++ b/legacy/evas/src/lib/canvas/evas_object_textblock.c
@@ -348,11 +348,11 @@ struct _Evas_Object_Textblock_Format
348 double halign; 348 double halign;
349 double valign; 349 double valign;
350 struct { 350 struct {
351 const char *name; 351 Evas_Font_Description *fdesc;
352 const char *source; 352 const char *source;
353 const char *fallbacks; 353 const char *fallbacks;
354 Evas_Font_Set *font; 354 Evas_Font_Set *font;
355 int size; 355 Evas_Font_Size size;
356 } font; 356 } font;
357 struct { 357 struct {
358 struct { 358 struct {
@@ -620,7 +620,7 @@ _format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
620{ 620{
621 fmt->ref--; 621 fmt->ref--;
622 if (fmt->ref > 0) return; 622 if (fmt->ref > 0) return;
623 if (fmt->font.name) eina_stringshare_del(fmt->font.name); 623 if (fmt->font.fdesc) evas_font_desc_unref(fmt->font.fdesc);
624 if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks); 624 if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
625 if (fmt->font.source) eina_stringshare_del(fmt->font.source); 625 if (fmt->font.source) eina_stringshare_del(fmt->font.source);
626 evas_font_free(obj->layer->evas, fmt->font.font); 626 evas_font_free(obj->layer->evas, fmt->font.font);
@@ -1131,95 +1131,6 @@ _format_clean_param(char *dst, const char *src)
1131 *ds = 0; 1131 *ds = 0;
1132} 1132}
1133 1133
1134static const char *_style_weight_map[] = { "ultralight", "light", "bold",
1135 "ultrabold", "black", "normal" };
1136#define _STYLE_WEIGHT_MAP_LEN (sizeof(_style_weight_map) / sizeof(_style_weight_map[0]))
1137
1138static const char *_style_style_map[] = { "normal", "oblique", "italic" };
1139#define _STYLE_STYLE_MAP_LEN (sizeof(_style_style_map) / sizeof(_style_style_map[0]))
1140/**
1141 * @internal
1142 * Find a certain attribute from the map in the style.
1143 * @return true if found, false otherwise.
1144 */
1145static Eina_Bool
1146_format_font_style_find(const char *style, const char *style_end,
1147 const char **start, const char **end, const char *_map[], size_t map_len)
1148{
1149 size_t i;
1150 while (style < style_end)
1151 {
1152 for (i = 0 ; i < map_len ; i++)
1153 {
1154 size_t len;
1155 const char *cur = _map[i];
1156 len = strlen(cur);
1157 if (!strncasecmp(style, cur, len) &&
1158 (!cur[len] || (cur[len] == ' ')))
1159 {
1160 *start = style;
1161 *end = *start + len;
1162 return EINA_TRUE;
1163 }
1164 }
1165 style = strchr(style, ' ');
1166 if (!style)
1167 break;
1168
1169 while (*style && _is_white(*style))
1170 style++;
1171 }
1172 return EINA_FALSE;
1173}
1174
1175static void
1176_format_command_parse_font_weight_style(Evas_Object_Textblock_Format *fmt,
1177 const char *param, const char *_map[], size_t map_len)
1178{
1179 size_t flen = eina_stringshare_strlen(fmt->font.name);
1180 const char *style = strstr(fmt->font.name, ":style=");
1181 if (style)
1182 {
1183 Eina_Strbuf *buf;
1184 const char *found_start, *found_end;
1185 const char *style_end = strchr(style + 7, ':');
1186 /* Point to the end, either it be the next attribute,
1187 * or the terminating 0 */
1188 if (!style_end)
1189 style_end = fmt->font.name + flen;
1190
1191 buf = eina_strbuf_new();
1192 eina_strbuf_append_length(buf, fmt->font.name, flen);
1193
1194 if (_format_font_style_find(style + 7, style_end,
1195 &found_start, &found_end, _map, map_len))
1196 {
1197 eina_strbuf_remove(buf, found_start - fmt->font.name,
1198 found_end - fmt->font.name);
1199 }
1200 else
1201 {
1202 found_start = style + 7; /* + 7 for :style= */
1203 eina_strbuf_insert_char(buf, ' ', found_start - fmt->font.name);
1204 }
1205 eina_strbuf_insert(buf, param, found_start - fmt->font.name);
1206 if (fmt->font.name) eina_stringshare_del(fmt->font.name);
1207 fmt->font.name = eina_stringshare_add(eina_strbuf_string_get(buf));
1208 eina_strbuf_free(buf);
1209 }
1210 else
1211 {
1212 /* Make a buffer big enough to hold whatever we do.
1213 * 7 == len(:style=). */
1214 char *tmpres = alloca(flen + strlen(param) + 7 + 1);
1215 /* Handle font.name == NULL */
1216 memcpy(tmpres, fmt->font.name, flen);
1217 sprintf(tmpres + flen, ":style=%s", param);
1218 if (fmt->font.name) eina_stringshare_del(fmt->font.name);
1219 fmt->font.name = eina_stringshare_add(tmpres);
1220 }
1221}
1222
1223/** 1134/**
1224 * @internal 1135 * @internal
1225 * Parses the cmd and parameter and adds the parsed format to fmt. 1136 * Parses the cmd and parameter and adds the parsed format to fmt.
@@ -1232,7 +1143,6 @@ _format_command_parse_font_weight_style(Evas_Object_Textblock_Format *fmt,
1232static void 1143static void
1233_format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *cmd, const char *param) 1144_format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *cmd, const char *param)
1234{ 1145{
1235 int new_font = 0;
1236 int len; 1146 int len;
1237 char *tmp_param; 1147 char *tmp_param;
1238 1148
@@ -1240,15 +1150,26 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
1240 tmp_param = alloca(len + 1); 1150 tmp_param = alloca(len + 1);
1241 1151
1242 _format_clean_param(tmp_param, param); 1152 _format_clean_param(tmp_param, param);
1243 if (cmd == fontstr) 1153
1154 /* If we are changing the font, create the fdesc. */
1155 if ((cmd == font_weightstr) || (cmd == font_stylestr) || (cmd == fontstr))
1244 { 1156 {
1245 if ((!fmt->font.name) || 1157 if (!fmt->font.fdesc)
1246 ((fmt->font.name) && (strcmp(fmt->font.name, tmp_param))))
1247 { 1158 {
1248 if (fmt->font.name) eina_stringshare_del(fmt->font.name); 1159 fmt->font.fdesc = evas_font_desc_new();
1249 fmt->font.name = eina_stringshare_add(tmp_param);
1250 new_font = 1;
1251 } 1160 }
1161 else if (!fmt->font.fdesc->new)
1162 {
1163 Evas_Font_Description *old = fmt->font.fdesc;
1164 fmt->font.fdesc = evas_font_desc_dup(fmt->font.fdesc);
1165 if (old) evas_font_desc_unref(old);
1166 }
1167 }
1168
1169
1170 if (cmd == fontstr)
1171 {
1172 evas_font_name_parse(fmt->font.fdesc, tmp_param);
1252 } 1173 }
1253 else if (cmd == font_fallbacksstr) 1174 else if (cmd == font_fallbacksstr)
1254 { 1175 {
@@ -1260,7 +1181,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
1260 */ 1181 */
1261 if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks); 1182 if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
1262 fmt->font.fallbacks = eina_stringshare_add(tmp_param); 1183 fmt->font.fallbacks = eina_stringshare_add(tmp_param);
1263 new_font = 1;
1264 } 1184 }
1265 } 1185 }
1266 else if (cmd == font_sizestr) 1186 else if (cmd == font_sizestr)
@@ -1271,7 +1191,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
1271 if (v != fmt->font.size) 1191 if (v != fmt->font.size)
1272 { 1192 {
1273 fmt->font.size = v; 1193 fmt->font.size = v;
1274 new_font = 1;
1275 } 1194 }
1276 } 1195 }
1277 else if (cmd == font_sourcestr) 1196 else if (cmd == font_sourcestr)
@@ -1281,20 +1200,17 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
1281 { 1200 {
1282 if (fmt->font.source) eina_stringshare_del(fmt->font.source); 1201 if (fmt->font.source) eina_stringshare_del(fmt->font.source);
1283 fmt->font.source = eina_stringshare_add(tmp_param); 1202 fmt->font.source = eina_stringshare_add(tmp_param);
1284 new_font = 1;
1285 } 1203 }
1286 } 1204 }
1287 if (cmd == font_weightstr) 1205 if (cmd == font_weightstr)
1288 { 1206 {
1289 _format_command_parse_font_weight_style(fmt, tmp_param, 1207 fmt->font.fdesc->weight = evas_font_style_find(tmp_param,
1290 _style_weight_map, _STYLE_WEIGHT_MAP_LEN); 1208 tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_WEIGHT);
1291 new_font = 1;
1292 } 1209 }
1293 if (cmd == font_stylestr) 1210 if (cmd == font_stylestr)
1294 { 1211 {
1295 _format_command_parse_font_weight_style(fmt, tmp_param, 1212 fmt->font.fdesc->slant = evas_font_style_find(tmp_param,
1296 _style_style_map, _STYLE_STYLE_MAP_LEN); 1213 tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_SLANT);
1297 new_font = 1;
1298 } 1214 }
1299 else if (cmd == colorstr) 1215 else if (cmd == colorstr)
1300 _format_color_parse(tmp_param, 1216 _format_color_parse(tmp_param,
@@ -1616,29 +1532,6 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
1616 else if (!strcmp(tmp_param, "on")) 1532 else if (!strcmp(tmp_param, "on"))
1617 fmt->password = 1; 1533 fmt->password = 1;
1618 } 1534 }
1619
1620 if (new_font)
1621 {
1622 void *of;
1623 char *buf = NULL;
1624
1625 of = fmt->font.font;
1626 if ((fmt->font.name) && (fmt->font.fallbacks))
1627 {
1628 buf = malloc(strlen(fmt->font.name) + 1 + strlen(fmt->font.fallbacks) + 1);
1629 strcpy(buf, fmt->font.name);
1630 strcat(buf, ",");
1631 strcat(buf, fmt->font.fallbacks);
1632 }
1633 else if (fmt->font.name)
1634 buf = strdup(fmt->font.name);
1635
1636 fmt->font.font = evas_font_load(obj->layer->evas,
1637 buf, fmt->font.source,
1638 (int)(((double)fmt->font.size) * obj->cur.scale));
1639 if (buf) free(buf);
1640 if (of) evas_font_free(obj->layer->evas, of);
1641 }
1642} 1535}
1643 1536
1644/** 1537/**
@@ -1796,22 +1689,14 @@ _format_dup(Evas_Object *obj, const Evas_Object_Textblock_Format *fmt)
1796 fmt2 = calloc(1, sizeof(Evas_Object_Textblock_Format)); 1689 fmt2 = calloc(1, sizeof(Evas_Object_Textblock_Format));
1797 memcpy(fmt2, fmt, sizeof(Evas_Object_Textblock_Format)); 1690 memcpy(fmt2, fmt, sizeof(Evas_Object_Textblock_Format));
1798 fmt2->ref = 1; 1691 fmt2->ref = 1;
1799 if (fmt->font.name) fmt2->font.name = eina_stringshare_add(fmt->font.name); 1692 fmt2->font.fdesc = evas_font_desc_ref(fmt->font.fdesc);
1693
1800 if (fmt->font.fallbacks) fmt2->font.fallbacks = eina_stringshare_add(fmt->font.fallbacks); 1694 if (fmt->font.fallbacks) fmt2->font.fallbacks = eina_stringshare_add(fmt->font.fallbacks);
1801 if (fmt->font.source) fmt2->font.source = eina_stringshare_add(fmt->font.source); 1695 if (fmt->font.source) fmt2->font.source = eina_stringshare_add(fmt->font.source);
1802 1696
1803 if ((fmt2->font.name) && (fmt2->font.fallbacks)) 1697 /* FIXME: just ref the font here... */
1804 { 1698 fmt2->font.font = evas_font_load(obj->layer->evas, fmt2->font.fdesc,
1805 buf = malloc(strlen(fmt2->font.name) + 1 + strlen(fmt2->font.fallbacks) + 1); 1699 fmt2->font.source, (int)(((double) fmt2->font.size) * obj->cur.scale));
1806 strcpy(buf, fmt2->font.name);
1807 strcat(buf, ",");
1808 strcat(buf, fmt2->font.fallbacks);
1809 }
1810 else if (fmt2->font.name)
1811 buf = strdup(fmt2->font.name);
1812 fmt2->font.font = evas_font_load(obj->layer->evas,
1813 buf, fmt2->font.source,
1814 (int)(((double)fmt2->font.size) * obj->cur.scale));
1815 if (buf) free(buf); 1700 if (buf) free(buf);
1816 return fmt2; 1701 return fmt2;
1817} 1702}
@@ -3067,6 +2952,23 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const cha
3067 2952
3068/** 2953/**
3069 * @internal 2954 * @internal
2955 * Should be call after we finish filling a format.
2956 * FIXME: doc.
2957 */
2958static void
2959_format_finalize(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
2960{
2961 void *of;
2962
2963 of = fmt->font.font;
2964
2965 fmt->font.font = evas_font_load(obj->layer->evas, fmt->font.fdesc,
2966 fmt->font.source, (int)(((double) fmt->font.size) * obj->cur.scale));
2967 if (of) evas_font_free(obj->layer->evas, of);
2968}
2969
2970/**
2971 * @internal
3070 * Returns true if the item is a tab 2972 * Returns true if the item is a tab
3071 * @def _IS_TAB(item) 2973 * @def _IS_TAB(item)
3072 */ 2974 */
@@ -3253,6 +3155,7 @@ _layout_do_format(const Evas_Object *obj __UNUSED__, Ctxt *c,
3253 } 3155 }
3254 } 3156 }
3255 } 3157 }
3158 _format_finalize(c->obj, fmt);
3256 } 3159 }
3257 3160
3258 { 3161 {
@@ -4222,6 +4125,7 @@ _layout(const Evas_Object *obj, int w, int h, int *w_ret, int *h_ret)
4222 { 4125 {
4223 c->fmt = _layout_format_push(c, NULL, NULL); 4126 c->fmt = _layout_format_push(c, NULL, NULL);
4224 _format_fill(c->obj, c->fmt, c->o->style->default_tag); 4127 _format_fill(c->obj, c->fmt, c->o->style->default_tag);
4128 _format_finalize(c->obj, c->fmt);
4225 } 4129 }
4226 if (!c->fmt) 4130 if (!c->fmt)
4227 { 4131 {
diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h
index 768d7d2f34..77b41fde3d 100644
--- a/legacy/evas/src/lib/include/evas_private.h
+++ b/legacy/evas/src/lib/include/evas_private.h
@@ -31,6 +31,7 @@ typedef struct _Evas_Size_Hints Evas_Size_Hints;
31typedef struct _Evas_Font_Dir Evas_Font_Dir; 31typedef struct _Evas_Font_Dir Evas_Font_Dir;
32typedef struct _Evas_Font Evas_Font; 32typedef struct _Evas_Font Evas_Font;
33typedef struct _Evas_Font_Alias Evas_Font_Alias; 33typedef struct _Evas_Font_Alias Evas_Font_Alias;
34typedef struct _Evas_Font_Description Evas_Font_Description;
34typedef struct _Evas_Data_Node Evas_Data_Node; 35typedef struct _Evas_Data_Node Evas_Data_Node;
35typedef struct _Evas_Func_Node Evas_Func_Node; 36typedef struct _Evas_Func_Node Evas_Func_Node;
36typedef RGBA_Image_Loadopts Evas_Image_Load_Opts; 37typedef RGBA_Image_Loadopts Evas_Image_Load_Opts;
@@ -46,6 +47,11 @@ typedef struct _Evas_Map_Point Evas_Map_Point;
46typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array; 47typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array;
47typedef struct _Evas_Post_Callback Evas_Post_Callback; 48typedef struct _Evas_Post_Callback Evas_Post_Callback;
48 49
50typedef enum _Evas_Font_Style Evas_Font_Style;
51typedef enum _Evas_Font_Slant Evas_Font_Slant;
52typedef enum _Evas_Font_Weight Evas_Font_Weight;
53typedef enum _Evas_Font_Width Evas_Font_Width;
54
49/* General types - used for script type chceking */ 55/* General types - used for script type chceking */
50#define OPAQUE_TYPE(type) struct __##type { int a; }; \ 56#define OPAQUE_TYPE(type) struct __##type { int a; }; \
51 typedef struct __##type type 57 typedef struct __##type type
@@ -584,6 +590,61 @@ struct _Evas_Font_Alias
584 Evas_Font *fn; 590 Evas_Font *fn;
585}; 591};
586 592
593enum _Evas_Font_Style
594{
595 EVAS_FONT_STYLE_SLANT,
596 EVAS_FONT_STYLE_WEIGHT,
597 EVAS_FONT_STYLE_WIDTH
598};
599
600enum _Evas_Font_Slant
601{
602 EVAS_FONT_SLANT_NORMAL,
603 EVAS_FONT_SLANT_OBLIQUE,
604 EVAS_FONT_SLANT_ITALIC
605};
606
607enum _Evas_Font_Weight
608{
609 EVAS_FONT_WEIGHT_NORMAL,
610 EVAS_FONT_WEIGHT_THIN,
611 EVAS_FONT_WEIGHT_ULTRALIGHT,
612 EVAS_FONT_WEIGHT_LIGHT,
613 EVAS_FONT_WEIGHT_BOOK,
614 EVAS_FONT_WEIGHT_MEDIUM,
615 EVAS_FONT_WEIGHT_SEMIBOLD,
616 EVAS_FONT_WEIGHT_BOLD,
617 EVAS_FONT_WEIGHT_ULTRABOLD,
618 EVAS_FONT_WEIGHT_BLACK,
619 EVAS_FONT_WEIGHT_EXTRABLACK
620};
621
622enum _Evas_Font_Width
623{
624 EVAS_FONT_WIDTH_NORMAL,
625 EVAS_FONT_WIDTH_ULTRACONDENSED,
626 EVAS_FONT_WIDTH_EXTRACONDENSED,
627 EVAS_FONT_WIDTH_CONDENSED,
628 EVAS_FONT_WIDTH_SEMICONDENSED,
629 EVAS_FONT_WIDTH_SEMIEXPANDED,
630 EVAS_FONT_WIDTH_EXPANDED,
631 EVAS_FONT_WIDTH_EXTRAEXPANDED,
632 EVAS_FONT_WIDTH_ULTRAEXPANDED
633};
634
635struct _Evas_Font_Description
636{
637 int ref;
638 /* We assume everywhere this is stringshared */
639 const char *name;
640
641 Evas_Font_Slant slant;
642 Evas_Font_Weight weight;
643 Evas_Font_Width width;
644
645 Eina_Bool new : 1;
646};
647
587struct _Evas_Object_Func 648struct _Evas_Object_Func
588{ 649{
589 void (*free) (Evas_Object *obj); 650 void (*free) (Evas_Object *obj);
@@ -871,7 +932,14 @@ void evas_font_dir_available_list_free(Eina_List *available);
871void evas_font_free(Evas *evas, void *font); 932void evas_font_free(Evas *evas, void *font);
872void evas_fonts_zero_free(Evas *evas); 933void evas_fonts_zero_free(Evas *evas);
873void evas_fonts_zero_presure(Evas *evas); 934void evas_fonts_zero_presure(Evas *evas);
874void *evas_font_load(Evas *evas, const char *name, const char *source, int size); 935void evas_font_name_parse(Evas_Font_Description *fdesc, const char *name);
936int evas_font_style_find(const char *start, const char *end, Evas_Font_Style style);
937Evas_Font_Description *evas_font_desc_new(void);
938Evas_Font_Description *evas_font_desc_dup(const Evas_Font_Description *fdesc);
939void evas_font_desc_unref(Evas_Font_Description *fdesc);
940int evas_font_desc_cmp(const Evas_Font_Description *a, const Evas_Font_Description *b);
941Evas_Font_Description *evas_font_desc_ref(Evas_Font_Description *fdesc);
942void * evas_font_load(Evas *evas, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size);
875void evas_font_load_hinting_set(Evas *evas, void *font, int hinting); 943void evas_font_load_hinting_set(Evas *evas, void *font, int hinting);
876void evas_object_smart_member_cache_invalidate(Evas_Object *obj); 944void evas_object_smart_member_cache_invalidate(Evas_Object *obj);
877void evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b); 945void evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b);