billiob pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=b0d039aa02471c342523d11755dbb933f0ef5c83

commit b0d039aa02471c342523d11755dbb933f0ef5c83
Author: Boris Faure <bill...@gmail.com>
Date:   Wed Sep 2 23:02:29 2015 +0200

    evas_text_grid: display bold/italic/bolditalic fonts if available
---
 src/lib/evas/canvas/evas_object_textgrid.c | 420 +++++++++++++++++++++--------
 1 file changed, 310 insertions(+), 110 deletions(-)

diff --git a/src/lib/evas/canvas/evas_object_textgrid.c 
b/src/lib/evas/canvas/evas_object_textgrid.c
index 45aeab6..75ac501 100644
--- a/src/lib/evas/canvas/evas_object_textgrid.c
+++ b/src/lib/evas/canvas/evas_object_textgrid.c
@@ -36,7 +36,7 @@ struct _Evas_Textgrid_Data
       const char                 *font_source;
       const char                 *font_name;
       Evas_Font_Size              font_size;
-      Evas_Font_Description      *font_description;
+      Evas_Font_Description      *font_description_normal;
 
       Eina_Array                  palette_standard;
       Eina_Array                  palette_extended;
@@ -44,7 +44,10 @@ struct _Evas_Textgrid_Data
 
    int                            ascent;
 
-   Evas_Font_Set                 *font;
+   Evas_Font_Set                 *font_normal;
+   Evas_Font_Set                 *font_bold;
+   Evas_Font_Set                 *font_italic;
+   Evas_Font_Set                 *font_bolditalic;
 
    unsigned int                   changed : 1;
    unsigned int                   core_change : 1;
@@ -75,9 +78,11 @@ struct _Evas_Object_Textgrid_Rect
 
 struct _Evas_Object_Textgrid_Text
 {
-   unsigned char r, g, b, a;
-   int x;
    Evas_Text_Props text_props;
+   unsigned char r, g, b, a;
+   int           x      : 30;
+   unsigned char bold   :  1;
+   unsigned char italic :  1;
 };
 
 struct _Evas_Object_Textgrid_Line
@@ -216,8 +221,14 @@ evas_object_textgrid_free(Evas_Object *eo_obj, 
Evas_Object_Protected_Data *obj)
    if (o->cur.rows) free(o->cur.rows);
    if (o->cur.font_name) eina_stringshare_del(o->cur.font_name);
    if (o->cur.font_source) eina_stringshare_del(o->cur.font_source);
-   if (o->cur.font_description) evas_font_desc_unref(o->cur.font_description);
-   if (o->font) evas_font_free(obj->layer->evas->evas, o->font);
+
+   if (o->cur.font_description_normal)
+     evas_font_desc_unref(o->cur.font_description_normal);
+   if (o->font_normal) evas_font_free(obj->layer->evas->evas, o->font_normal);
+   if (o->font_bold) evas_font_free(obj->layer->evas->evas, o->font_bold);
+   if (o->font_italic) evas_font_free(obj->layer->evas->evas, o->font_italic);
+   if (o->font_bolditalic) evas_font_free(obj->layer->evas->evas, 
o->font_bolditalic);
+
    if (o->cur.cells) free(o->cur.cells);
    while ((c = eina_array_pop(&o->cur.palette_standard)))
      free(c);
@@ -265,17 +276,58 @@ 
evas_object_textgrid_row_rect_append(Evas_Object_Textgrid_Row *row,
    row->rects[row->rects_num - 1].a = a;
 }
 
+static Evas_Font_Set *
+_textgrid_font_get(Evas_Textgrid_Data *o,
+                   Eina_Bool is_bold,
+                   Eina_Bool is_italic)
+{
+   if ((!is_bold) && (!is_italic))
+     return o->font_normal;
+   /* bold */
+   else if ((is_bold) && (!is_italic))
+     {
+        if (o->font_bold)
+          return o->font_bold;
+        else
+          return o->font_normal;
+     }
+   /* italic */
+   else if ((!is_bold) && (is_italic))
+     {
+        if (o->font_italic)
+          return o->font_italic;
+        else
+          return o->font_normal;
+     }
+   /* bolditalic */
+   else
+     {
+        if (o->font_bolditalic)
+          return o->font_bolditalic;
+        else if (o->font_italic)
+          return o->font_italic;
+        else if (o->font_bold)
+          return o->font_bold;
+        else
+          return o->font_normal;
+     }
+}
+
 static void
 evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row,
                                      Evas_Object_Protected_Data *obj,
                                      Evas_Textgrid_Data *o,
                                      int x,
                                      Eina_Unicode codepoint,
-                                     int r, int g, int b, int a)
+                                     int r, int g, int b, int a,
+                                     Eina_Bool is_bold,
+                                     Eina_Bool is_italic)
 {
    Evas_Script_Type script;
    Evas_Font_Instance *script_fi = NULL;
    Evas_Font_Instance *cur_fi = NULL;
+   Evas_Object_Textgrid_Text *text;
+   Evas_Font_Set *font;
 
    row->texts_num++;
    if (row->texts_num > row->texts_alloc)
@@ -293,23 +345,24 @@ 
evas_object_textgrid_row_text_append(Evas_Object_Textgrid_Row *row,
      }
 
    script = evas_common_language_script_type_get(&codepoint, 1);
-   ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi,
+   text = &row->texts[row->texts_num - 1];
+   text->bold = is_bold;
+   text->italic = is_italic;
+   font = _textgrid_font_get(o, is_bold, is_italic);
+   ENFN->font_run_end_get(ENDT, font, &script_fi, &cur_fi,
                           script, &codepoint, 1);
-   memset(&(row->texts[row->texts_num - 1].text_props), 0,
-          sizeof(Evas_Text_Props));
-   evas_common_text_props_script_set
-     (&(row->texts[row->texts_num - 1].text_props), script);
-   ENFN->font_text_props_info_create
-     (ENDT, script_fi, &codepoint,
-         &(row->texts[row->texts_num - 1].text_props), NULL, 0, 1,
-         EVAS_TEXT_PROPS_MODE_NONE,
-         o->cur.font_description->lang);
-
-   row->texts[row->texts_num - 1].x = x;
-   row->texts[row->texts_num - 1].r = r;
-   row->texts[row->texts_num - 1].g = g;
-   row->texts[row->texts_num - 1].b = b;
-   row->texts[row->texts_num - 1].a = a;
+   memset(&(text->text_props), 0, sizeof(Evas_Text_Props));
+   evas_common_text_props_script_set(&(text->text_props), script);
+   ENFN->font_text_props_info_create(ENDT, script_fi, &codepoint,
+                                     &(text->text_props), NULL, 0, 1,
+                                     EVAS_TEXT_PROPS_MODE_NONE,
+                                     o->cur.font_description_normal->lang);
+
+   text->x = x;
+   text->r = r;
+   text->g = g;
+   text->b = b;
+   text->a = a;
 }
 
 static void
@@ -352,9 +405,10 @@ _drop_glyphs_ref(const void *container EINA_UNUSED, void 
*data, void *fdata)
 
 static void
 evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
-                           Evas_Object_Protected_Data *obj,
-                           void *type_private_data,
-                           void *output, void *context, void *surface, int x, 
int y, Eina_Bool do_async)
+                            Evas_Object_Protected_Data *obj,
+                            void *type_private_data,
+                            void *output, void *context, void *surface,
+                            int x, int y, Eina_Bool do_async)
 {
    Evas_Textgrid_Cell *cells;
    Evas_Object_Textgrid_Color *c;
@@ -367,7 +421,7 @@ evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
    ENFN->context_multiplier_unset(output, context);
    ENFN->context_render_op_set(output, context, obj->cur->render_op);
 
-   if (!(o->font) || (!o->cur.cells)) return;
+   if (!(o->font_normal) || (!o->cur.cells)) return;
 
    w = o->cur.char_width;
    h = o->cur.char_height;
@@ -439,7 +493,9 @@ evas_object_textgrid_render(Evas_Object *eo_obj EINA_UNUSED,
                          evas_object_textgrid_row_text_append(row, obj,
                                                               o, xp,
                                                               cells->codepoint,
-                                                              c->r, c->g, 
c->b, c->a);
+                                                              c->r, c->g, 
c->b, c->a,
+                                                              cells->bold,
+                                                              cells->italic);
                        // XXX: underlines and strikethroughs dont get
                        // merged into horizontal runs like bg rects above
                        if (cells->underline)
@@ -484,57 +540,82 @@ evas_object_textgrid_render(Evas_Object *eo_obj 
EINA_UNUSED,
           {
              if ((do_async) && (ENFN->multi_font_draw))
                {
+                  Evas_Font_Set *font, *current_font;
                   Eina_Bool async_unref;
-                 Evas_Font_Array_Data *fad;
-
-                  texts = malloc(sizeof(*texts));
-                  texts->array = 
eina_inarray_new(sizeof(Evas_Font_Array_Data), 1); /* FIXME: Wasting 1 int here 
*/
-                  texts->refcount = 1;
+                  Evas_Object_Textgrid_Text *text;
 
-                 fad = eina_inarray_grow(texts->array, row->texts_num);
-                 if (!fad)
-                   {
-                       ERR("Failed to allocate Evas_Font_Array_Data.");
-                       eina_inarray_free(texts->array);
-                       free(texts);
-                       return;
-                   }
-
-                  for (xx = 0; xx < row->texts_num; xx++)
+                  xx = 0;
+                  do
                     {
-                       Evas_Text_Props *props;
-
-                       props = &row->texts[xx].text_props;
-
-                       evas_common_font_draw_prepare(props);
-
-                       evas_common_font_glyphs_ref(props->glyphs);
-                       evas_unref_queue_glyph_put(obj->layer->evas,
-                                                  props->glyphs);
-
-                       fad->color.r = row->texts[xx].r;
-                       fad->color.g = row->texts[xx].g;
-                       fad->color.b = row->texts[xx].b;
-                       fad->color.a = row->texts[xx].a;
-                       fad->x = row->texts[xx].x;
-                       fad->glyphs = props->glyphs;
-
-                      fad++;
-                    }
-
-                  async_unref =
-                    ENFN->multi_font_draw(output, context, surface,
-                                          o->font, xp, yp + o->ascent,
-                                          ww, hh, ww, hh, texts, do_async);
-                  if (async_unref)
-                    evas_unref_queue_texts_put(obj->layer->evas, texts);
-                  else
-                    {
-                       eina_inarray_foreach(texts->array, _drop_glyphs_ref,
-                                            obj->layer->evas);
-                       eina_inarray_free(texts->array);
-                       free(texts);
+                       texts = malloc(sizeof(*texts));
+                       if (!texts)
+                         {
+                            ERR("Failed to allocate Evas_Font_Array.");
+                            return;
+                         }
+                       texts->array = 
eina_inarray_new(sizeof(Evas_Font_Array_Data), 1);
+                       texts->refcount = 1;
+
+                       text = &row->texts[xx];
+                       font = _textgrid_font_get(o, text->bold, text->italic);
+
+                       do
+                         {
+                            Evas_Font_Array_Data *fad;
+                            Evas_Text_Props *props;
+
+                            current_font = font;
+
+                            props = &text->text_props;
+                            evas_common_font_draw_prepare(props);
+
+                            evas_common_font_glyphs_ref(props->glyphs);
+                            evas_unref_queue_glyph_put(obj->layer->evas,
+                                                       props->glyphs);
+
+                            fad = eina_inarray_grow(texts->array, 1);
+                            if (!fad)
+                              {
+                                 ERR("Failed to allocate 
Evas_Font_Array_Data.");
+                                 eina_inarray_free(texts->array);
+                                 free(texts);
+                                 return;
+                              }
+                            fad->color.r = text->r;
+                            fad->color.g = text->g;
+                            fad->color.b = text->b;
+                            fad->color.a = text->a;
+                            fad->x = text->x;
+                            fad->glyphs = props->glyphs;
+
+                            fad++;
+
+                            xx++;
+                            if (xx >= row->texts_num)
+                              break;
+                            text = &row->texts[xx];
+                            font = _textgrid_font_get(o, text->bold,
+                                                      text->italic);
+                         }
+                       while (font == current_font);
+
+                       async_unref =
+                          ENFN->multi_font_draw(output, context, surface,
+                                                current_font,
+                                                xp,
+                                                yp + o->ascent,
+                                                ww, hh, ww, hh, texts, 
do_async);
+                       if (async_unref)
+                         evas_unref_queue_texts_put(obj->layer->evas, texts);
+                       else
+                         {
+                            eina_inarray_foreach(texts->array, 
_drop_glyphs_ref,
+                                                 obj->layer->evas);
+                            eina_inarray_free(texts->array);
+                            free(texts);
+                         }
                     }
+                  while (xx < row->texts_num);
                }
              else
                {
@@ -542,20 +623,23 @@ evas_object_textgrid_render(Evas_Object *eo_obj 
EINA_UNUSED,
                     {
                        Evas_Text_Props *props;
                        unsigned int     r, g, b, a;
-                       int              tx = xp + row->texts[xx].x;
+                       Evas_Object_Textgrid_Text *text = &row->texts[xx];
+                       int              tx = xp + text->x;
                        int              ty = yp + o->ascent;
+                       Evas_Font_Set *font;
 
-                       props = &row->texts[xx].text_props;
+                       props = &text->text_props;
 
-                       r = row->texts[xx].r;
-                       g = row->texts[xx].g;
-                       b = row->texts[xx].b;
-                       a = row->texts[xx].a;
+                       r = text->r;
+                       g = text->g;
+                       b = text->b;
+                       a = text->a;
 
                        ENFN->context_color_set(output, context,
                                                r, g, b, a);
+                       font = _textgrid_font_get(o, text->bold, text->italic);
                        evas_font_draw_async_check(obj, output, context, 
surface,
-                                                  o->font, tx, ty, ww, hh,
+                                                  font, tx, ty, ww, hh,
                                                   ww, hh, props, do_async);
                     }
                }
@@ -758,7 +842,7 @@ evas_object_textgrid_engine_data_get(Evas_Object *eo_obj)
 {
    Evas_Textgrid_Data *o = eo_data_scope_get(eo_obj, MY_CLASS);
    if (!o) return NULL;
-   return o->font;
+   return o->font_normal; /* TODO: why ? */
 }
 
 static int
@@ -899,35 +983,89 @@ _evas_textgrid_efl_text_properties_font_source_get(Eo 
*eo_obj EINA_UNUSED, Evas_
    return o->cur.font_source;
 }
 
+static int
+_alternate_font_weight_slant(Evas_Object_Protected_Data *obj,
+                             Evas_Textgrid_Data *o,
+                             Evas_Font_Set **fontp,
+                             Evas_Font_Description *fdesc)
+{
+   int ret = -1;
+   Evas_Font_Set *font;
+
+   font = evas_font_load(obj->layer->evas->evas,
+                         fdesc,
+                         o->cur.font_source,
+                         (int)(((double) o->cur.font_size) *
+                               obj->cur->scale));
+   if (font)
+     {
+        Eina_Unicode W[2] = { 'O', 0 };
+        Evas_Font_Instance *script_fi = NULL;
+        Evas_Font_Instance *cur_fi = NULL;
+        Evas_Text_Props text_props;
+        Evas_Script_Type script;
+        int advance, vadvance, ascent;
+
+        script = evas_common_language_script_type_get(W, 1);
+        ENFN->font_run_end_get(ENDT, font, &script_fi, &cur_fi,
+                               script, W, 1);
+        memset(&text_props, 0, sizeof(Evas_Text_Props));
+        evas_common_text_props_script_set(&text_props, script);
+        ENFN->font_text_props_info_create(ENDT, script_fi, W, &text_props,
+                                          NULL, 0, 1,
+                                          EVAS_TEXT_PROPS_MODE_NONE,
+                                          fdesc->lang);
+        advance = ENFN->font_h_advance_get(ENDT, font, &text_props);
+        vadvance = ENFN->font_v_advance_get(ENDT, font, &text_props);
+        ascent = ENFN->font_ascent_get(ENDT, font);
+        if ((o->cur.char_width != advance) ||
+            (o->cur.char_height != vadvance) ||
+            (o->ascent != ascent))
+          {
+             evas_font_free(obj->layer->evas->evas, font);
+          }
+        else
+          {
+             *fontp = font;
+             ret = 0;
+          }
+        evas_common_text_props_content_unref(&text_props);
+     }
+   return ret;
+}
+
 EOLIAN static void
-_evas_textgrid_efl_text_properties_font_set(Eo *eo_obj, Evas_Textgrid_Data *o, 
const char *font_name, Evas_Font_Size font_size)
+_evas_textgrid_efl_text_properties_font_set(Eo *eo_obj,
+                                            Evas_Textgrid_Data *o,
+                                            const char *font_name,
+                                            Evas_Font_Size font_size)
 {
    Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, 
EVAS_OBJECT_CLASS);
    Eina_Bool is, was = EINA_FALSE;
    Eina_Bool pass = EINA_FALSE, freeze = EINA_FALSE;
    Eina_Bool source_invisible = EINA_FALSE;
-   Evas_Font_Description *font_description;
-   
+   Evas_Font_Description *fdesc;
+
    if ((!font_name) || (!*font_name) || (font_size <= 0))
      return;
 
    evas_object_async_block(obj);
-   font_description = evas_font_desc_new();
-
+   fdesc = evas_font_desc_new();
    /* Set default language according to locale. */
-   eina_stringshare_replace(&(font_description->lang),
+   eina_stringshare_replace(&(fdesc->lang),
                             evas_font_lang_normalize("auto"));
-   evas_font_name_parse(font_description, font_name);
-   if (o->cur.font_description &&
-       !evas_font_desc_cmp(font_description, o->cur.font_description) &&
+   evas_font_name_parse(fdesc, font_name);
+   if (o->cur.font_description_normal &&
+       !evas_font_desc_cmp(fdesc, o->cur.font_description_normal) &&
        (font_size == o->cur.font_size))
      {
-        evas_font_desc_unref(font_description);
+        evas_font_desc_unref(fdesc);
         return;
      }
 
-   if (o->cur.font_description) evas_font_desc_unref(o->cur.font_description);
-   o->cur.font_description = font_description;
+   if (o->cur.font_description_normal)
+     evas_font_desc_unref(o->cur.font_description_normal);
+   o->cur.font_description_normal = fdesc;
 
    o->cur.font_size = font_size;
    eina_stringshare_replace(&o->cur.font_name, font_name);
@@ -944,19 +1082,19 @@ _evas_textgrid_efl_text_properties_font_set(Eo *eo_obj, 
Evas_Textgrid_Data *o, c
                                               obj->layer->evas->pointer.y,
                                               1, 1);
      }
-   
-   /* DO IT */
-   if (o->font)
+
+   if (o->font_normal)
      {
-        evas_font_free(obj->layer->evas->evas, o->font);
-        o->font = NULL;
+        evas_font_free(obj->layer->evas->evas, o->font_normal);
+        o->font_normal = NULL;
      }
-   
-   o->font = evas_font_load(obj->layer->evas->evas, o->cur.font_description,
+
+   o->font_normal = evas_font_load(obj->layer->evas->evas,
+                            o->cur.font_description_normal,
                             o->cur.font_source,
-                            (int)(((double) o->cur.font_size) * 
+                            (int)(((double) o->cur.font_size) *
                                   obj->cur->scale));
-   if (o->font)
+   if (o->font_normal)
      {
         Eina_Unicode W[2] = { 'O', 0 };
         Evas_Font_Instance *script_fi = NULL;
@@ -964,21 +1102,21 @@ _evas_textgrid_efl_text_properties_font_set(Eo *eo_obj, 
Evas_Textgrid_Data *o, c
         Evas_Text_Props text_props;
         Evas_Script_Type script;
         int advance, vadvance;
-        
+
         script = evas_common_language_script_type_get(W, 1);
-        ENFN->font_run_end_get(ENDT, o->font, &script_fi, &cur_fi,
+        ENFN->font_run_end_get(ENDT, o->font_normal, &script_fi, &cur_fi,
                                script, W, 1);
         memset(&text_props, 0, sizeof(Evas_Text_Props));
         evas_common_text_props_script_set(&text_props, script);
         ENFN->font_text_props_info_create(ENDT, script_fi, W, &text_props,
                                           NULL, 0, 1,
                                           EVAS_TEXT_PROPS_MODE_NONE,
-                                          o->cur.font_description->lang);
-        advance = ENFN->font_h_advance_get(ENDT, o->font, &text_props);
-        vadvance = ENFN->font_v_advance_get(ENDT, o->font, &text_props);
+                                          fdesc->lang);
+        advance = ENFN->font_h_advance_get(ENDT, o->font_normal, &text_props);
+        vadvance = ENFN->font_v_advance_get(ENDT, o->font_normal, &text_props);
         o->cur.char_width = advance;
         o->cur.char_height = vadvance;
-        o->ascent = ENFN->font_ascent_get(ENDT, o->font);;
+        o->ascent = ENFN->font_ascent_get(ENDT, o->font_normal);
         evas_common_text_props_content_unref(&text_props);
      }
    else
@@ -993,6 +1131,68 @@ _evas_textgrid_efl_text_properties_font_set(Eo *eo_obj, 
Evas_Textgrid_Data *o, c
         o->ascent = 0;
      }
 
+   /* Bold */
+   if (o->font_bold)
+     {
+        evas_font_free(obj->layer->evas->evas, o->font_bold);
+        o->font_bold = NULL;
+     }
+   if (fdesc->weight == EVAS_FONT_WEIGHT_NORMAL)
+     {
+        Evas_Font_Description *bold_desc = evas_font_desc_dup(fdesc);
+        bold_desc->weight = EVAS_FONT_WEIGHT_BOLD;
+        _alternate_font_weight_slant(obj, o, &o->font_bold, bold_desc);
+        evas_font_desc_unref(bold_desc);
+     }
+
+   /* Italic */
+   if (o->font_italic)
+     {
+        evas_font_free(obj->layer->evas->evas, o->font_italic);
+        o->font_italic = NULL;
+     }
+   if (fdesc->slant == EVAS_FONT_SLANT_NORMAL)
+     {
+        Evas_Font_Description *italic_desc = evas_font_desc_dup(fdesc);
+        int ret;
+
+        italic_desc->slant = EVAS_FONT_SLANT_ITALIC;
+        ret = _alternate_font_weight_slant(obj, o, &o->font_italic,
+                                           italic_desc);
+        if (ret != 0)
+          {
+             italic_desc->slant = EVAS_FONT_SLANT_OBLIQUE;
+             _alternate_font_weight_slant(obj, o, &o->font_italic,
+                                          italic_desc);
+          }
+        evas_font_desc_unref(italic_desc);
+     }
+
+   /* BoldItalic */
+   if (o->font_bolditalic)
+     {
+        evas_font_free(obj->layer->evas->evas, o->font_bolditalic);
+        o->font_bolditalic = NULL;
+     }
+   if (fdesc->slant == EVAS_FONT_SLANT_NORMAL &&
+       fdesc->weight == EVAS_FONT_WEIGHT_NORMAL)
+     {
+        Evas_Font_Description *bolditalic_desc = evas_font_desc_dup(fdesc);
+        int ret;
+
+        bolditalic_desc->slant = EVAS_FONT_SLANT_ITALIC;
+        bolditalic_desc->weight = EVAS_FONT_WEIGHT_BOLD;
+        ret = _alternate_font_weight_slant(obj, o, &o->font_bolditalic,
+                                           bolditalic_desc);
+        if (ret != 0)
+          {
+             bolditalic_desc->slant = EVAS_FONT_SLANT_OBLIQUE;
+             _alternate_font_weight_slant(obj, o, &o->font_bolditalic,
+                                          bolditalic_desc);
+          }
+        evas_font_desc_unref(bolditalic_desc);
+     }
+
    o->changed = 1;
    evas_object_change(eo_obj, obj);
    evas_object_clip_dirty(eo_obj, obj);

-- 


Reply via email to