/* font.c -- "Font" primitives.
- Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
- Copyright (C) 2006, 2007, 2008
+ Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2008, 2009
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
#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
{
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);
}
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;
}
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 (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
{
if (prop == FONT_FAMILY_INDEX)
- ASET (font, FONT_FOUNDRY_INDEX, Qnil);
+ {
+ ASET (font, FONT_FOUNDRY_INDEX, Qnil);
+ /* If we are setting the font family, we must also clear
+ FONT_WIDTH_INDEX to avoid rejecting families that lack
+ support for some widths. */
+ ASET (font, FONT_WIDTH_INDEX, Qnil);
+ }
ASET (font, FONT_ADSTYLE_INDEX, Qnil);
ASET (font, FONT_REGISTRY_INDEX, Qnil);
ASET (font, FONT_SIZE_INDEX, Qnil);
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));
+ entities = font_sort_entites (entities, prefer, frame, c < 0);
+
+ if (c < 0)
+ return entities;
+
+ for (i = 0; i < ASIZE (entities); i++)
+ {
+ int j;
+
+ font_entity = AREF (entities, i);
+ if (i > 0)
+ {
+ for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
+ if (! EQ (AREF (font_entity, j), props[j]))
+ break;
+ if (j > FONT_REGISTRY_INDEX)
+ continue;
+ }
+ for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
+ props[j] = AREF (font_entity, j);
+ result = font_has_char (f, font_entity, c);
+ if (result > 0)
+ return font_entity;
+ }
+ return Qnil;
+}
+
/* 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;
}
size = font_pixel_size (f, spec);
else
{
- double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
+ double pt;
+ if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
+ pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
+ else
+ {
+ struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
+ if (INTEGERP (height))
+ pt = XINT (height);
+ else
+ abort(); /* We should never end up here. */
+ }
pt /= 10;
size = POINT_TO_PIXEL (pt, f->resy);
category = CHAR_TABLE_REF (Vunicode_category_table, c);
if (! EQ (category, QCf)
+ && ! CHAR_VARIATION_SELECTOR_P (c)
&& font_encode_char (font_object, c) == FONT_INVALID_CODE)
{
Lisp_Object f = font_for_char (face, c, pos - 1, string);
FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, i, i_byte);
category = CHAR_TABLE_REF (Vunicode_category_table, c);
if (! EQ (category, QCf)
+ && ! CHAR_VARIATION_SELECTOR_P (c)
&& font_encode_char (f, c) == FONT_INVALID_CODE)
{
*limit = pos - 1;
`: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;
if (driver_list->driver->list_family)
{
Lisp_Object val = driver_list->driver->list_family (frame);
+ Lisp_Object tail = list;
- if (NILP (list))
- list = val;
- else
- {
- Lisp_Object tail = list;
-
- for (; CONSP (val); val = XCDR (val))
- if (NILP (Fmemq (XCAR (val), tail)))
- list = Fcons (XCAR (val), list);
- }
+ for (; CONSP (val); val = XCDR (val))
+ if (NILP (Fmemq (XCAR (val), tail))
+ && SYMBOLP (XCAR (val)))
+ list = Fcons (SYMBOL_NAME (XCAR (val)), list);
}
return list;
}
return composition_gstring_put_cache (gstring, XINT (n));
}
+DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
+ 2, 2, 0,
+ doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
+Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
+where
+ VARIATION-SELECTOR is a chracter code of variation selection
+ (#xFE00..#xFE0F or #xE0100..#xE01EF)
+ GLYPH-ID is a glyph code of the corresponding variation glyph. */)
+ (font_object, character)
+ Lisp_Object font_object, character;
+{
+ unsigned variations[256];
+ struct font *font;
+ int i, n;
+ Lisp_Object val;
+
+ CHECK_FONT_OBJECT (font_object);
+ CHECK_CHARACTER (character);
+ font = XFONT_OBJECT (font_object);
+ if (! font->driver->get_variation_glyphs)
+ return Qnil;
+ n = font->driver->get_variation_glyphs (font, XINT (character), variations);
+ if (! n)
+ return Qnil;
+ val = Qnil;
+ for (i = 0; i < 255; i++)
+ if (variations[i])
+ {
+ Lisp_Object code;
+ int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
+ /* Stops GCC whining about limited range of data type. */
+ EMACS_INT var = variations[i];
+
+ if (var > MOST_POSITIVE_FIXNUM)
+ code = Fcons (make_number ((variations[i]) >> 16),
+ make_number ((variations[i]) & 0xFFFF));
+ else
+ code = make_number (variations[i]);
+ val = Fcons (Fcons (make_number (vs), code), val);
+ }
+ return val;
+}
+
#if 0
DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
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");
defsubr (&Sfont_xlfd_name);
defsubr (&Sclear_font_cache);
defsubr (&Sfont_shape_gstring);
+ defsubr (&Sfont_variation_glyphs);
#if 0
defsubr (&Sfont_drive_otf);
defsubr (&Sfont_otf_alternates);