Function: font-get-glyphs

font-get-glyphs is a function defined in font.c.

Signature

(font-get-glyphs FONT-OBJECT FROM TO &optional OBJECT)

Documentation

Return a vector of FONT-OBJECT's glyphs for the specified characters.

FROM and TO are positions (integers or markers) specifying a region of the current buffer, and can be in either order. If the optional fourth arg OBJECT is not nil, it is a string or a vector containing the target characters between indices FROM and TO, which are treated as in substring.

Each element is a vector containing information of a glyph in this format:
  [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
where
  FROM is an index numbers of a character the glyph corresponds to.
  TO is the same as FROM.
  C is the character of the glyph.
  CODE is the glyph-code of C in FONT-OBJECT.
  WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
  ADJUSTMENT is always nil.

If FONT-OBJECT doesn't have a glyph for a character, the corresponding element is nil.

Also see font-has-char-p, which is more efficient than this function if you just want to check whether FONT-OBJECT has a glyph for a character.

Source Code

// Defined in /usr/src/emacs/src/font.c
{
  struct font *font = CHECK_FONT_GET_OBJECT (font_object);
  ptrdiff_t len;
  Lisp_Object *chars;
  USE_SAFE_ALLOCA;

  if (NILP (object))
    {
      ptrdiff_t charpos, bytepos;

      validate_region (&from, &to);
      if (EQ (from, to))
	return Qnil;
      len = XFIXNAT (to) - XFIXNAT (from);
      SAFE_ALLOCA_LISP (chars, len);
      charpos = XFIXNAT (from);
      bytepos = CHAR_TO_BYTE (charpos);
      for (ptrdiff_t i = 0; charpos < XFIXNAT (to); i++)
	{
	  int c = fetch_char_advance (&charpos, &bytepos);
	  chars[i] = make_fixnum (c);
	}
    }
  else if (STRINGP (object))
    {
      const unsigned char *p;
      ptrdiff_t ifrom, ito;

      validate_subarray (object, from, to, SCHARS (object), &ifrom, &ito);
      if (ifrom == ito)
	return Qnil;
      len = ito - ifrom;
      SAFE_ALLOCA_LISP (chars, len);
      p = SDATA (object);
      if (STRING_MULTIBYTE (object))
	{
	  int c;

	  /* Skip IFROM characters from the beginning.  */
	  for (ptrdiff_t i = 0; i < ifrom; i++)
	    p += BYTES_BY_CHAR_HEAD (*p);

	  /* Now fetch an interesting characters.  */
	  for (ptrdiff_t i = 0; i < len; i++)
	    {
	      c = string_char_advance (&p);
	      chars[i] = make_fixnum (c);
	    }
	}
      else
	for (ptrdiff_t i = 0; i < len; i++)
	  chars[i] = make_fixnum (p[ifrom + i]);
    }
  else if (VECTORP (object))
    {
      ptrdiff_t ifrom, ito;

      validate_subarray (object, from, to, ASIZE (object), &ifrom, &ito);
      if (ifrom == ito)
	return Qnil;
      len = ito - ifrom;
      for (ptrdiff_t i = 0; i < len; i++)
	{
	  Lisp_Object elt = AREF (object, ifrom + i);
	  CHECK_CHARACTER (elt);
	}
      chars = aref_addr (object, ifrom);
    }
  else
    wrong_type_argument (Qarrayp, object);

  Lisp_Object vec = make_nil_vector (len);
  for (ptrdiff_t i = 0; i < len; i++)
    {
      Lisp_Object g;
      int c = XFIXNAT (chars[i]);
      unsigned code;
      struct font_metrics metrics;

      code = font->driver->encode_char (font, c);
      if (code == FONT_INVALID_CODE)
	{
	  ASET (vec, i, Qnil);
	  continue;
	}
      g = LGLYPH_NEW ();
      LGLYPH_SET_FROM (g, i);
      LGLYPH_SET_TO (g, i);
      LGLYPH_SET_CHAR (g, c);
      LGLYPH_SET_CODE (g, code);
      font->driver->text_extents (font, &code, 1, &metrics);
      LGLYPH_SET_WIDTH (g, metrics.width);
      LGLYPH_SET_LBEARING (g, metrics.lbearing);
      LGLYPH_SET_RBEARING (g, metrics.rbearing);
      LGLYPH_SET_ASCENT (g, metrics.ascent);
      LGLYPH_SET_DESCENT (g, metrics.descent);
      ASET (vec, i, g);
    }
  if (! VECTORP (object))
    SAFE_FREE ();
  return vec;
}