#include "w32term.h"
#endif /* HAVE_NTGUI */
-#ifdef MAC_OS
-#include "macterm.h"
-#endif /* MAC_OS */
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif /* HAVE_NS */
Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
+
+#ifdef HAVE_NS
+extern Lisp_Object Qfontsize;
+#endif
Lisp_Object Qopentype;
/* Important character set strings. */
Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
+#ifdef HAVE_NS
+#define DEFAULT_ENCODING Qiso10646_1
+#else
+#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;
return font_entity;
}
+/* Create a font-object whose structure size is SIZE. If ENTITY is
+ not nil, copy properties from ENTITY to the font-object. If
+ PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
Lisp_Object
-font_make_object (size)
+font_make_object (size, entity, pixelsize)
int size;
+ Lisp_Object entity;
+ int pixelsize;
{
Lisp_Object font_object;
struct font *font
= (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
+ int i;
+
XSETFONT (font_object, font);
+ if (! NILP (entity))
+ {
+ for (i = 1; i < FONT_SPEC_MAX; i++)
+ font->props[i] = AREF (entity, i);
+ if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
+ font->props[FONT_EXTRA_INDEX]
+ = Fcopy_sequence (AREF (entity, FONT_EXTRA_INDEX));
+ }
+ if (size > 0)
+ font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
return font_object;
}
{
/* KEY=VAL pairs */
Lisp_Object key;
- char *keyhead = p;
int prop;
if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
{
if (isdigit (*p))
{
- char *r;
int size_found = 1;
+
for (q = p + 1; *q && *q != ' '; q++)
if (! isdigit (*q))
{
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 */
static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
static int font_compare P_ ((const void *, const void *));
static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object,
- int));
+ Lisp_Object, int));
/* We sort fonts by scoring each of them against a specified
font-spec. The score value is 32 bit (`unsigned'), and the smaller
/* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
The return value indicates how different ENTITY is compared with
- SPEC_PROP.
-
- ALTERNATE_FAMILIES, if non-nil, is a pre-calculated list of
- alternate family names for AREF (SPEC_PROP, FONT_FAMILY_INDEX). */
+ SPEC_PROP. */
static unsigned
font_score (entity, spec_prop)
/* Score the size. Maximum difference is 127. */
i = FONT_SIZE_INDEX;
- if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i])
- && XINT (AREF (entity, i)) > 0)
+ if (! NILP (spec_prop[i]) && XINT (AREF (entity, i)) > 0)
{
/* We use the higher 6-bit for the actual size difference. The
lowest bit is set if the DPI is different. */
/* Sort font-entities in vector VEC by closeness to font-spec PREFER.
If PREFER specifies a point-size, calculate the corresponding
pixel-size from QCdpi property of PREFER or from the Y-resolution
- of FRAME before sorting. If SPEC is not nil, it is a font-spec to
- get the font-entities in VEC.
+ of FRAME before sorting.
If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
return the sorted VEC. */
static Lisp_Object
-font_sort_entites (vec, prefer, frame, spec, best_only)
- Lisp_Object vec, prefer, frame, spec;
+font_sort_entites (vec, prefer, frame, best_only)
+ Lisp_Object vec, prefer, frame;
int best_only;
{
Lisp_Object prefer_prop[FONT_SPEC_MAX];
if (len <= 1)
return best_only ? AREF (vec, 0) : vec;
- for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
+ for (i = FONT_WEIGHT_INDEX; i <= FONT_DPI_INDEX; i++)
prefer_prop[i] = AREF (prefer, i);
-
- if (! NILP (spec))
- {
- /* A font driver may return a font that has a property value
- different from the value specified in SPEC if the driver
- thinks they are the same. That happens, for instance, such a
- generic family name as "serif" is specified. So, to ignore
- such a difference, for all properties specified in SPEC, set
- the corresponding properties in PREFER_PROP to nil. */
- for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
- if (! NILP (AREF (spec, i)))
- prefer_prop[i] = Qnil;
- }
-
if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
prefer_prop[FONT_SIZE_INDEX]
= make_number (font_pixel_size (XFRAME (frame), prefer));
break;
}
}
- if (NILP (best_entity))
+ if (! best_only)
{
qsort (data, len, sizeof *data, font_compare);
for (i = 0; i < len; i++)
}
}
+static int
+font_check_otf_features (script, langsys, features, table)
+ Lisp_Object script, langsys, features, table;
+{
+ Lisp_Object val;
+ int negative;
+
+ table = assq_no_quit (script, table);
+ if (NILP (table))
+ return 0;
+ table = XCDR (table);
+ if (! NILP (langsys))
+ {
+ table = assq_no_quit (langsys, table);
+ if (NILP (table))
+ return 0;
+ }
+ else
+ {
+ val = assq_no_quit (Qnil, table);
+ if (NILP (val))
+ table = XCAR (table);
+ else
+ table = val;
+ }
+ table = XCDR (table);
+ for (negative = 0; CONSP (features); features = XCDR (features))
+ {
+ if (NILP (XCAR (features)))
+ negative = 1;
+ if (NILP (Fmemq (XCAR (features), table)) != negative)
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
-/* Check if ENTITY matches with the font specification SPEC. */
+static int
+font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
+{
+ Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
+
+ script = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
+ {
+ langsys = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
+ {
+ gsub = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
+ gpos = XCAR (spec);
+ }
+ }
+
+ if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
+ XCAR (otf_capability)))
+ return 0;
+ if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
+ XCDR (otf_capability)))
+ return 0;
+ return 1;
+}
+
+
+
+/* Check if FONT (font-entity or font-object) matches with the font
+ specification SPEC. */
int
-font_match_p (spec, entity)
- Lisp_Object spec, entity;
+font_match_p (spec, font)
+ Lisp_Object spec, font;
{
- Lisp_Object prefer_prop[FONT_SPEC_MAX];
- Lisp_Object alternate_families = Qnil;
+ Lisp_Object prop[FONT_SPEC_MAX], *props;
+ Lisp_Object extra, font_extra;
int i;
- for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
- prefer_prop[i] = AREF (spec, i);
- if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
- prefer_prop[FONT_SIZE_INDEX]
- = make_number (font_pixel_size (XFRAME (selected_frame), spec));
- if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
+ for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
+ if (! NILP (AREF (spec, i))
+ && ! NILP (AREF (font, i))
+ && ! EQ (AREF (spec, i), AREF (font, i)))
+ return 0;
+ props = XFONT_SPEC (spec)->props;
+ if (FLOATP (props[FONT_SIZE_INDEX]))
+ {
+ for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
+ prop[i] = AREF (spec, i);
+ prop[FONT_SIZE_INDEX]
+ = make_number (font_pixel_size (XFRAME (selected_frame), spec));
+ props = prop;
+ }
+
+ if (font_score (font, props) > 0)
+ return 0;
+ extra = AREF (spec, FONT_EXTRA_INDEX);
+ font_extra = AREF (font, FONT_EXTRA_INDEX);
+ for (; CONSP (extra); extra = XCDR (extra))
{
- alternate_families
- = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
- Vface_alternative_font_family_alist, Qt);
- if (CONSP (alternate_families))
- alternate_families = XCDR (alternate_families);
+ Lisp_Object key = XCAR (XCAR (extra));
+ Lisp_Object val = XCDR (XCAR (extra)), val2;
+
+ if (EQ (key, QClang))
+ {
+ val2 = assq_no_quit (key, font_extra);
+ if (NILP (val2))
+ return 0;
+ val2 = XCDR (val2);
+ if (CONSP (val))
+ {
+ if (! CONSP (val2))
+ return 0;
+ while (CONSP (val))
+ if (NILP (Fmemq (val, val2)))
+ return 0;
+ }
+ else
+ if (CONSP (val2)
+ ? NILP (Fmemq (val, XCDR (val2)))
+ : ! EQ (val, val2))
+ return 0;
+ }
+ else if (EQ (key, QCscript))
+ {
+ val2 = assq_no_quit (val, Vscript_representative_chars);
+ if (! NILP (val2))
+ for (val2 = XCDR (val2); CONSP (val2); val2 = XCDR (val2))
+ if (font_encode_char (font, XINT (XCAR (val2)))
+ == FONT_INVALID_CODE)
+ return 0;
+ }
+ else if (EQ (key, QCotf))
+ {
+ struct font *fontp;
+
+ if (! FONT_OBJECT_P (font))
+ return 0;
+ fontp = XFONT_OBJECT (font);
+ if (! fontp->driver->otf_capability)
+ return 0;
+ val2 = fontp->driver->otf_capability (fontp);
+ if (NILP (val2) || ! font_check_otf (val, val2))
+ return 0;
+ }
}
- return (font_score (entity, prefer_prop) == 0);
+ return 1;
}
\f
&& ((XINT (AREF (spec, prop)) >> 8)
!= (XINT (AREF (entity, prop)) >> 8)))
prop = FONT_SPEC_MAX;
- if (prop++ <= FONT_SIZE_INDEX
+ if (prop < FONT_SPEC_MAX
&& size
&& XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
{
: diff > FONT_PIXEL_SIZE_QUANTUM))
prop = FONT_SPEC_MAX;
}
+ if (prop < FONT_SPEC_MAX
+ && INTEGERP (AREF (spec, FONT_DPI_INDEX))
+ && INTEGERP (AREF (entity, FONT_DPI_INDEX))
+ && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
+ prop = FONT_SPEC_MAX;
+ if (prop < FONT_SPEC_MAX
+ && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
+ && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
+ && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
+ AREF (entity, FONT_AVGWIDTH_INDEX)))
+ prop = FONT_SPEC_MAX;
if (prop < FONT_SPEC_MAX)
val = Fcons (entity, val);
}
registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
if (NILP (registry[0]))
{
- registry[0] = Qiso8859_1;
+ registry[0] = DEFAULT_ENCODING;
registry[1] = Qascii_0;
registry[2] = null_vector;
}
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);
if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
- entities = font_sort_entites (entities, prefer, frame, work, c < 0);
+ entities = font_sort_entites (entities, prefer, frame, c < 0);
}
if (c < 0)
return entities;
pt /= 10;
size = POINT_TO_PIXEL (pt, f->resy);
+#ifdef HAVE_NS
+ if (size == 0)
+ {
+ Lisp_Object ffsize = get_frame_param(f, Qfontsize);
+ size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
+ }
+#endif
}
return font_open_entity (f, entity, size);
}
attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
= attrs[LFACE_SLANT_INDEX] = Qnormal;
+#ifndef HAVE_NS
attrs[LFACE_HEIGHT_INDEX] = make_number (120);
+#else
+ attrs[LFACE_HEIGHT_INDEX] = make_number (0);
+#endif
attrs[LFACE_FONT_INDEX] = Qnil;
return font_load_for_lface (f, attrs, spec);
}
-/* 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
- The return value is the position of the character that is displayed
- by the differnt font than that of the character as POS. */
+/* 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.
-EMACS_INT
-font_range (pos, limit, face, f, string)
- EMACS_INT pos, limit;
+ 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.
+
+ It is assured that the current buffer (or STRING) is multibyte. */
+
+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 */
Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : f->resy;
plist[n++] = QCheight;
- plist[n++] = make_number (10 * PIXEL_TO_POINT (XINT (val), dpi));
+ plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
}
else if (FLOATP (val))
{
return Fcons (AREF (vec, 0), Qnil);
if (! NILP (prefer))
- vec = font_sort_entites (vec, prefer, frame, font_spec, 0);
+ vec = font_sort_entites (vec, prefer, frame, 0);
list = tail = Fcons (AREF (vec, 0), Qnil);
if (n == 0 || n > len)
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;
+ if (from > LGLYPH_FROM (this))
+ from = LGLYPH_FROM (this);
+ if (to < LGLYPH_TO (this))
+ to = LGLYPH_TO (this);
}
- 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 (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_ (());
extern void syms_of_bdffont P_ (());
extern void syms_of_w32font P_ (());
extern void syms_of_atmfont P_ (());
+extern void syms_of_nsfont P_ (());
void
syms_of_font ()
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 WINDOWSNT
syms_of_w32font ();
#endif /* WINDOWSNT */
-#ifdef MAC_OS
- syms_of_atmfont ();
-#endif /* MAC_OS */
+#ifdef HAVE_NS
+ syms_of_nsfont ();
+#endif /* HAVE_NS */
#endif /* HAVE_WINDOW_SYSTEM */
}