#include "nsterm.h"
#endif /* HAVE_NS */
-Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
-
#ifdef HAVE_NS
extern Lisp_Object Qfontsize;
#endif
{ 40, { "extra-light", "extralight" }},
{ 50, { "light" }},
{ 75, { "semi-light", "semilight", "demilight", "book" }},
- { 100, { "normal", "medium", "regular" }},
+ { 100, { "normal", "medium", "regular", "unspecified" }},
{ 180, { "semi-bold", "semibold", "demibold", "demi" }},
{ 200, { "bold" }},
{ 205, { "extra-bold", "extrabold" }},
{
{ 0, { "reverse-oblique", "ro" }},
{ 10, { "reverse-italic", "ri" }},
- { 100, { "normal", "r" }},
+ { 100, { "normal", "r", "unspecified" }},
{ 200, { "italic" ,"i", "ot" }},
{ 210, { "oblique", "o" }}
};
{ 63, { "extra-condensed", "extracondensed" }},
{ 75, { "condensed", "compressed", "narrow" }},
{ 87, { "semi-condensed", "semicondensed", "demicondensed" }},
- { 100, { "normal", "medium", "regular" }},
+ { 100, { "normal", "medium", "regular", "unspecified" }},
{ 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
{ 125, { "expanded" }},
{ 150, { "extra-expanded", "extraexpanded" }},
return -1;
if (len == 255)
abort ();
- elt = Fmake_vector (make_number (2), make_number (255));
+ elt = Fmake_vector (make_number (2), make_number (100));
ASET (elt, 1, val);
args[0] = table;
args[1] = Fmake_vector (make_number (1), elt);
ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
- return (255 << 8) | (i << 4);
+ return (100 << 8) | (i << 4);
}
else
{
: CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
return (XCDR (elt));
}
- /* We don't know the encoding of this font. Let's assume `ascii'. */
- return Qascii;
+ return Qnil;
}
/* Return encoding charset and repertory charset for REGISTRY in
{
Lisp_Object prev = Qnil;
+ if (NILP (val))
+ return val;
while (CONSP (extra)
&& NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
prev = extra, extra = XCDR (extra);
return val;
}
XSETCDR (slot, val);
+ if (NILP (val))
+ ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
return val;
}
Lisp_Object val;
char *p;
- if (len > 255)
+ if (len > 255 || !len)
/* Maximum XLFD name length is 255. */
return -1;
/* Accept "*-.." as a fully specified XLFD. */
- if (name[0] == '*' && name[1] == '-')
+ if (name[0] == '*' && (len == 1 || name[1] == '-'))
i = 1, f[XLFD_FOUNDRY_INDEX] = name;
else
i = 0;
char *name;
Lisp_Object font;
{
- if (name[0] == '-' || index (name, '*'))
+ if (name[0] == '-' || index (name, '*') || index (name, '?'))
return font_parse_xlfd (name, font);
return font_parse_fcname (name, font);
}
pixel-size from QCdpi property of PREFER or from the Y-resolution
of FRAME before sorting.
- If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
- return the sorted VEC. */
+ If BEST-ONLY is nonzero, return the best matching entity (that
+ supports the character BEST-ONLY if BEST-ONLY is positive, or any
+ if BEST-ONLY is negative). Otherwise, return the sorted VEC.
+
+ This function does no optimization for the case that the length of
+ VEC is 1. The caller should avoid calling this in such a case. */
static Lisp_Object
font_sort_entites (vec, prefer, frame, best_only)
USE_SAFE_ALLOCA;
len = ASIZE (vec);
- if (len <= 1)
- return best_only ? AREF (vec, 0) : vec;
-
for (i = FONT_WEIGHT_INDEX; i <= FONT_DPI_INDEX; i++)
prefer_prop[i] = AREF (prefer, i);
if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
/* Scoring and sorting. */
SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
- best_score = 0xFFFFFFFF;
/* We are sure that the length of VEC > 1. */
driver_type = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
for (driver_order = 0, list = f->font_driver_list; list;
driver_order++, list = list->next)
if (EQ (driver_type, list->driver->type))
break;
- best_entity = data[0].entity = AREF (vec, 0);
- best_score = data[0].score
- = font_score (data[0].entity, prefer_prop) | driver_order;
+ best_score = 0xFFFFFFFF;
+ best_entity = Qnil;
for (i = 0; i < len; i++)
{
if (!EQ (driver_type, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
if (EQ (driver_type, list->driver->type))
break;
data[i].entity = AREF (vec, i);
- data[i].score = font_score (data[i].entity, prefer_prop) | driver_order;
+ data[i].score
+ = (best_only <= 0 || font_has_char (f, data[i].entity, best_only) > 0
+ ? font_score (data[i].entity, prefer_prop) | driver_order
+ : 0xFFFFFFFF);
if (best_only && best_score > data[i].score)
{
best_score = data[i].score;
for (negative = 0; CONSP (features); features = XCDR (features))
{
if (NILP (XCAR (features)))
- negative = 1;
+ {
+ negative = 1;
+ continue;
+ }
if (NILP (Fmemq (XCAR (features), table)) != negative)
return 0;
}
if (prop < FONT_SPEC_MAX)
val = Fcons (entity, val);
}
- return val;
+ return Fnreverse (val);
}
return spec;
}
+
+/* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
+ could not be parsed by font_parse_name, return Qnil. */
+
Lisp_Object
font_spec_from_name (font_name)
Lisp_Object font_name;
{
- Lisp_Object args[2];
+ Lisp_Object spec = Ffont_spec (0, NULL);
- args[0] = QCname;
- args[1] = font_name;
- return Ffont_spec (2, args);
+ CHECK_STRING (font_name);
+ if (font_parse_name ((char *) SDATA (font_name), spec) == -1)
+ return Qnil;
+ font_put_extra (spec, QCname, font_name);
+ return spec;
}
if (! FONTP (font))
return;
+ if (! NILP (Ffont_get (font, QCname)))
+ {
+ font = Fcopy_font_spec (font);
+ font_put_extra (font, QCname, Qnil);
+ }
+
if (NILP (AREF (font, prop))
&& prop != FONT_FAMILY_INDEX
&& prop != FONT_FOUNDRY_INDEX
&& prop != FONT_WIDTH_INDEX
&& prop != FONT_SIZE_INDEX)
return;
- font = Fcopy_font_spec (font);
+ if (EQ (font, attrs[LFACE_FONT_INDEX]))
+ font = Fcopy_font_spec (font);
ASET (font, prop, Qnil);
if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
{
if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
- attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);;
+ attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);
if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
}
+/* Selecte a font from ENTITIES that supports C and matches best with
+ ATTRS and PIXEL_SIZE. */
+
+static Lisp_Object
+font_select_entity (frame, entities, attrs, pixel_size, c)
+ Lisp_Object frame, entities, *attrs;
+ int pixel_size, c;
+{
+ Lisp_Object font_entity;
+ Lisp_Object prefer;
+ Lisp_Object props[FONT_REGISTRY_INDEX + 1] ;
+ int result, i;
+ FRAME_PTR f = XFRAME (frame);
+
+ if (ASIZE (entities) == 1)
+ {
+ font_entity = AREF (entities, 0);
+ if (c < 0
+ || (result = font_has_char (f, font_entity, c)) > 0)
+ return font_entity;
+ return Qnil;
+ }
+
+ /* Sort fonts by properties specified in ATTRS. */
+ prefer = scratch_font_prefer;
+
+ for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
+ ASET (prefer, i, Qnil);
+ if (FONTP (attrs[LFACE_FONT_INDEX]))
+ {
+ Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
+
+ for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
+ ASET (prefer, i, AREF (face_font, i));
+ }
+ if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
+ FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
+ if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
+ FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
+ 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));
+
+ return font_sort_entites (entities, prefer, frame, c);
+}
+
/* Return a font-entity satisfying SPEC and best matching with face's
font related attributes in ATTRS. C, if not negative, is a
character that the entity must support. */
ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
entities = font_list_entities (frame, work);
if (ASIZE (entities) > 0)
- goto found;
+ {
+ val = font_select_entity (frame, entities,
+ attrs, pixel_size, c);
+ if (! NILP (val))
+ return val;
+ }
}
}
}
}
return Qnil;
- found:
- if (ASIZE (entities) == 1)
- {
- if (c < 0)
- return AREF (entities, 0);
- }
- else
- {
- /* Sort fonts by properties specified in LFACE. */
- Lisp_Object prefer = scratch_font_prefer;
-
- for (i = 0; i < FONT_EXTRA_INDEX; i++)
- ASET (prefer, i, AREF (work, i));
- if (FONTP (attrs[LFACE_FONT_INDEX]))
- {
- Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
-
- for (i = 0; i < FONT_EXTRA_INDEX; i++)
- if (NILP (AREF (prefer, i)))
- ASET (prefer, i, AREF (face_font, i));
- }
- if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
- FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
- if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
- FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
- 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, c < 0);
- }
- if (c < 0)
- return entities;
-
- for (i = 0; i < ASIZE (entities); i++)
- {
- int j;
-
- val = AREF (entities, i);
- if (i > 0)
- {
- for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
- if (! EQ (AREF (val, j), props[j]))
- break;
- if (j > FONT_REGISTRY_INDEX)
- continue;
- }
- for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
- props[j] = AREF (val, j);
- result = font_has_char (f, val, c);
- if (result > 0)
- return val;
- if (result == 0)
- return Qnil;
- val = font_open_for_lface (f, val, attrs, spec);
- if (NILP (val))
- continue;
- result = font_has_char (f, val, c);
- font_close_object (f, val);
- if (result > 0)
- return AREF (entities, i);
- }
- return Qnil;
}
{
Lisp_Object entity;
- entity = font_find_for_lface (f, attrs, spec, -1);
+ /* We assume that a font that supports 'A' supports ASCII chars. */
+ entity = font_find_for_lface (f, attrs, spec, 'A');
if (NILP (entity))
{
/* No font is listed for SPEC, but each font-backend may have
}
-/* Open a font best matching with NAME on frame F. If no proper font
- is found, return Qnil. */
+/* Open a font matching with font-spec SPEC on frame F. If no proper
+ font is found, return Qnil. */
Lisp_Object
-font_open_by_name (f, name)
+font_open_by_spec (f, spec)
FRAME_PTR f;
- char *name;
+ Lisp_Object spec;
{
- Lisp_Object args[2];
- Lisp_Object spec, attrs[LFACE_VECTOR_SIZE];
+ Lisp_Object attrs[LFACE_VECTOR_SIZE];
- args[0] = QCname;
- args[1] = make_unibyte_string (name, strlen (name));
- spec = Ffont_spec (2, args);
/* We set up the default font-related attributes of a face to prefer
a moderate font. */
attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
}
+/* Open a font matching with NAME on frame F. If no proper font is
+ found, return Qnil. */
+
+Lisp_Object
+font_open_by_name (f, name)
+ FRAME_PTR f;
+ char *name;
+{
+ Lisp_Object args[2];
+ Lisp_Object spec;
+
+ args[0] = QCname;
+ args[1] = make_unibyte_string (name, strlen (name));
+ spec = Ffont_spec (2, args);
+ return font_open_by_spec (f, spec);
+}
+
+
/* Register font-driver DRIVER. This function is used in two ways.
The first is with frame F non-NULL. In this case, make DRIVER
`:size'
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).
+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'
`:script'
VALUE must be a symbol representing a script that the font must
-support.
+support. It may be a symbol representing a subgroup of a script
+listed in the variable `script-representative-chars'.
+
+`:lang'
+
+VALUE must be a symbol of two-letter ISO-639 language names,
+e.g. `ja'.
+
+`:otf'
+
+VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
+required OpenType features.
+
+ SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
+ LANGSYS-TAG: OpenType language system tag symbol,
+ or nil for the default language system.
+ GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
+ GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
+
+GSUB and GPOS may contain `nil' element. In such a case, the font
+must not have any of the remaining elements.
+
+For instance, if the VALUE is `(thai nil nil (mark))', the font must
+be an OpenType font, and whose GPOS table of `thai' script's default
+language system must contain `mark' feature.
+
usage: (font-spec ARGS...) */)
(nargs, args)
int nargs;
DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
doc: /* Return information about a font named NAME on frame FRAME.
If FRAME is omitted or nil, use the selected frame.
-The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
+The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
where
OPENED-NAME is the name used for opening the font,
FULL-NAME is the full name of the font,
- SIZE is the maximum bound width of the font,
- HEIGHT is the height of the font,
+ SIZE is the pixelsize of the font,
+ HEIGHT is the pixel-height of the font (i.e ascent + descent),
BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
how to compose characters.
info = Fmake_vector (make_number (7), Qnil);
XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
- XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX);
+ XVECTOR (info)->contents[1] = AREF (font_object, FONT_FULLNAME_INDEX);
XVECTOR (info)->contents[2] = make_number (font->pixel_size);
XVECTOR (info)->contents[3] = make_number (font->height);
XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
staticpro (&font_charset_alist);
font_charset_alist = Qnil;
- DEFSYM (Qfont_spec, "font-spec");
- DEFSYM (Qfont_entity, "font-entity");
- DEFSYM (Qfont_object, "font-object");
-
DEFSYM (Qopentype, "opentype");
DEFSYM (Qascii_0, "ascii-0");