From 40fb53d66732a8fb4fd2e7d05b57ea3fa92a9c7c Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Tue, 25 Dec 2007 10:36:06 +0000 Subject: [PATCH] (Ffont_fill_gstring): Stop filling when a character not supported by the font is found. (Ffont_shape_text): When a shape callback function returns nil, try at most two more times with larger gstring. (Ffont_at): Fix getting of w. Call font_at with correct 5th argument. --- src/font.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/font.c b/src/font.c index 10dce4764a2..8347a0d5b23 100644 --- a/src/font.c +++ b/src/font.c @@ -3496,8 +3496,8 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */) c = STRING_CHAR_ADVANCE (p); code = font->driver->encode_char (font, c); - if (code > MOST_POSITIVE_FIXNUM) - error ("Glyph code 0x%X is too large", code); + if (code > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE) + break; LGLYPH_SET_FROM (g, i); LGLYPH_SET_TO (g, i); LGLYPH_SET_CHAR (g, c); @@ -3522,15 +3522,15 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */) FETCH_CHAR_ADVANCE (c, pos, pos_byte); code = font->driver->encode_char (font, c); - if (code > MOST_POSITIVE_FIXNUM) - error ("Glyph code 0x%X is too large", code); + if (code > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE) + break; LGLYPH_SET_FROM (g, i); LGLYPH_SET_TO (g, i); LGLYPH_SET_CHAR (g, c); LGLYPH_SET_CODE (g, code); } } - for (i = LGSTRING_LENGTH (gstring) - 1; i >= len; i--) + for (; i < LGSTRING_LENGTH (gstring); i++) LGSTRING_SET_GLYPH (gstring, i, Qnil); return Qnil; } @@ -3539,7 +3539,8 @@ DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0, doc: /* Shape text between FROM and TO by FONT-OBJECT. If optional 4th argument STRING is non-nil, it is a string to shape, and FROM and TO are indices to the string. -The value is the end position of the shaped text. */) +The value is the end position of the text that can be shaped by +FONT-OBJECT. */) (from, to, font_object, string) Lisp_Object from, to, font_object, string; { @@ -3547,7 +3548,7 @@ The value is the end position of the shaped text. */) struct font_metrics metrics; EMACS_INT start, end; Lisp_Object gstring, n; - int i; + int len, i, j; if (NILP (string)) { @@ -3569,12 +3570,27 @@ The value is the end position of the shaped text. */) if (! font->driver->shape) return from; - gstring = Ffont_make_gstring (font_object, make_number (end - start)); + len = end - start; + gstring = Ffont_make_gstring (font_object, make_number (len)); Ffont_fill_gstring (gstring, font_object, from, to, string); - n = font->driver->shape (gstring); - if (NILP (n)) + + /* Try at most three times with larger gstring each time. */ + for (i = 0; i < 3; i++) + { + Lisp_Object args[2]; + + n = font->driver->shape (gstring); + if (INTEGERP (n)) + break; + args[0] = gstring; + args[1] = Fmake_vector (make_number (len), Qnil); + gstring = Fvconcat (2, args); + } + if (! INTEGERP (n) || XINT (n) == 0) return Qnil; - for (i = 0; i < XINT (n);) + len = XINT (n); + + for (i = 0; i < len;) { Lisp_Object gstr; Lisp_Object g = LGSTRING_GLYPH (gstring, i); @@ -3602,7 +3618,7 @@ The value is the end position of the shaped text. */) metrics.descent += LGLYPH_YOFF (g); need_composition = 1; } - for (j = i + 1; j < XINT (n); j++) + for (j = i + 1; j < len; j++) { int x; @@ -3970,9 +3986,9 @@ the current buffer. It defaults to the currently selected window. */) if (NILP (window)) window = selected_window; CHECK_LIVE_WINDOW (window); - w = XWINDOW (selected_window); + w = XWINDOW (window); - return font_at (-1, pos, NULL, w, Qnil); + return font_at (-1, pos, NULL, w, string); } #if 0 -- 2.39.5