#include "w32term.h"
#endif /* HAVE_NTGUI */
+#ifdef HAVE_NS
+#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
+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
+
/* 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;
extern Lisp_Object Qnormal;
/* Symbols representing keys of normal font properties. */
-extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
+extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth;
+extern Lisp_Object QCheight, QCsize, QCname;
+
Lisp_Object QCfoundry, QCadstyle, QCregistry;
/* Symbols representing keys of font extra info. */
Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
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;
}
font_assert (((i >> 4) & 0xF) < ASIZE (table));
elt = AREF (table, ((i >> 4) & 0xF));
font_assert ((i & 0xF) + 1 < ASIZE (elt));
- return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
+ return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
}
extern Lisp_Object Vface_alternative_font_family_alist;
if (*p == '~')
p++;
ASET (font, FONT_AVGWIDTH_INDEX,
- font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 1));
+ font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0));
}
else
{
p++;
else if (*p == ':')
{
- family_end = p;
- props_beg = p + 1;
+ props_beg = family_end = p;
break;
}
else if (*p == '-')
{
- int size_found = 1;
+ int decimal = 0, size_found = 1;
for (q = p + 1; *q && *q != ':'; q++)
- if (! isdigit(*q) && *q != '.')
+ if (! isdigit(*q))
{
- size_found = 0;
- break;
+ if (*q != '.' || decimal)
+ {
+ size_found = 0;
+ break;
+ }
+ decimal = 1;
}
if (size_found)
{
double point_size = strtod (size_beg, &size_end);
ASET (font, FONT_SIZE_INDEX, make_float (point_size));
if (*size_end == ':' && size_end[1])
- props_beg = size_end + 1;
+ props_beg = size_end;
}
if (props_beg)
{
- /* Now parse ":KEY=VAL" patterns. Store known keys and values in
- extra, copy unknown ones to COPY. It is stored in extra slot by
- the key QCfc_unknown_spec. */
- char *copy;
-
- name = copy = alloca (name + len - props_beg);
- if (! copy)
- return -1;
+ /* Now parse ":KEY=VAL" patterns. */
+ Lisp_Object val;
- p = props_beg;
- while (*p)
+ for (p = props_beg; *p; p = q)
{
- Lisp_Object val;
- int word_len, prop;
-
-#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
-
for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
- word_len = q - p;
if (*q != '=')
{
/* Must be an enumerated value. */
+ int word_len;
+ p = p + 1;
+ word_len = q - p;
val = font_intern_prop (p, q - p, 1);
+
+#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
+
if (PROP_MATCH ("light", 5)
|| PROP_MATCH ("medium", 6)
|| PROP_MATCH ("demibold", 8)
else if (PROP_MATCH ("proportional", 12))
ASET (font, FONT_SPACING_INDEX,
make_number (FONT_SPACING_PROPORTIONAL));
- else
- {
- /* Unknown key */
- bcopy (p, copy, word_len);
- copy += word_len;
- }
+#undef PROP_MATCH
}
- else /* KEY=VAL pairs */
+ else
{
+ /* KEY=VAL pairs */
Lisp_Object key;
- char *keyhead = p;
+ int prop;
- if (PROP_MATCH ("pixelsize=", 10))
+ if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
prop = FONT_SIZE_INDEX;
else
{
key = font_intern_prop (p, q - p, 1);
prop = get_font_prop_index (key);
}
+
p = q + 1;
for (q = p; *q && *q != ':'; q++);
+ val = font_intern_prop (p, q - p, 0);
- val = font_intern_prop (p, word_len, 0);
- if (! NILP (val))
- {
- if (prop >= FONT_FOUNDRY_INDEX
- && prop < FONT_EXTRA_INDEX)
- ASET (font, prop,
- font_prop_validate (prop, Qnil, val));
- else if (prop >= 0)
- Ffont_put (font, key, val);
- else
- bcopy (keyhead, copy, q - keyhead);
- copy += q - keyhead;
- }
+ if (prop >= FONT_FOUNDRY_INDEX
+ && prop < FONT_EXTRA_INDEX)
+ ASET (font, prop, font_prop_validate (prop, Qnil, val));
+ else
+ Ffont_put (font, key, val);
}
- p = *q ? q + 1 : q;
-#undef PROP_MATCH
+ p = q;
}
- if (name != copy)
- font_put_extra (font, QCfc_unknown_spec,
- make_unibyte_string (name, copy - name));
}
}
else
{
if (isdigit (*p))
{
- char *r;
int size_found = 1;
+
for (q = p + 1; *q && *q != ' '; q++)
if (! isdigit (*q))
{
ASET (font, FONT_FAMILY_INDEX, family);
}
}
-
+
return 0;
}
char *name;
int nbytes;
{
+ Lisp_Object family, foundry;
Lisp_Object tail, val;
int point_size;
int dpi;
char *style_names[3] = { "weight", "slant", "width" };
char work[256];
- val = AREF (font, FONT_FAMILY_INDEX);
- if (STRINGP (val))
- len += SBYTES (val);
+ family = AREF (font, FONT_FAMILY_INDEX);
+ if (! NILP (family))
+ {
+ if (SYMBOLP (family))
+ {
+ family = SYMBOL_NAME (family);
+ len += SBYTES (family);
+ }
+ else
+ family = Qnil;
+ }
val = AREF (font, FONT_SIZE_INDEX);
if (INTEGERP (val))
len += 11; /* for "-NUM" */
}
- val = AREF (font, FONT_FOUNDRY_INDEX);
- if (STRINGP (val))
- /* ":foundry=NAME" */
- len += 9 + SBYTES (val);
+ foundry = AREF (font, FONT_FOUNDRY_INDEX);
+ if (! NILP (foundry))
+ {
+ if (SYMBOLP (foundry))
+ {
+ foundry = SYMBOL_NAME (foundry);
+ len += 9 + SBYTES (foundry); /* ":foundry=NAME" */
+ }
+ else
+ foundry = Qnil;
+ }
for (i = 0; i < 3; i++)
{
if (len > nbytes)
return -1;
p = name;
- if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
- p += sprintf(p, "%s", SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
+ if (! NILP (family))
+ p += sprintf (p, "%s", SDATA (family));
if (point_size > 0)
{
if (p == name)
return (p - name);
}
+/* Store GTK-style font name of FONT (font-spec or font-entity) in
+ NAME (NBYTES length), and return the name length. F is the frame
+ on which the font is displayed; it is used to calculate the point
+ size. */
+
+int
+font_unparse_gtkname (font, f, name, nbytes)
+ Lisp_Object font;
+ struct frame *f;
+ char *name;
+ int nbytes;
+{
+ char *p;
+ int len = 1;
+ Lisp_Object family, weight, slant, size;
+ int point_size = -1;
+
+ family = AREF (font, FONT_FAMILY_INDEX);
+ if (! NILP (family))
+ {
+ if (! SYMBOLP (family))
+ return -1;
+ family = SYMBOL_NAME (family);
+ len += SBYTES (family);
+ }
+
+ weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
+ if (EQ (weight, Qnormal))
+ weight = Qnil;
+ else if (! NILP (weight))
+ {
+ weight = SYMBOL_NAME (weight);
+ len += SBYTES (weight);
+ }
+
+ slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
+ if (EQ (slant, Qnormal))
+ slant = Qnil;
+ else if (! NILP (slant))
+ {
+ slant = SYMBOL_NAME (slant);
+ len += SBYTES (slant);
+ }
+
+ size = AREF (font, FONT_SIZE_INDEX);
+ /* Convert pixel size to point size. */
+ if (INTEGERP (size))
+ {
+ Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
+ int dpi = 75;
+ if (INTEGERP (font_dpi))
+ dpi = XINT (font_dpi);
+ else if (f)
+ dpi = f->resy;
+ point_size = PIXEL_TO_POINT (XINT (size), dpi);
+ len += 11;
+ }
+ else if (FLOATP (size))
+ {
+ point_size = (int) XFLOAT_DATA (size);
+ len += 11;
+ }
+
+ if (len > nbytes)
+ return -1;
+
+ p = name + sprintf (name, "%s", SDATA (family));
+
+ if (! NILP (weight))
+ {
+ char *q = p;
+ p += sprintf (p, " %s", SDATA (weight));
+ q[1] = toupper (q[1]);
+ }
+
+ if (! NILP (slant))
+ {
+ char *q = p;
+ p += sprintf (p, " %s", SDATA (slant));
+ q[1] = toupper (q[1]);
+ }
+
+ if (point_size > 0)
+ p += sprintf (p, " %d", point_size);
+
+ return (p - name);
+}
+
/* Parse NAME (null terminated) and store information in FONT
(font-spec or font-entity). If NAME is successfully parsed, return
0. Otherwise return -1. */
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)
if (diff < 0)
diff = - diff;
- /* This is to prefer the exact symbol style. */
- diff++;
- score |= min (diff, 127) << sort_shift_bits[i];
+ if (diff > 0)
+ score |= min (diff, 127) << sort_shift_bits[i];
}
/* 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 ENTITY matches with the font specification SPEC. */
+/* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
-int
-font_match_p (spec, entity)
- Lisp_Object spec, entity;
+static int
+font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
{
- Lisp_Object prefer_prop[FONT_SPEC_MAX];
- Lisp_Object alternate_families = Qnil;
- int i;
+ Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
- 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]))
+ script = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
{
- alternate_families
- = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
- Vface_alternative_font_family_alist, Qt);
- if (CONSP (alternate_families))
- alternate_families = XCDR (alternate_families);
+ langsys = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
+ {
+ gsub = XCAR (spec);
+ spec = XCDR (spec);
+ if (! NILP (spec))
+ gpos = XCAR (spec);
+ }
}
- return (font_score (entity, prefer_prop) == 0);
+ 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 a lispy font object corresponding to FONT. */
+
+/* Check if FONT (font-entity or font-object) matches with the font
+ specification SPEC. */
int
-font_check_object (font)
- struct font *font;
+font_match_p (spec, font)
+ Lisp_Object spec, font;
{
- Lisp_Object tail, elt;
+ Lisp_Object prop[FONT_SPEC_MAX], *props;
+ Lisp_Object extra, font_extra;
+ int i;
- for (tail = font->props[FONT_OBJLIST_INDEX]; CONSP (tail);
- tail = XCDR (tail))
+ 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]))
{
- elt = XCAR (tail);
- if (font == XFONT_OBJECT (elt))
- return 1;
+ 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;
}
- return 0;
-}
+ 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))
+ {
+ 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 1;
+}
\f
/* Font cache
Lisp_Object val = XCAR (objlist);
struct font *font = XFONT_OBJECT (val);
- font_assert (font && driver == font->driver);
- driver->close (f, font);
- num_fonts--;
+ if (! NILP (AREF (val, FONT_TYPE_INDEX)))
+ {
+ font_assert (font && driver == font->driver);
+ driver->close (f, font);
+ num_fonts--;
+ }
}
if (driver->free_entity)
driver->free_entity (entity);
&& ((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);
}
struct font_driver_list *driver_list;
Lisp_Object objlist, size, val, font_object;
struct font *font;
- int min_width;
+ int min_width, height;
font_assert (FONT_ENTITY_P (entity));
size = AREF (entity, FONT_SIZE_INDEX);
for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
objlist = XCDR (objlist))
- if (XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
+ if (! NILP (AREF (XCAR (objlist), FONT_TYPE_INDEX))
+ && XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
return XCAR (objlist);
val = AREF (entity, FONT_TYPE_INDEX);
return Qnil;
ASET (entity, FONT_OBJLIST_INDEX,
Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
- ASET (font_object, FONT_OBJLIST_INDEX, AREF (entity, FONT_OBJLIST_INDEX));
+ ASET (font_object, FONT_OBJLIST_INDEX, Qnil);
num_fonts++;
font = XFONT_OBJECT (font_object);
: font->average_width ? font->average_width
: font->space_width ? font->space_width
: 1);
+ height = (font->height ? font->height : 1);
#ifdef HAVE_WINDOW_SYSTEM
FRAME_X_DISPLAY_INFO (f)->n_fonts++;
if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
{
FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
- FRAME_SMALLEST_FONT_HEIGHT (f) = font->height;
+ FRAME_SMALLEST_FONT_HEIGHT (f) = height;
fonts_changed_p = 1;
}
else
{
if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
- if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->height)
- FRAME_SMALLEST_FONT_HEIGHT (f) = font->height, fonts_changed_p = 1;
+ if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
+ FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
}
#endif
Lisp_Object font_object;
{
struct font *font = XFONT_OBJECT (font_object);
- Lisp_Object objlist;
- Lisp_Object tail, prev = Qnil;
- objlist = AREF (font_object, FONT_OBJLIST_INDEX);
- for (prev = Qnil, tail = objlist; CONSP (tail);
- prev = tail, tail = XCDR (tail))
- if (EQ (font_object, XCAR (tail)))
- {
- font_add_log ("close", font_object, Qnil);
- font->driver->close (f, font);
+ if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
+ /* Already closed. */
+ return;
+ font_add_log ("close", font_object, Qnil);
+ font->driver->close (f, font);
#ifdef HAVE_WINDOW_SYSTEM
- font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
- FRAME_X_DISPLAY_INFO (f)->n_fonts--;
+ font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
+ FRAME_X_DISPLAY_INFO (f)->n_fonts--;
#endif
- if (NILP (prev))
- ASET (font_object, FONT_OBJLIST_INDEX, XCDR (objlist));
- else
- XSETCDR (prev, XCDR (objlist));
- num_fonts--;
- return;
- }
- abort ();
+ num_fonts--;
}
{
Lisp_Object work;
Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
- Lisp_Object size, foundry[3], *family;
+ Lisp_Object size, foundry[3], *family, registry[3], adstyle[3];
int pixel_size;
- int i, j, result;
+ int i, j, k, l, result;
+
+ registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
+ if (NILP (registry[0]))
+ {
+ registry[0] = DEFAULT_ENCODING;
+ registry[1] = Qascii_0;
+ registry[2] = null_vector;
+ }
+ else
+ registry[1] = null_vector;
if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
{
else
foundry[0] = Qnil, foundry[1] = null_vector;
+ adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
+ if (! NILP (adstyle[0]))
+ adstyle[1] = null_vector;
+ else if (FONTP (attrs[LFACE_FONT_INDEX]))
+ {
+ Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
+
+ if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
+ {
+ adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
+ adstyle[1] = Qnil;
+ adstyle[2] = null_vector;
+ }
+ else
+ adstyle[0] = Qnil, adstyle[1] = null_vector;
+ }
+ else
+ adstyle[0] = Qnil, adstyle[1] = 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]),
}
}
- for (j = 0; SYMBOLP (family[j]); j++)
+ for (i = 0; SYMBOLP (family[i]); i++)
{
- ASET (work, FONT_FAMILY_INDEX, family[j]);
- for (i = 0; SYMBOLP (foundry[i]); i++)
+ ASET (work, FONT_FAMILY_INDEX, family[i]);
+ for (j = 0; SYMBOLP (foundry[j]); j++)
{
- ASET (work, FONT_FOUNDRY_INDEX, foundry[i]);
- entities = font_list_entities (frame, work);
- if (ASIZE (entities) > 0)
- break;
+ ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
+ for (k = 0; SYMBOLP (registry[k]); k++)
+ {
+ ASET (work, FONT_REGISTRY_INDEX, registry[k]);
+ for (l = 0; SYMBOLP (adstyle[l]); l++)
+ {
+ ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
+ entities = font_list_entities (frame, work);
+ if (ASIZE (entities) > 0)
+ goto found;
+ }
+ }
}
- if (ASIZE (entities) > 0)
- break;
}
- if (ASIZE (entities) == 0)
- return Qnil;
+ return Qnil;
+ found:
if (ASIZE (entities) == 1)
{
if (c < 0)
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);
if (! EQ (new_drivers, Qt))
{
/* Re-order the driver list according to new_drivers. */
- struct font_driver_list **list_table, *list;
+ struct font_driver_list **list_table, **next;
Lisp_Object tail;
int i;
list_table[i] = list;
list_table[i] = NULL;
- f->font_driver_list = list = NULL;
+ next = &f->font_driver_list;
for (i = 0; list_table[i]; i++)
{
- if (list)
- list->next = list_table[i], list = list->next;
- else
- f->font_driver_list = list = list_table[i];
+ *next = list_table[i];
+ next = &(*next)->next;
}
- list->next = NULL;
+ *next = NULL;
}
for (list = f->font_driver_list; list; list = list->next)
if (! face->font)
return Qnil;
- font_assert (font_check_object ((struct font *) face->font));
XSETFONT (font_object, face->font);
return font_object;
}
VALUE must be a non-negative integer or a floating point number
specifying the font size. It specifies the font size in pixels
(if VALUE is an integer), or in points (if VALUE is a float).
+
+`:name'
+
+VALUE must be a string of XLFD-style or fontconfig-style font name.
usage: (font-spec ARGS ...) */)
(nargs, args)
int nargs;
(font)
Lisp_Object font;
{
- Lisp_Object new_spec, tail, extra;
+ Lisp_Object new_spec, tail, prev, extra;
int i;
CHECK_FONT (font);
new_spec = font_make_spec ();
for (i = 1; i < FONT_EXTRA_INDEX; i++)
ASET (new_spec, i, AREF (font, i));
- extra = Qnil;
- for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
- {
- if (! EQ (XCAR (XCAR (tail)), QCfont_entity))
- extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
- }
+ extra = Fcopy_sequence (AREF (font, FONT_EXTRA_INDEX));
+ /* We must remove :font-entity property. */
+ for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
+ if (EQ (XCAR (XCAR (tail)), QCfont_entity))
+ {
+ if (NILP (prev))
+ extra = XCDR (extra);
+ else
+ XSETCDR (prev, XCDR (tail));
+ break;
+ }
ASET (new_spec, FONT_EXTRA_INDEX, extra);
return new_spec;
}
CHECK_SYMBOL (key);
idx = get_font_prop_index (key);
+ if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
+ return font_style_symbolic (font, idx, 0);
if (idx >= 0 && idx < FONT_EXTRA_INDEX)
return AREF (font, idx);
return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
}
+#ifdef HAVE_WINDOW_SYSTEM
+
+DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
+ doc: /* Return a plist of face attributes generated by FONT.
+FONT is a font name, a font-spec, a font-entity, or a font-object.
+The return value is a list of the form
+
+\(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
+
+where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
+compatible with `set-face-attribute'. Some of these key-attribute pairs
+may be omitted from the list if they are not specified by FONT.
+
+The optional argument FRAME specifies the frame that the face attributes
+are to be displayed on. If omitted, the selected frame is used. */)
+ (font, frame)
+ Lisp_Object font, frame;
+{
+ struct frame *f;
+ Lisp_Object plist[10];
+ Lisp_Object val;
+ int n = 0;
+
+ if (NILP (frame))
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+
+ if (STRINGP (font))
+ {
+ int fontset = fs_query_fontset (font, 0);
+ Lisp_Object name = font;
+ if (fontset >= 0)
+ font = fontset_ascii (fontset);
+ font = font_spec_from_name (name);
+ if (! FONTP (font))
+ signal_error ("Invalid font name", name);
+ }
+ else if (! FONTP (font))
+ signal_error ("Invalid font object", font);
+
+ val = AREF (font, FONT_FAMILY_INDEX);
+ if (! NILP (val))
+ {
+ plist[n++] = QCfamily;
+ plist[n++] = SYMBOL_NAME (val);
+ }
+
+ val = AREF (font, FONT_SIZE_INDEX);
+ if (INTEGERP (val))
+ {
+ 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 (PIXEL_TO_POINT (XINT (val) * 10, dpi));
+ }
+ else if (FLOATP (val))
+ {
+ plist[n++] = QCheight;
+ plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
+ }
+
+ val = FONT_WEIGHT_FOR_FACE (font);
+ if (! NILP (val))
+ {
+ plist[n++] = QCweight;
+ plist[n++] = val;
+ }
+
+ val = FONT_SLANT_FOR_FACE (font);
+ if (! NILP (val))
+ {
+ plist[n++] = QCslant;
+ plist[n++] = val;
+ }
+
+ val = FONT_WIDTH_FOR_FACE (font);
+ if (! NILP (val))
+ {
+ plist[n++] = QCwidth;
+ plist[n++] = val;
+ }
+
+ return Flist (n, plist);
+}
+
+#endif
DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
doc: /* Set one property of FONT-SPEC: give property PROP value 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)
{
int i, j;
Lisp_Object table, elt;
-
+
table = Fmake_vector (make_number (nelement), Qnil);
for (i = 0; i < nelement; i++)
{
elt = Fmake_vector (make_number (j + 1), Qnil);
ASET (elt, 0, make_number (entry[i].numeric));
for (j = 0; entry[i].names[j]; j++)
- ASET (elt, j + 1, intern (entry[i].names[j]));
+ ASET (elt, j + 1, intern (entry[i].names[j]));
ASET (table, i, elt);
}
return table;
if (FONTP (arg))
arg = Ffont_xlfd_name (arg, Qt);
if (FONTP (result))
- result = Ffont_xlfd_name (result, Qt);
+ {
+ val = Ffont_xlfd_name (result, Qt);
+ if (! FONT_SPEC_P (result))
+ val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
+ build_string (":"), val);
+ result = val;
+ }
else if (CONSP (result))
{
result = Fcopy_sequence (result);
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 ()
defsubr (&Sfontp);
defsubr (&Sfont_spec);
defsubr (&Sfont_get);
+#ifdef HAVE_WINDOW_SYSTEM
+ defsubr (&Sfont_face_attributes);
+#endif
defsubr (&Sfont_put);
defsubr (&Slist_fonts);
defsubr (&Sfont_family_list);
doc: /* Vector of valid font weight values.
Each element has the form:
[NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
-NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symobls. */);
+NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
doc: /* Vector of font slant symbols vs the corresponding numeric values.
-See `font-weight_table' for the format of the vector. */);
+See `font-weight-table' for the format of the vector. */);
Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
doc: /* Alist of font width symbols vs the corresponding numeric values.
-See `font-weight_table' for the format of the vector. */);
+See `font-weight-table' for the format of the vector. */);
Vfont_width_table = BUILD_STYLE_TABLE (width_table);
staticpro (&font_style_table);
#ifdef WINDOWSNT
syms_of_w32font ();
#endif /* WINDOWSNT */
+#ifdef HAVE_NS
+ syms_of_nsfont ();
+#endif /* HAVE_NS */
#ifdef MAC_OS
syms_of_atmfont ();
#endif /* MAC_OS */