#include "nsterm.h"
#endif /* HAVE_NS */
-#ifdef MAC_OS
-#include "macterm.h"
-#endif /* MAC_OS */
-
Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
#ifdef HAVE_NS
#define DEFAULT_ENCODING Qiso8859_1
#endif
+/* Unicode category `Cf'. */
+static Lisp_Object QCf;
+
/* Special vector of zero length. This is repeatedly used by (struct
font_driver *)->list when a specified font is not found. */
static Lisp_Object null_vector;
if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
- for (i = 0; i < LGSTRING_LENGTH (gstring); i++)
+ for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
{
val = LGSTRING_GLYPH (gstring, i);
CHECK_VECTOR (val);
#endif /* HAVE_LIBOTF */
#endif /* 0 */
-/* G-string (glyph string) handler */
-
-/* G-string is a vector of the form [HEADER GLYPH ...].
- See the docstring of `font-make-gstring' for more detail. */
-
-struct font *
-font_prepare_composition (cmp, f)
- struct composition *cmp;
- FRAME_PTR f;
-{
- Lisp_Object gstring
- = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
- cmp->hash_index * 2);
-
- cmp->font = XFONT_OBJECT (LGSTRING_FONT (gstring));
- cmp->glyph_len = LGSTRING_LENGTH (gstring);
- cmp->pixel_width = LGSTRING_WIDTH (gstring);
- cmp->lbearing = LGSTRING_LBEARING (gstring);
- cmp->rbearing = LGSTRING_RBEARING (gstring);
- cmp->ascent = LGSTRING_ASCENT (gstring);
- cmp->descent = LGSTRING_DESCENT (gstring);
- cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f);
- if (cmp->width == 0)
- cmp->width = 1;
-
- return cmp->font;
-}
-
\f
/* Font sorting */
foundry[1] = null_vector;
else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
{
- foundry[0] = font_intern_prop (SDATA (attrs[LFACE_FOUNDRY_INDEX]),
- SBYTES (attrs[LFACE_FOUNDRY_INDEX]), 1);
+ val = attrs[LFACE_FOUNDRY_INDEX];
+ foundry[0] = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
foundry[1] = Qnil;
foundry[2] = null_vector;
}
val = AREF (work, FONT_FAMILY_INDEX);
if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
- val = font_intern_prop (SDATA (attrs[LFACE_FAMILY_INDEX]),
- SBYTES (attrs[LFACE_FAMILY_INDEX]), 1);
+ {
+ val = attrs[LFACE_FAMILY_INDEX];
+ val = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
+ }
if (NILP (val))
{
family = alloca ((sizeof family[0]) * 2);
}
-/* Check how many characters after POS (at most to LIMIT) can be
- displayed by the same font. FACE is the face selected for the
- character as POS on frame F. STRING, if not nil, is the string to
- check instead of the current buffer.
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Check how many characters after POS (at most to *LIMIT) can be
+ displayed by the same font on the window W. FACE, if non-NULL, is
+ the face selected for the character at POS. If STRING is not nil,
+ it is the string to check instead of the current buffer. In that
+ case, FACE must be not NULL.
+
+ The return value is the font-object for the character at POS.
+ *LIMIT is set to the position where that font can't be used.
- The return value is the position of the character that is displayed
- by the differnt font than that of the character as POS. */
+ It is assured that the current buffer (or STRING) is multibyte. */
-EMACS_INT
-font_range (pos, limit, face, f, string)
- EMACS_INT pos, limit;
+Lisp_Object
+font_range (pos, limit, w, face, string)
+ EMACS_INT pos, *limit;
+ struct window *w;
struct face *face;
- FRAME_PTR f;
Lisp_Object string;
{
- int multibyte;
- EMACS_INT pos_byte;
+ EMACS_INT pos_byte, ignore, start, start_byte;
int c;
- struct font *font;
- int first = 1;
+ Lisp_Object font_object = Qnil;
if (NILP (string))
{
- multibyte = ! NILP (current_buffer->enable_multibyte_characters);
pos_byte = CHAR_TO_BYTE (pos);
+ if (! face)
+ {
+ int face_id;
+
+ face_id = face_at_buffer_position (w, pos, 0, 0, &ignore, *limit, 0);
+ face = FACE_FROM_ID (XFRAME (w->frame), face_id);
+ }
}
else
{
- multibyte = STRING_MULTIBYTE (string);
+ font_assert (face);
pos_byte = string_char_to_byte (string, pos);
}
- if (! multibyte)
- /* All unibyte character are displayed by the same font. */
- return limit;
-
- while (pos < limit)
+ start = pos, start_byte = pos_byte;
+ while (pos < *limit)
{
- int face_id;
+ Lisp_Object category;
if (NILP (string))
FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
else
FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
- face_id = FACE_FOR_CHAR (f, face, c, pos, string);
- face = FACE_FROM_ID (f, face_id);
- if (first)
+ if (NILP (font_object))
{
- font = face->font;
- first = 0;
+ font_object = font_for_char (face, c, pos - 1, string);
+ if (NILP (font_object))
+ return Qnil;
continue;
}
- else if (font != face->font)
+
+ category = CHAR_TABLE_REF (Vunicode_category_table, c);
+ if (! EQ (category, QCf)
+ && font_encode_char (font_object, c) == FONT_INVALID_CODE)
{
- pos--;
- break;
+ Lisp_Object f = font_for_char (face, c, pos - 1, string);
+ EMACS_INT i, i_byte;
+
+
+ if (NILP (f))
+ {
+ *limit = pos - 1;
+ return font_object;
+ }
+ i = start, i_byte = start_byte;
+ while (i < pos - 1)
+ {
+
+ if (NILP (string))
+ FETCH_CHAR_ADVANCE_NO_CHECK (c, i, i_byte);
+ else
+ FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, i, i_byte);
+ category = CHAR_TABLE_REF (Vunicode_category_table, c);
+ if (! EQ (category, QCf)
+ && font_encode_char (f, c) == FONT_INVALID_CODE)
+ {
+ *limit = pos - 1;
+ return font_object;
+ }
+ }
+ font_object = f;
}
}
- return pos;
+ return font_object;
}
+#endif
\f
/* Lisp API */
return Qnil;
}
-/* The following three functions are still experimental. */
-
-DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
- doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
-FONT-OBJECT may be nil if it is not yet known.
-
-G-string is sequence of glyphs of a specific font,
-and is a vector of this form:
- [ HEADER GLYPH ... ]
-HEADER is a vector of this form:
- [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
-where
- FONT-OBJECT is a font-object for all glyphs in the g-string,
- WIDTH thru DESCENT are the metrics (in pixels) of the whole G-string.
-GLYPH is a vector of 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 offests to the base position for the glyph.
- WADJUST is the adjustment to the normal width of the glyph. */)
- (font_object, num)
- Lisp_Object font_object, num;
-{
- Lisp_Object gstring, g;
- int len;
- int i;
-
- if (! NILP (font_object))
- CHECK_FONT_OBJECT (font_object);
- CHECK_NATNUM (num);
-
- len = XINT (num) + 1;
- gstring = Fmake_vector (make_number (len), Qnil);
- g = Fmake_vector (make_number (6), Qnil);
- ASET (g, 0, font_object);
- ASET (gstring, 0, g);
- for (i = 1; i < len; i++)
- ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
- return gstring;
-}
-
-DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
- doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
-START and END specify the region to extract characters.
-If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
-where to extract characters.
-FONT-OBJECT may be nil if GSTRING already contains one. */)
- (gstring, font_object, start, end, object)
- Lisp_Object gstring, font_object, start, end, object;
+\f
+void
+font_fill_lglyph_metrics (glyph, font_object)
+ Lisp_Object glyph, font_object;
{
- int len, i, c;
+ struct font *font = XFONT_OBJECT (font_object);
unsigned code;
- struct font *font;
-
- CHECK_VECTOR (gstring);
- if (NILP (font_object))
- font_object = LGSTRING_FONT (gstring);
- font = XFONT_OBJECT (font_object);
-
- if (STRINGP (object))
- {
- const unsigned char *p;
+ /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
+ EMACS_INT ecode = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
+ struct font_metrics metrics;
- CHECK_NATNUM (start);
- CHECK_NATNUM (end);
- if (XINT (start) > XINT (end)
- || XINT (end) > ASIZE (object)
- || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
- args_out_of_range_3 (object, start, end);
+ LGLYPH_SET_CODE (glyph, ecode);
+ code = ecode;
+ font->driver->text_extents (font, &code, 1, &metrics);
+ LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
+ LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
+ LGLYPH_SET_WIDTH (glyph, metrics.width);
+ LGLYPH_SET_ASCENT (glyph, metrics.ascent);
+ LGLYPH_SET_DESCENT (glyph, metrics.descent);
+}
- len = XINT (end) - XINT (start);
- p = SDATA (object) + string_char_to_byte (object, XINT (start));
- for (i = 0; i < len; i++)
- {
- Lisp_Object g = LGSTRING_GLYPH (gstring, i);
- /* Shut up GCC warning in comparison with
- MOST_POSITIVE_FIXNUM below. */
- EMACS_INT cod;
-
- c = STRING_CHAR_ADVANCE (p);
- cod = code = font->driver->encode_char (font, c);
- if (cod > 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);
- }
- }
- else
- {
- int pos, pos_byte;
- if (! NILP (object))
- Fset_buffer (object);
- validate_region (&start, &end);
- if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
- args_out_of_range (start, end);
- len = XINT (end) - XINT (start);
- pos = XINT (start);
- pos_byte = CHAR_TO_BYTE (pos);
- for (i = 0; i < len; i++)
- {
- Lisp_Object g = LGSTRING_GLYPH (gstring, i);
- /* Shut up GCC warning in comparison with
- MOST_POSITIVE_FIXNUM below. */
- EMACS_INT cod;
-
- FETCH_CHAR_ADVANCE (c, pos, pos_byte);
- cod = code = font->driver->encode_char (font, c);
- if (cod > 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); i++)
- LGSTRING_SET_GLYPH (gstring, i, Qnil);
- return Qnil;
-}
+DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
+ doc: /* Shape the glyph-string GSTRING.
+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.
-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 text that can be shaped by
-FONT-OBJECT. */)
- (from, to, font_object, string)
- Lisp_Object from, to, font_object, string;
+If the shaping was successful, the value is GSTRING itself or a newly
+created glyph-string. Otherwise, the value is nil. */)
+ (gstring)
+ Lisp_Object gstring;
{
struct font *font;
- struct font_metrics metrics;
- EMACS_INT start, end;
- Lisp_Object gstring, n;
- int len, i;
-
- if (! FONT_OBJECT_P (font_object))
- return Qnil;
+ Lisp_Object font_object, n, glyph;
+ int i, j, from, to;
+
+ if (! composition_gstring_p (gstring))
+ signal_error ("Invalid glyph-string: ", gstring);
+ if (! NILP (LGSTRING_ID (gstring)))
+ return gstring;
+ font_object = LGSTRING_FONT (gstring);
+ CHECK_FONT_OBJECT (font_object);
font = XFONT_OBJECT (font_object);
if (! font->driver->shape)
return Qnil;
- if (NILP (string))
- {
- validate_region (&from, &to);
- start = XFASTINT (from);
- end = XFASTINT (to);
- modify_region (current_buffer, start, end, 0);
- }
- else
- {
- CHECK_STRING (string);
- start = XINT (from);
- end = XINT (to);
- if (start < 0 || start > end || end > SCHARS (string))
- args_out_of_range_3 (string, from, to);
- }
-
- len = end - start;
- gstring = Ffont_make_gstring (font_object, make_number (len));
- Ffont_fill_gstring (gstring, font_object, from, to, string);
-
/* 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);
+ gstring = larger_vector (gstring,
+ ASIZE (gstring) + LGSTRING_GLYPH_LEN (gstring),
+ Qnil);
}
- if (! INTEGERP (n) || XINT (n) == 0)
+ if (i == 3 || XINT (n) == 0)
return Qnil;
- len = XINT (n);
-
- for (i = 0; i < len;)
- {
- Lisp_Object gstr;
- Lisp_Object g = LGSTRING_GLYPH (gstring, i);
- EMACS_INT this_from = LGLYPH_FROM (g);
- EMACS_INT this_to = LGLYPH_TO (g) + 1;
- int j, k;
- int need_composition = 0;
-
- metrics.lbearing = LGLYPH_LBEARING (g);
- metrics.rbearing = LGLYPH_RBEARING (g);
- metrics.ascent = LGLYPH_ASCENT (g);
- metrics.descent = LGLYPH_DESCENT (g);
- if (NILP (LGLYPH_ADJUSTMENT (g)))
+
+ glyph = LGSTRING_GLYPH (gstring, 0);
+ from = LGLYPH_FROM (glyph);
+ to = LGLYPH_TO (glyph);
+ for (i = 1, j = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
+ {
+ Lisp_Object this = LGSTRING_GLYPH (gstring, i);
+
+ if (NILP (this))
+ break;
+ if (NILP (LGLYPH_ADJUSTMENT (this)))
{
- metrics.width = LGLYPH_WIDTH (g);
- if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
- need_composition = 1;
+ if (j < i - 1)
+ for (; j < i; j++)
+ {
+ glyph = LGSTRING_GLYPH (gstring, j);
+ LGLYPH_SET_FROM (glyph, from);
+ LGLYPH_SET_TO (glyph, to);
+ }
+ from = LGLYPH_FROM (this);
+ to = LGLYPH_TO (this);
+ j = i;
}
else
{
- metrics.width = LGLYPH_WADJUST (g);
- metrics.lbearing += LGLYPH_XOFF (g);
- metrics.rbearing += LGLYPH_XOFF (g);
- metrics.ascent -= LGLYPH_YOFF (g);
- metrics.descent += LGLYPH_YOFF (g);
- need_composition = 1;
- }
- for (j = i + 1; j < len; j++)
- {
- int x;
-
- g = LGSTRING_GLYPH (gstring, j);
- if (this_from != LGLYPH_FROM (g))
- break;
- need_composition = 1;
- x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
- if (metrics.lbearing > x)
- metrics.lbearing = x;
- x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
- if (metrics.rbearing < x)
- metrics.rbearing = x;
- x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
- if (metrics.ascent < x)
- metrics.ascent = x;
- x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
- if (metrics.descent < x)
- metrics.descent = x;
- if (NILP (LGLYPH_ADJUSTMENT (g)))
- metrics.width += LGLYPH_WIDTH (g);
- else
- metrics.width += LGLYPH_WADJUST (g);
+ if (from > LGLYPH_FROM (this))
+ from = LGLYPH_FROM (this);
+ if (to < LGLYPH_TO (this))
+ to = LGLYPH_TO (this);
}
-
- if (need_composition)
- {
- gstr = Ffont_make_gstring (font_object, make_number (j - i));
- LGSTRING_SET_WIDTH (gstr, metrics.width);
- LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
- LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
- LGSTRING_SET_ASCENT (gstr, metrics.ascent);
- LGSTRING_SET_DESCENT (gstr, metrics.descent);
- for (k = i; i < j; i++)
- {
- Lisp_Object g = LGSTRING_GLYPH (gstring, i);
-
- LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
- LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
- LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
- }
- from = make_number (start + this_from);
- to = make_number (start + this_to);
- if (NILP (string))
- Fcompose_region_internal (from, to, gstr, Qnil);
- else
- Fcompose_string_internal (string, from, to, gstr, Qnil);
- }
- else
- i = j;
}
-
- return to;
+ if (j < i - 1)
+ for (; j < i; j++)
+ {
+ glyph = LGSTRING_GLYPH (gstring, j);
+ LGLYPH_SET_FROM (glyph, from);
+ LGLYPH_SET_TO (glyph, to);
+ }
+ return composition_gstring_put_cache (gstring, XINT (n));
}
#if 0
static Lisp_Object Vfont_log;
static int font_log_env_checked;
+/* The deferred font-log data of the form [ACTION ARG RESULT].
+ If ACTION is not nil, that is added to the log when font_add_log is
+ called next time. At that time, ACTION is set back to nil. */
+static Lisp_Object Vfont_log_deferred;
+
+/* Prepend the font-related logging data in Vfont_log if it is not
+ `t'. ACTION describes a kind of font-related action (e.g. listing,
+ opening), ARG is the argument for the action, and RESULT is the
+ result of the action. */
void
font_add_log (action, arg, result)
char *action;
}
if (EQ (Vfont_log, Qt))
return;
+ if (STRINGP (AREF (Vfont_log_deferred, 0)))
+ {
+ char *str = (char *) SDATA (AREF (Vfont_log_deferred, 0));
+
+ ASET (Vfont_log_deferred, 0, Qnil);
+ font_add_log (str, AREF (Vfont_log_deferred, 1),
+ AREF (Vfont_log_deferred, 2));
+ }
+
if (FONTP (arg))
- arg = Ffont_xlfd_name (arg, Qt);
+ {
+ Lisp_Object tail, elt;
+ Lisp_Object equalstr = build_string ("=");
+
+ val = Ffont_xlfd_name (arg, Qt);
+ for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
+ tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ if (EQ (XCAR (elt), QCscript))
+ val = concat3 (val, SYMBOL_NAME (QCscript),
+ concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
+ else if (EQ (XCAR (elt), QClang))
+ val = concat3 (val, SYMBOL_NAME (QClang),
+ concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
+ else if (EQ (XCAR (elt), QCotf) && CONSP (XCDR (elt)))
+ val = concat3 (val, SYMBOL_NAME (QCotf),
+ concat2 (equalstr,
+ SYMBOL_NAME (XCAR (XCDR (elt)))));
+ }
+ arg = val;
+ }
if (FONTP (result))
{
val = Ffont_xlfd_name (result, Qt);
Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
}
+/* Record a font-related logging data to be added to Vfont_log when
+ font_add_log is called next time. ACTION, ARG, RESULT are the same
+ as font_add_log. */
+
+void
+font_deferred_log (action, arg, result)
+ char *action;
+ Lisp_Object arg, result;
+{
+ ASET (Vfont_log_deferred, 0, build_string (action));
+ ASET (Vfont_log_deferred, 1, arg);
+ ASET (Vfont_log_deferred, 2, result);
+}
+
extern void syms_of_ftfont P_ (());
extern void syms_of_xfont P_ (());
extern void syms_of_xftfont P_ (());
DEFSYM (Qunicode_bmp, "unicode-bmp");
DEFSYM (Qunicode_sip, "unicode-sip");
+ DEFSYM (QCf, "Cf");
+
DEFSYM (QCotf, ":otf");
DEFSYM (QClang, ":lang");
DEFSYM (QCscript, ":script");
staticpro (&scratch_font_prefer);
scratch_font_prefer = Ffont_spec (0, NULL);
+ staticpro (&Vfont_log_deferred);
+ Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
+
#if 0
#ifdef HAVE_LIBOTF
staticpro (&otf_list);
defsubr (&Sfind_font);
defsubr (&Sfont_xlfd_name);
defsubr (&Sclear_font_cache);
- defsubr (&Sfont_make_gstring);
- defsubr (&Sfont_fill_gstring);
- defsubr (&Sfont_shape_text);
+ defsubr (&Sfont_shape_gstring);
#if 0
defsubr (&Sfont_drive_otf);
defsubr (&Sfont_otf_alternates);
#ifdef HAVE_NS
syms_of_nsfont ();
#endif /* HAVE_NS */
-#ifdef MAC_OS
- syms_of_atmfont ();
-#endif /* MAC_OS */
#endif /* HAVE_WINDOW_SYSTEM */
}