Beispiel #1
0
EAPI Eina_Bool
evas_common_text_props_content_create(void *_fi, const Eina_Unicode *text,
      Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props,
      size_t par_pos, int len)
{
   RGBA_Font_Int *fi = (RGBA_Font_Int *) _fi;

   if (text_props->info)
     {
        evas_common_text_props_content_unref(text_props);
     }
   if (len == 0)
     {
        text_props->info = NULL;
        text_props->start = text_props->len = text_props->text_offset = 0;
     }
   text_props->info = calloc(1, sizeof(Evas_Text_Props_Info));

   text_props->font_instance = fi;

   evas_common_font_int_reload(fi);
   if (fi->src->current_size != fi->size)
     {
        FTLOCK();
        FT_Activate_Size(fi->ft.size);
        FTUNLOCK();
        fi->src->current_size = fi->size;
     }

#ifdef OT_SUPPORT
   size_t char_index;
   Evas_Font_Glyph_Info *gl_itr;
   Evas_Coord pen_x = 0, adjust_x = 0;
   (void) par_props;
   (void) par_pos;

   evas_common_font_ot_populate_text_props(text, text_props, len);

   gl_itr = text_props->info->glyph;
   for (char_index = 0 ; char_index < text_props->len ; char_index++)
     {
        FT_UInt idx;
        RGBA_Font_Glyph *fg;
        Eina_Bool is_replacement = EINA_FALSE;
        /* If we got a malformed index, show the replacement char instead */
        if (gl_itr->index == 0)
          {
             gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
             is_replacement = EINA_TRUE;
          }
        idx = gl_itr->index;
        LKL(fi->ft_mutex);
        fg = evas_common_font_int_cache_glyph_get(fi, idx);
        if (!fg)
          {
             LKU(fi->ft_mutex);
             continue;
          }
        LKU(fi->ft_mutex);

        gl_itr->x_bear = fg->glyph_out->left;
        gl_itr->width = fg->glyph_out->bitmap.width;
        /* text_props->info->glyph[char_index].advance =
         * text_props->info->glyph[char_index].index =
         * already done by the ot function */
        if (EVAS_FONT_CHARACTER_IS_INVISIBLE(
              text[text_props->info->ot[char_index].source_cluster]))
          {
             gl_itr->index = 0;
             /* Reduce the current advance */
             if (gl_itr > text_props->info->glyph)
               {
                  adjust_x -= gl_itr->pen_after - (gl_itr - 1)->pen_after;
               }
             else
               {
                  adjust_x -= gl_itr->pen_after;
               }
          }
        else
          {
             if (is_replacement)
               {
                  /* Update the advance accordingly */
                  adjust_x += (pen_x + (fg->glyph->advance.x >> 16)) -
                     gl_itr->pen_after;
               }
             pen_x = gl_itr->pen_after;
          }
        gl_itr->pen_after += adjust_x;

        fi = text_props->font_instance;
        gl_itr++;
     }
#else
   /* We are walking the string in visual ordering */
   Evas_Font_Glyph_Info *gl_itr;
   Eina_Bool use_kerning;
   FT_UInt prev_index;
   FT_Face pface = NULL;
   Evas_Coord pen_x = 0;
   int adv_d, i;
#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT)
   Eina_Unicode *base_str = NULL;
   if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
     {
        text = base_str = eina_unicode_strndup(text, len);
        evas_bidi_shape_string(base_str, par_props, par_pos, len);
     }
#else
   (void) par_props;
   (void) par_pos;
#endif

   FTLOCK();
   use_kerning = FT_HAS_KERNING(fi->src->ft.face);
   FTUNLOCK();
   prev_index = 0;

   i = len;
   text_props->info->glyph = calloc(len,
                                    sizeof(Evas_Font_Glyph_Info));

   if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
     {
        text += len - 1;
        adv_d = -1;
     }
   else
     {
        adv_d = 1;
     }

   gl_itr = text_props->info->glyph;
   for ( ; i > 0 ; gl_itr++, text += adv_d, i--)
     {
        FT_UInt idx;
        RGBA_Font_Glyph *fg;
        int _gl, kern;
        Evas_Coord adv;
        _gl = *text;
        if (_gl == 0) break;

        idx = evas_common_get_char_index(fi, _gl);
        if (idx == 0)
          {
             idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
          }

        LKL(fi->ft_mutex);
        fg = evas_common_font_int_cache_glyph_get(fi, idx);
        if (!fg)
          {
             LKU(fi->ft_mutex);
             continue;
          }
        kern = 0;

        if ((use_kerning) && (prev_index) && (idx) &&
            (pface == fi->src->ft.face))
          {
             if (evas_common_font_query_kerning(fi, prev_index, idx, &kern))
               {
                  pen_x += kern;
                  (gl_itr - 1)->pen_after +=
                     EVAS_FONT_ROUND_26_6_TO_INT(kern);
               }
          }

        pface = fi->src->ft.face;
        LKU(fi->ft_mutex);

        gl_itr->index = idx;
        gl_itr->x_bear = fg->glyph_out->left;
        adv = fg->glyph->advance.x >> 10;
        gl_itr->width = fg->glyph_out->bitmap.width;

        if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl))
          {
             gl_itr->index = 0;
          }
        else
          {
             pen_x += adv;
          }

        gl_itr->pen_after = EVAS_FONT_ROUND_26_6_TO_INT(pen_x);

        prev_index = idx;
     }
   text_props->len = len;
# if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT)
   if (base_str)
      free(base_str);
# endif
#endif
   text_props->text_len = len;
   text_props->info->refcount = 1;
   return EINA_TRUE;
}
Beispiel #2
0
static inline void
_content_create_regular(RGBA_Font_Int *fi, const Eina_Unicode *text,
      Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props,
      size_t par_pos, int len, Evas_Text_Props_Mode mode)
{
   /* We are walking the string in visual ordering */
   Evas_Font_Glyph_Info *gl_itr;
   Eina_Bool use_kerning;
   FT_UInt prev_index;
   FT_Face pface = NULL;
   Evas_Coord pen_x = 0;
   int adv_d, i;
#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT)
   Eina_Unicode *base_str = NULL;
   if (mode == EVAS_TEXT_PROPS_MODE_SHAPE)
     {
        if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
          {
             text = base_str = eina_unicode_strndup(text, len);
             evas_bidi_shape_string(base_str, par_props, par_pos, len);
          }
     }
#else
   (void) mode;
   (void) par_props;
   (void) par_pos;
#endif

   FTLOCK();
   use_kerning = FT_HAS_KERNING(fi->src->ft.face);
   FTUNLOCK();
   prev_index = 0;

   i = len;
   text_props->info->glyph = calloc(len,
                                    sizeof(Evas_Font_Glyph_Info));

   if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL)
     {
        text += len - 1;
        adv_d = -1;
     }
   else
     {
        adv_d = 1;
     }

   gl_itr = text_props->info->glyph;
   for ( ; i > 0 ; gl_itr++, text += adv_d, i--)
     {
        FT_UInt idx;
        RGBA_Font_Glyph *fg;
        int _gl, kern;
        Evas_Coord adv;
        _gl = *text;
        if (_gl == 0) break;

        idx = evas_common_get_char_index(fi, _gl);
        if (idx == 0)
          {
             idx = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
          }

        fg = evas_common_font_int_cache_glyph_get(fi, idx);
        if (!fg) continue;
        kern = 0;

        if ((use_kerning) && (prev_index) && (idx) &&
            (pface == fi->src->ft.face))
          {
             if (evas_common_font_query_kerning(fi, prev_index, idx, &kern))
               {
                  pen_x += kern;
                  (gl_itr - 1)->pen_after +=
                     EVAS_FONT_ROUND_26_6_TO_INT(kern);
               }
          }

        pface = fi->src->ft.face;

        gl_itr->index = idx;
        gl_itr->x_bear = fg->x_bear;
        gl_itr->y_bear = fg->y_bear;
        adv = fg->glyph->advance.x >> 10;
        gl_itr->width = fg->width;

        if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl))
          {
             gl_itr->index = 0;
          }
        else
          {
             pen_x += adv;
          }

        gl_itr->pen_after = EVAS_FONT_ROUND_26_6_TO_INT(pen_x);

        prev_index = idx;
     }
   text_props->len = len;
# if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT)
   if (base_str)
      free(base_str);
# endif
}
Beispiel #3
0
/**
 * @internal
 * Find the end of a run according to font coverage, and return the base script
 * font and the current wanted font.
 *
 * @param[in] fn the font to use.
 * @param script_fi The base font instance to be used with the script. If NULL, then it's calculated and returned in this variable, if not NULL, it's used and not modified.
 * @param[out] cur_fi The font instance found for the current run.
 * @param[in] script the base script
 * @param[in] text the text to work on.
 * @param[in] run_let the current run len, i.e "search limit".
 * @return length of the run found.
 */
EAPI int
evas_common_font_query_run_font_end_get(RGBA_Font *fn, RGBA_Font_Int **script_fi, RGBA_Font_Int **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len)
{
   RGBA_Font_Int *fi = NULL;
   const Eina_Unicode *run_end = text + run_len;
   const Eina_Unicode *itr;

   /* If there's no current script_fi, find it first */
   if (!*script_fi)
     {
        const Eina_Unicode *base_char = NULL;
        /* Skip common chars */
        for (base_char = text ;
             (base_char < run_end) &&
             (evas_common_language_char_script_get(*base_char) != script) ;
             base_char++)
           ;
        if (base_char == run_end) base_char = text;

        /* Find the first renderable char */
        while (base_char < run_end)
          {
             /* 0x1F is the last ASCII contral char, just a hack in
              * the meanwhile. */
             if ((*base_char > 0x1F) &&
                   evas_common_font_glyph_search(fn, &fi, *base_char))
                break;
             base_char++;
          }


        /* If everything else fails, at least try to find a font for the
         * replacement char */
        if (base_char == run_end)
           evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);

        if (!fi)
           fi = fn->fonts->data;

        *script_fi = fi;
     }
   else
     {
        fi = *script_fi;
     }

   /* Find the longest run of the same font starting from the start position
    * and update cur_fi accordingly. */
   itr = text;
   while (itr < run_end)
     {
        RGBA_Font_Int *tmp_fi;
        /* Itr will end up being the first of the next run  */
        for ( ; itr < run_end ; itr++)
          {
             /* 0x1F is the last ASCII contral char, just a hack in
              * the meanwhile. */
             if (*itr <= 0x1F)
                continue;
             /* Break if either it's not in the font, or if it is in the
              * script's font. */
             if (!evas_common_get_char_index(fi, *itr))
                break;

             if (fi != *script_fi)
               {
                  if (evas_common_get_char_index(*script_fi, *itr))
                     break;
               }
          }

        /* Abort if we reached the end */
        if (itr == run_end)
           break;

        /* If the script font doesn't fit even one char, find a new font. */
        if (itr == text)
          {
             /* If we can find a font, use it. Otherwise, find the first
              * char the run of chars that can't be rendered until the first
              * one that can. */
             if (evas_common_font_glyph_search(fn, &tmp_fi, *itr))
               {
                  fi = tmp_fi;
               }
             else
               {
                  itr++;
                  /* Go through all the chars that can't be rendered with any
                   * font */
                  for ( ; itr < run_end ; itr++)
                    {
                       tmp_fi = fi;
                       if (evas_common_get_char_index(fi, *itr) ||
                             evas_common_font_glyph_search(fn, &tmp_fi, *itr))
                         {
                            fi = tmp_fi;
                            break;
                         }
                    }

                  /* If we found a renderable character and the found font
                   * can render the replacement char, continue, otherwise
                   * find a font most suitable for the replacement char and
                   * break */
                  if ((itr == run_end) ||
                        !evas_common_get_char_index(fi, REPLACEMENT_CHAR))
                    {
                       evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR);
                       break;
                    }
               }
             itr++;
          }
        else
          {
             /* If this char is not renderable by any font, but the replacement
              * char can be rendered using the currentfont, continue this
              * run. */
             if (!evas_common_font_glyph_search(fn, &tmp_fi, *itr) &&
                   evas_common_get_char_index(fi, REPLACEMENT_CHAR))
               {
                  itr++;
               }
             else
               {
                  /* Done, we did as much as possible */
                  break;
               }
          }
     }

   if (fi)
      *cur_fi = fi;
   else
      *cur_fi = *script_fi;

   return itr - text;
}
Beispiel #4
0
static inline void
_content_create_ot(RGBA_Font_Int *fi, const Eina_Unicode *text,
      Evas_Text_Props *text_props, int len, Evas_Text_Props_Mode mode)
{
   size_t char_index;
   Evas_Font_Glyph_Info *gl_itr;
   Evas_Coord pen_x = 0, adjust_x = 0;

   evas_common_font_ot_populate_text_props(text, text_props, len, mode);

   gl_itr = text_props->info->glyph;
   for (char_index = 0 ; char_index < text_props->len ; char_index++)
     {
        FT_UInt idx;
        RGBA_Font_Glyph *fg;
        Eina_Bool is_replacement = EINA_FALSE;
        /* If we got a malformed index, show the replacement char instead */
        if (gl_itr->index == 0)
          {
             gl_itr->index = evas_common_get_char_index(fi, REPLACEMENT_CHAR);
             is_replacement = EINA_TRUE;
          }
        idx = gl_itr->index;
        LKL(fi->ft_mutex);
        fg = evas_common_font_int_cache_glyph_get(fi, idx);
        if (!fg)
          {
             LKU(fi->ft_mutex);
             continue;
          }
        LKU(fi->ft_mutex);

        gl_itr->x_bear = fg->x_bear;
        gl_itr->y_bear = fg->y_bear;
        gl_itr->width = fg->width;
        /* text_props->info->glyph[char_index].advance =
         * text_props->info->glyph[char_index].index =
         * already done by the ot function */
        if (EVAS_FONT_CHARACTER_IS_INVISIBLE(
              text[text_props->info->ot[char_index].source_cluster]))
          {
             gl_itr->index = 0;
             /* Reduce the current advance */
             if (gl_itr > text_props->info->glyph)
               {
                  adjust_x -= gl_itr->pen_after - (gl_itr - 1)->pen_after;
               }
             else
               {
                  adjust_x -= gl_itr->pen_after;
               }
          }
        else
          {
             if (is_replacement)
               {
                  /* Update the advance accordingly */
                  adjust_x += (pen_x + (fg->glyph->advance.x >> 16)) -
                     gl_itr->pen_after;
               }
             pen_x = gl_itr->pen_after;
          }
        gl_itr->pen_after += adjust_x;

        fi = text_props->font_instance;
        gl_itr++;
     }
}