Function: composition-get-gstring

composition-get-gstring is a function defined in composite.c.

Signature

(composition-get-gstring FROM TO FONT-OBJECT STRING)

Documentation

Return a glyph-string for characters between FROM and TO.

If the glyph string is for graphic display, FONT-OBJECT must be a font-object to use for those characters. Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a frame, or nil for the selected frame's terminal device.

If the optional 4th argument STRING is not nil, it is a string containing the target characters between indices FROM and TO, which are treated as in substring. Otherwise FROM and TO are character positions in current buffer; they can be in either order, and can be integers or markers.

A glyph-string is a vector containing information about how to display a specific character sequence. The format is:
   [HEADER ID GLYPH ...]

HEADER is a vector of this form:
    [FONT-OBJECT CHAR ...]
where
    FONT-OBJECT is a font-object for all glyphs in the glyph-string,
    or the terminal coding system of the specified terminal.
    CHARs are characters to be composed by GLYPHs.

ID is an identification number of the glyph-string. It may be nil if not yet shaped.

GLYPH is a vector whose elements have this form:
    [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
      [ [X-OFF Y-OFF WADJUST] | nil] ]
where
    FROM-IDX and TO-IDX are used internally and should not be touched.
    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.
    X-OFF and Y-OFF are offsets to the base position for the glyph.
    WADJUST is the adjustment to the normal width of the glyph.

If GLYPH is nil, the remaining elements of the glyph-string vector should be ignored.

Source Code

// Defined in /usr/src/emacs/src/composite.c
{
  Lisp_Object gstring, header;
  ptrdiff_t frompos, frombyte, topos;

  if (! FONT_OBJECT_P (font_object))
    {
      struct coding_system *coding;
      struct terminal *terminal = decode_live_terminal (font_object);

      coding = ((TERMINAL_TERMINAL_CODING (terminal)->common_flags
		 & CODING_REQUIRE_ENCODING_MASK)
		? TERMINAL_TERMINAL_CODING (terminal) : &safe_terminal_coding);
      font_object = CODING_ID_NAME (coding->id);
    }

  if (NILP (string))
    {
      if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
	error ("Attempt to shape unibyte text");
      validate_region (&from, &to);
      frompos = XFIXNAT (from);
      topos = XFIXNAT (to);
      frombyte = CHAR_TO_BYTE (frompos);
    }
  else
    {
      CHECK_STRING (string);
      ptrdiff_t chars = SCHARS (string);
      validate_subarray (string, from, to, chars, &frompos, &topos);
      if (! STRING_MULTIBYTE (string))
	{
	  ptrdiff_t i;

	  for (i = SBYTES (string) - 1; i >= 0; i--)
	    if (!ASCII_CHAR_P (SREF (string, i)))
	      error ("Attempt to shape unibyte text");
	  /* STRING is a pure-ASCII string, so we can convert it (or,
	     rather, its copy) to multibyte and use that thereafter.  */
	  /* FIXME: Not clear why we need to do that: AFAICT the rest of
             the code should work on an ASCII-only unibyte string just
             as well (bug#56347).  */
	  string = make_multibyte_string (SSDATA (string), chars, chars);
	}
      frombyte = string_char_to_byte (string, frompos);
    }

  header = fill_gstring_header (frompos, frombyte,
				topos, font_object, string);
  gstring = composition_gstring_lookup_cache (header);
  if (! NILP (gstring))
    return gstring;

  if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
    gstring_work = make_nil_vector (topos - frompos + 2);
  LGSTRING_SET_HEADER (gstring_work, header);
  LGSTRING_SET_ID (gstring_work, Qnil);
  fill_gstring_body (gstring_work);
  return gstring_work;
}