Function: font-shape-gstring

font-shape-gstring is a function defined in font.c.

Signature

(font-shape-gstring GSTRING DIRECTION)

Documentation

Shape the glyph-string GSTRING subject to bidi DIRECTION.

Shaping means substituting glyphs and/or adjusting positions of glyphs to get the correct visual image of character sequences set in the header of the glyph-string.

DIRECTION should be produced by the UBA, the Unicode Bidirectional Algorithm, and should be a symbol, either L2R or R2L. It can also be nil if the bidi context is unknown.

If the shaping was successful, the value is GSTRING itself or a newly created glyph-string. Otherwise, the value is nil.

See the documentation of composition-get-gstring for the format of GSTRING.

Source Code

// Defined in /usr/src/emacs/src/font.c
{
  struct font *font;
  Lisp_Object font_object, n, glyph;
  ptrdiff_t i, from, to;

  if (! composition_gstring_p (gstring))
    signal_error ("Invalid glyph-string: ", gstring);
  if (! NILP (LGSTRING_ID (gstring)))
    return gstring;
  Lisp_Object cached_gstring =
    composition_gstring_lookup_cache (LGSTRING_HEADER (gstring));
  if (! NILP (cached_gstring))
    return cached_gstring;
  font_object = LGSTRING_FONT (gstring);
  CHECK_FONT_OBJECT (font_object);
  font = XFONT_OBJECT (font_object);
  if (! font->driver->shape)
    return Qnil;

  /* Try at most three times with larger gstring each time.  */
  for (i = 0; i < 3; i++)
    {
      n = font->driver->shape (gstring, direction);
      if (FIXNUMP (n))
	break;
      gstring = larger_vector (gstring,
			       LGSTRING_GLYPH_LEN (gstring), -1);
    }
  if (i == 3 || XFIXNUM (n) == 0)
    return Qnil;
  if (XFIXNUM (n) < LGSTRING_GLYPH_LEN (gstring))
    LGSTRING_SET_GLYPH (gstring, XFIXNUM (n), Qnil);

  /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
     GLYPHS covers all characters (except for the last few ones) in
     GSTRING.  More formally, provided that NCHARS is the number of
     characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
     and TO_IDX of each glyph must satisfy these conditions:

       GLYPHS[0].FROM_IDX == 0
       GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
       if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
         ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
         GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
       else
         ;; Be sure to cover all characters.
         GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
  glyph = LGSTRING_GLYPH (gstring, 0);
  from = LGLYPH_FROM (glyph);
  to = LGLYPH_TO (glyph);
  if (from != 0 || to < from)
    goto shaper_error;
  for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
    {
      glyph = LGSTRING_GLYPH (gstring, i);
      if (NILP (glyph))
	break;
      if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
	     && (LGLYPH_FROM (glyph) == from
		 ? LGLYPH_TO (glyph) == to
		 : LGLYPH_FROM (glyph) == to + 1)))
	goto shaper_error;
      from = LGLYPH_FROM (glyph);
      to = LGLYPH_TO (glyph);
    }
  composition_gstring_adjust_zero_width (gstring);
  return composition_gstring_put_cache (gstring, XFIXNUM (n));

 shaper_error:
  return Qnil;
}