mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-19 10:22:27 +00:00
(ftfont_pattern_entity): Argument FRAME removed. Make
a font-entity by font_make_entity. Use font_intern_prop instead of intern_downcase. Use FONT_SET_STYLE to set a style-related font property. If a font is scalable, set avgwidth property to 0. Set font-entity property by font_put_extra. (ftfont_list_generic_family): Argument SPEC and REGISTRY removed. (ffont_driver): Adjusted for the change of struct font_driver. (ftfont_spec_pattern): New function. (ftfont_list): Return a list, not vector. (ftfont_match): Use ftfont_spec_pattern to get a pattern. (ftfont_list_family): Don't downcase names. (ftfont_free_entity): Deleted. (ftfont_open): Return a font-ojbect. Adjusted for the change of struct font. Get underline_thickness and underline_position from font property. Don't update dpyinfo->smallest_font_height and dpyinfo->smallest_char_width. (ftfont_close): Don't free `struct font'. (ftfont_has_char): Adjusted for the format change of font-entity. (ftfont_encode_char, ftfont_text_extents): Likewise.
This commit is contained in:
parent
38548f605f
commit
42984a746c
665
src/ftfont.c
665
src/ftfont.c
@ -71,10 +71,8 @@ struct ftfont_info
|
||||
};
|
||||
|
||||
static int ftfont_build_basic_charsets P_ ((void));
|
||||
static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *,
|
||||
Lisp_Object, Lisp_Object));
|
||||
static Lisp_Object ftfont_list_generic_family P_ ((Lisp_Object, Lisp_Object,
|
||||
Lisp_Object));
|
||||
static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object));
|
||||
static Lisp_Object ftfont_list_generic_family P_ ((Lisp_Object));
|
||||
Lisp_Object ftfont_font_format P_ ((FcPattern *));
|
||||
|
||||
#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
|
||||
@ -99,10 +97,12 @@ ftfont_build_basic_charsets ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern Lisp_Object Qc, Qm, Qp, Qd;
|
||||
|
||||
static Lisp_Object
|
||||
ftfont_pattern_entity (p, frame, registry)
|
||||
ftfont_pattern_entity (p, registry)
|
||||
FcPattern *p;
|
||||
Lisp_Object frame, registry;
|
||||
Lisp_Object registry;
|
||||
{
|
||||
Lisp_Object entity;
|
||||
FcChar8 *file, *fontformat;
|
||||
@ -110,6 +110,7 @@ ftfont_pattern_entity (p, frame, registry)
|
||||
FcChar8 *str;
|
||||
int numeric;
|
||||
double dbl;
|
||||
FcBool b;
|
||||
|
||||
if (FcPatternGetString (p, FC_FILE, 0, &file) != FcResultMatch)
|
||||
return Qnil;
|
||||
@ -120,38 +121,48 @@ ftfont_pattern_entity (p, frame, registry)
|
||||
#endif /* FC_FONTFORMAT */
|
||||
fontformat = NULL;
|
||||
|
||||
entity = Fmake_vector (make_number (FONT_ENTITY_MAX), null_string);
|
||||
entity = font_make_entity ();
|
||||
|
||||
ASET (entity, FONT_TYPE_INDEX, Qfreetype);
|
||||
ASET (entity, FONT_REGISTRY_INDEX, registry);
|
||||
ASET (entity, FONT_FRAME_INDEX, frame);
|
||||
ASET (entity, FONT_OBJLIST_INDEX, Qnil);
|
||||
|
||||
if (FcPatternGetString (p, FC_FOUNDRY, 0, &str) == FcResultMatch)
|
||||
ASET (entity, FONT_FOUNDRY_INDEX, intern_downcase (str, strlen (str)));
|
||||
ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str)));
|
||||
if (FcPatternGetString (p, FC_FAMILY, 0, &str) == FcResultMatch)
|
||||
ASET (entity, FONT_FAMILY_INDEX, intern_downcase (str, strlen (str)));
|
||||
ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str)));
|
||||
if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
|
||||
{
|
||||
if (numeric == FC_WEIGHT_REGULAR)
|
||||
numeric = 100;
|
||||
ASET (entity, FONT_WEIGHT_INDEX, make_number (numeric));
|
||||
if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
|
||||
numeric = FC_WEIGHT_MEDIUM;
|
||||
FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
|
||||
}
|
||||
if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
|
||||
ASET (entity, FONT_SLANT_INDEX, make_number (numeric + 100));
|
||||
{
|
||||
numeric += 100;
|
||||
FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
|
||||
}
|
||||
if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
|
||||
ASET (entity, FONT_WIDTH_INDEX, make_number (numeric));
|
||||
{
|
||||
FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
|
||||
}
|
||||
if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
|
||||
ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
|
||||
else
|
||||
ASET (entity, FONT_SIZE_INDEX, make_number (0));
|
||||
if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
|
||||
ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
|
||||
if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
|
||||
{
|
||||
int dpi = dbl;
|
||||
ASET (entity, FONT_DPI_INDEX, make_number (dpi));
|
||||
}
|
||||
if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
|
||||
&& b == FcTrue)
|
||||
ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
|
||||
|
||||
if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) != FcResultMatch)
|
||||
numeric = -1;
|
||||
file = FcStrCopy (file);
|
||||
if (! file)
|
||||
return Qnil;
|
||||
|
||||
p = FcPatternCreate ();
|
||||
if (! p)
|
||||
return Qnil;
|
||||
@ -163,24 +174,28 @@ ftfont_pattern_entity (p, frame, registry)
|
||||
|| (fontformat
|
||||
&& FcPatternAddString (p, FC_FONTFORMAT, fontformat) == FcFalse)
|
||||
#endif /* FC_FONTFORMAT */
|
||||
|| (numeric >= 0
|
||||
&& FcPatternAddInteger (p, FC_SPACING, numeric) == FcFalse))
|
||||
)
|
||||
{
|
||||
FcPatternDestroy (p);
|
||||
return Qnil;
|
||||
}
|
||||
ASET (entity, FONT_EXTRA_INDEX, make_save_value (p, 0));
|
||||
font_put_extra (entity, QCfont_entity, make_save_value (p, 0));
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
static Lisp_Object ftfont_generic_family_list;
|
||||
|
||||
static Lisp_Object
|
||||
ftfont_list_generic_family (spec, frame, registry)
|
||||
Lisp_Object spec, frame, registry;
|
||||
ftfont_list_generic_family (family)
|
||||
Lisp_Object family;
|
||||
{
|
||||
Lisp_Object family = AREF (spec, FONT_FAMILY_INDEX);
|
||||
Lisp_Object slot, list, val;
|
||||
FcObjectSet *objset = NULL;
|
||||
FcPattern *pattern = NULL, *pat = NULL;
|
||||
FcFontSet *fontset = NULL;
|
||||
FcChar8 *fam;
|
||||
int i, j;
|
||||
|
||||
if (EQ (family, Qmono))
|
||||
family = Qmonospace;
|
||||
@ -188,86 +203,53 @@ ftfont_list_generic_family (spec, frame, registry)
|
||||
family = Qsans_serif;
|
||||
slot = assq_no_quit (family, ftfont_generic_family_list);
|
||||
if (! CONSP (slot))
|
||||
return null_vector;
|
||||
return Qnil;
|
||||
list = XCDR (slot);
|
||||
if (EQ (list, Qt))
|
||||
if (! EQ (list, Qt))
|
||||
return list;
|
||||
|
||||
objset = FcObjectSetBuild (FC_FAMILY, NULL);
|
||||
if (! objset)
|
||||
goto err;
|
||||
pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString,
|
||||
SYMBOL_FcChar8 (family), (char *) 0);
|
||||
if (! pattern)
|
||||
goto err;
|
||||
pat = FcPatternCreate ();
|
||||
if (! pat)
|
||||
goto err;
|
||||
FcConfigSubstitute (NULL, pattern, FcMatchPattern);
|
||||
for (i = 0, list = Qnil;
|
||||
FcPatternGetString (pattern, FC_FAMILY, i, &fam) == FcResultMatch;
|
||||
i++)
|
||||
{
|
||||
/* Not yet listed. */
|
||||
FcObjectSet *objset = NULL;
|
||||
FcPattern *pattern = NULL, *pat = NULL;
|
||||
FcFontSet *fontset = NULL;
|
||||
FcChar8 *fam;
|
||||
int i, j;
|
||||
|
||||
objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
|
||||
FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING,
|
||||
FC_CHARSET, FC_FILE,
|
||||
#ifdef FC_FONTFORMAT
|
||||
FC_FONTFORMAT,
|
||||
#endif /* FC_FONTFORMAT */
|
||||
NULL);
|
||||
if (! objset)
|
||||
if (strcmp ((char *) fam, (char *) SYMBOL_FcChar8 (family)) == 0)
|
||||
continue;
|
||||
if (! FcPatternAddString (pat, FC_FAMILY, fam))
|
||||
goto err;
|
||||
pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString,
|
||||
SYMBOL_FcChar8 (family), (char *) 0);
|
||||
if (! pattern)
|
||||
fontset = FcFontList (NULL, pat, objset);
|
||||
if (! fontset)
|
||||
goto err;
|
||||
pat = FcPatternCreate ();
|
||||
if (! pat)
|
||||
goto err;
|
||||
FcConfigSubstitute (NULL, pattern, FcMatchPattern);
|
||||
for (i = 0, val = Qnil;
|
||||
FcPatternGetString (pattern, FC_FAMILY, i, &fam) == FcResultMatch;
|
||||
i++)
|
||||
{
|
||||
if (strcmp ((char *) fam, (char *) SYMBOL_FcChar8 (family)) == 0)
|
||||
continue;
|
||||
if (! FcPatternAddString (pat, FC_FAMILY, fam))
|
||||
goto err;
|
||||
fontset = FcFontList (NULL, pat, objset);
|
||||
if (! fontset)
|
||||
goto err;
|
||||
/* Here we build the list in reverse order so that the last
|
||||
loop in this function build a list in the correct
|
||||
order. */
|
||||
for (j = 0; j < fontset->nfont; j++)
|
||||
{
|
||||
Lisp_Object entity;
|
||||
|
||||
entity = ftfont_pattern_entity (fontset->fonts[j],
|
||||
frame, registry);
|
||||
if (! NILP (entity))
|
||||
val = Fcons (entity, val);
|
||||
}
|
||||
FcFontSetDestroy (fontset);
|
||||
fontset = NULL;
|
||||
FcPatternDel (pat, FC_FAMILY);
|
||||
}
|
||||
list = val;
|
||||
XSETCDR (slot, list);
|
||||
err:
|
||||
if (pat) FcPatternDestroy (pat);
|
||||
if (pattern) FcPatternDestroy (pattern);
|
||||
if (fontset) FcFontSetDestroy (fontset);
|
||||
if (objset) FcObjectSetDestroy (objset);
|
||||
if (EQ (list, Qt))
|
||||
return Qnil;
|
||||
if (fontset->nfont > 0)
|
||||
list = Fcons (intern ((char *) fam), list);
|
||||
FcFontSetDestroy (fontset);
|
||||
fontset = NULL;
|
||||
FcPatternDel (pat, FC_FAMILY);
|
||||
}
|
||||
ASET (spec, FONT_FAMILY_INDEX, Qnil);
|
||||
for (val = Qnil; CONSP (list); list = XCDR (list))
|
||||
if (font_match_p (spec, XCAR (list)))
|
||||
val = Fcons (XCAR (list), val);
|
||||
ASET (spec, FONT_FAMILY_INDEX, family);
|
||||
return Fvconcat (1, &val);
|
||||
XSETCDR (slot, list);
|
||||
err:
|
||||
if (pat) FcPatternDestroy (pat);
|
||||
if (pattern) FcPatternDestroy (pattern);
|
||||
if (fontset) FcFontSetDestroy (fontset);
|
||||
if (objset) FcObjectSetDestroy (objset);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
|
||||
static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
|
||||
static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
|
||||
static Lisp_Object ftfont_list_family P_ ((Lisp_Object));
|
||||
static void ftfont_free_entity P_ ((Lisp_Object));
|
||||
static struct font *ftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
|
||||
static Lisp_Object ftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
|
||||
static void ftfont_close P_ ((FRAME_PTR, struct font *));
|
||||
static int ftfont_has_char P_ ((Lisp_Object, int));
|
||||
static unsigned ftfont_encode_char P_ ((struct font *, int));
|
||||
@ -282,11 +264,12 @@ static Lisp_Object ftfont_shape P_ ((Lisp_Object));
|
||||
struct font_driver ftfont_driver =
|
||||
{
|
||||
0, /* Qfreetype */
|
||||
0, /* case insensitive */
|
||||
ftfont_get_cache,
|
||||
ftfont_list,
|
||||
ftfont_match,
|
||||
ftfont_list_family,
|
||||
ftfont_free_entity,
|
||||
NULL,
|
||||
ftfont_open,
|
||||
ftfont_close,
|
||||
/* We can't draw a text without device dependent functions. */
|
||||
@ -409,41 +392,41 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec)
|
||||
return spec;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
ftfont_list (frame, spec)
|
||||
Lisp_Object frame, spec;
|
||||
static FcPattern *
|
||||
ftfont_spec_pattern (spec, otlayout, otspec)
|
||||
Lisp_Object spec;
|
||||
char *otlayout;
|
||||
struct OpenTypeSpec **otspec;
|
||||
{
|
||||
Lisp_Object val, tmp, extra;
|
||||
int i;
|
||||
FcPattern *pattern = NULL;
|
||||
FcCharSet *charset = NULL;
|
||||
FcLangSet *langset = NULL;
|
||||
FcFontSet *fontset = NULL;
|
||||
FcObjectSet *objset = NULL;
|
||||
Lisp_Object script;
|
||||
Lisp_Object registry = Qunicode_bmp;
|
||||
struct OpenTypeSpec *otspec= NULL;
|
||||
int weight = 0;
|
||||
double dpi = -1;
|
||||
int n;
|
||||
int dpi = -1;
|
||||
int spacing = -1;
|
||||
int scalable = -1;
|
||||
char otlayout[15]; /* For "otlayout:XXXX" */
|
||||
|
||||
val = null_vector;
|
||||
|
||||
if (! fc_initialized)
|
||||
{
|
||||
FcInit ();
|
||||
fc_initialized = 1;
|
||||
}
|
||||
Lisp_Object name = Qnil;
|
||||
Lisp_Object script = Qnil;
|
||||
Lisp_Object registry = Qunicode_bmp;
|
||||
|
||||
if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
|
||||
&& ! EQ (AREF (spec, FONT_ADSTYLE_INDEX), null_string))
|
||||
return val;
|
||||
if (! NILP (AREF (spec, FONT_SLANT_INDEX))
|
||||
&& XINT (AREF (spec, FONT_SLANT_INDEX)) < 100)
|
||||
&& SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
|
||||
/* Fontconfig doesn't support adstyle property. */
|
||||
return NULL;
|
||||
if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
|
||||
&& n < 100)
|
||||
/* Fontconfig doesn't support reverse-italic/obligue. */
|
||||
return val;
|
||||
return NULL;
|
||||
|
||||
if (INTEGERP (AREF (spec, FONT_DPI_INDEX)))
|
||||
dpi = XINT (AREF (spec, FONT_DPI_INDEX));
|
||||
if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
|
||||
spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
|
||||
if (INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
|
||||
&& XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
|
||||
scalable = 1;
|
||||
|
||||
if (! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
|
||||
{
|
||||
@ -452,34 +435,27 @@ ftfont_list (frame, spec)
|
||||
{
|
||||
if (! cs_iso8859_1
|
||||
&& ftfont_build_basic_charsets () < 0)
|
||||
return Qnil;
|
||||
return NULL;
|
||||
charset = cs_iso8859_1;
|
||||
}
|
||||
else if (! EQ (registry, Qiso10646_1)
|
||||
&& ! EQ (registry, Qunicode_bmp)
|
||||
&& ! EQ (registry, Qunicode_sip))
|
||||
return val;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
otlayout[0] = '\0';
|
||||
script = Qnil;
|
||||
for (extra = AREF (spec, FONT_EXTRA_INDEX);
|
||||
CONSP (extra); extra = XCDR (extra))
|
||||
{
|
||||
Lisp_Object key, val;
|
||||
|
||||
tmp = XCAR (extra);
|
||||
key = XCAR (tmp), val = XCDR (tmp);
|
||||
if (EQ (key, QCotf))
|
||||
{
|
||||
otspec = ftfont_get_open_type_spec (val);
|
||||
if (! otspec)
|
||||
return null_vector;
|
||||
strcat (otlayout, "otlayout:");
|
||||
OTF_TAG_STR (otspec->script_tag, otlayout + 9);
|
||||
script = otspec->script;
|
||||
}
|
||||
else if (EQ (key, QClanguage))
|
||||
key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
|
||||
if (EQ (key, QCdpi))
|
||||
dpi = XINT (val);
|
||||
else if (EQ (key, QCfc_unknown_spec))
|
||||
name = val;
|
||||
else if (EQ (key, QClang))
|
||||
{
|
||||
langset = FcLangSetCreate ();
|
||||
if (! langset)
|
||||
@ -495,12 +471,19 @@ ftfont_list (frame, spec)
|
||||
&& ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
|
||||
goto err;
|
||||
}
|
||||
else if (EQ (key, QCname))
|
||||
name = val;
|
||||
else if (EQ (key, QCotf))
|
||||
{
|
||||
*otspec = ftfont_get_open_type_spec (val);
|
||||
if (! *otspec)
|
||||
return NULL;
|
||||
strcat (otlayout, "otlayout:");
|
||||
OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
|
||||
script = (*otspec)->script;
|
||||
}
|
||||
else if (EQ (key, QCscript))
|
||||
script = val;
|
||||
else if (EQ (key, QCdpi))
|
||||
dpi = XINT (val);
|
||||
else if (EQ (key, QCspacing))
|
||||
spacing = XINT (val);
|
||||
else if (EQ (key, QCscalable))
|
||||
scalable = ! NILP (val);
|
||||
}
|
||||
@ -521,32 +504,15 @@ ftfont_list (frame, spec)
|
||||
}
|
||||
}
|
||||
|
||||
pattern = FcPatternCreate ();
|
||||
pattern = NILP (name) ? FcPatternCreate () : FcNameParse (SDATA (name));
|
||||
if (! pattern)
|
||||
goto err;
|
||||
FcPatternDel (pattern, FC_SIZE);
|
||||
FcPatternDel (pattern, FC_PIXEL_SIZE);
|
||||
tmp = AREF (spec, FONT_FOUNDRY_INDEX);
|
||||
if (SYMBOLP (tmp) && ! NILP (tmp)
|
||||
if (! NILP (tmp)
|
||||
&& ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
|
||||
goto err;
|
||||
tmp = AREF (spec, FONT_FAMILY_INDEX);
|
||||
if (SYMBOLP (tmp) && ! NILP (tmp)
|
||||
&& ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
|
||||
goto err;
|
||||
/* Emacs conventionally doesn't distinguish normal, regular, and
|
||||
medium weight, but fontconfig does. So, we can't restrict font
|
||||
listing by weight. We check it after getting a list. */
|
||||
tmp = AREF (spec, FONT_WEIGHT_INDEX);
|
||||
if (INTEGERP (tmp))
|
||||
weight = XINT (tmp);
|
||||
tmp = AREF (spec, FONT_SLANT_INDEX);
|
||||
if (INTEGERP (tmp)
|
||||
&& ! FcPatternAddInteger (pattern, FC_SLANT, XINT (tmp) - 100))
|
||||
goto err;
|
||||
tmp = AREF (spec, FONT_WIDTH_INDEX);
|
||||
if (INTEGERP (tmp)
|
||||
&& ! FcPatternAddInteger (pattern, FC_WIDTH, XINT (tmp)))
|
||||
goto err;
|
||||
|
||||
if (charset
|
||||
&& ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
|
||||
goto err;
|
||||
@ -562,65 +528,100 @@ ftfont_list (frame, spec)
|
||||
if (scalable >= 0
|
||||
&& ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
|
||||
goto err;
|
||||
goto finish;
|
||||
|
||||
err:
|
||||
/* We come here because of unexpected error in fontconfig API call
|
||||
(usually insufficient memory). */
|
||||
if (pattern)
|
||||
{
|
||||
FcPatternDestroy (pattern);
|
||||
pattern = NULL;
|
||||
}
|
||||
if (*otspec)
|
||||
{
|
||||
if ((*otspec)->nfeatures[0] > 0)
|
||||
free ((*otspec)->features[0]);
|
||||
if ((*otspec)->nfeatures[1] > 0)
|
||||
free ((*otspec)->features[1]);
|
||||
free (*otspec);
|
||||
*otspec = NULL;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (charset && charset != cs_iso8859_1) FcCharSetDestroy (charset);
|
||||
if (langset) FcLangSetDestroy (langset);
|
||||
return pattern;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
ftfont_list (frame, spec)
|
||||
Lisp_Object frame, spec;
|
||||
{
|
||||
Lisp_Object val, tmp, registry, family, family_list;
|
||||
int i;
|
||||
FcPattern *pattern;
|
||||
FcFontSet *fontset = NULL;
|
||||
FcObjectSet *objset = NULL;
|
||||
double pixel_size = 0;
|
||||
int weight = -1, slant = -1, width = -1;
|
||||
double dpi = -1;
|
||||
int spacing = -1;
|
||||
int scalable = -1;
|
||||
char otlayout[15]; /* For "otlayout:XXXX" */
|
||||
struct OpenTypeSpec *otspec = NULL;
|
||||
|
||||
if (! fc_initialized)
|
||||
{
|
||||
FcInit ();
|
||||
fc_initialized = 1;
|
||||
}
|
||||
|
||||
pattern = ftfont_spec_pattern (spec, otlayout, &otspec);
|
||||
if (! pattern)
|
||||
return Qnil;
|
||||
objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
|
||||
FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING,
|
||||
FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
|
||||
FC_CHARSET, FC_FILE,
|
||||
#ifdef FC_CAPABILITY
|
||||
FC_CAPABILITY,
|
||||
#endif /* FC_CAPABILITY */
|
||||
#ifdef FC_FONTFORMAT
|
||||
FC_FONTFORMAT,
|
||||
#endif /* FC_FONTFORMAT */
|
||||
NULL);
|
||||
if (! objset)
|
||||
goto err;
|
||||
if (otlayout[0])
|
||||
|
||||
registry = AREF (spec, FONT_REGISTRY_INDEX);
|
||||
family = AREF (spec, FONT_FAMILY_INDEX);
|
||||
if (NILP (family))
|
||||
family_list = Fcons (Qnil, Qnil);
|
||||
else
|
||||
{
|
||||
#ifdef FC_CAPABILITY
|
||||
if (! FcObjectSetAdd (objset, FC_CAPABILITY))
|
||||
goto err;
|
||||
#else /* not FC_CAPABILITY */
|
||||
goto finish;
|
||||
#endif /* not FC_CAPABILITY */
|
||||
family_list = ftfont_list_generic_family (family);
|
||||
if (NILP (family_list))
|
||||
family_list = Fcons (family, Qnil);
|
||||
}
|
||||
|
||||
fontset = FcFontList (NULL, pattern, objset);
|
||||
if (! fontset)
|
||||
goto err;
|
||||
|
||||
if (fontset->nfont > 0)
|
||||
for (val = Qnil; CONSP (family_list); family_list = XCDR (family_list))
|
||||
{
|
||||
double pixel_size;
|
||||
|
||||
if (NILP (AREF (spec, FONT_SIZE_INDEX)))
|
||||
pixel_size = 0;
|
||||
else
|
||||
pixel_size = XINT (AREF (spec, FONT_SIZE_INDEX));
|
||||
|
||||
for (i = 0, val = Qnil; i < fontset->nfont; i++)
|
||||
family = XCAR (family_list);
|
||||
if (! NILP (family))
|
||||
{
|
||||
FcPatternDel (pattern, FC_FAMILY);
|
||||
if (! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family)))
|
||||
goto err;
|
||||
}
|
||||
fontset = FcFontList (NULL, pattern, objset);
|
||||
if (! fontset)
|
||||
goto err;
|
||||
for (i = 0; i < fontset->nfont; i++)
|
||||
{
|
||||
Lisp_Object entity;
|
||||
int n;
|
||||
double dbl;
|
||||
|
||||
if (pixel_size > 0)
|
||||
{
|
||||
double this;
|
||||
|
||||
if (FcPatternGetDouble (fontset->fonts[i], FC_PIXEL_SIZE, 0,
|
||||
&this) == FcResultMatch
|
||||
&& ((this < pixel_size - FONT_PIXEL_SIZE_QUANTUM)
|
||||
|| (this > pixel_size + FONT_PIXEL_SIZE_QUANTUM)))
|
||||
continue;
|
||||
}
|
||||
if (weight > 0)
|
||||
{
|
||||
int this;
|
||||
|
||||
if (FcPatternGetInteger (fontset->fonts[i], FC_WEIGHT, 0,
|
||||
&this) != FcResultMatch
|
||||
|| (this != weight
|
||||
&& (weight != 100
|
||||
|| this < FC_WEIGHT_REGULAR
|
||||
|| this > FC_WEIGHT_MEDIUM)))
|
||||
continue;
|
||||
}
|
||||
#ifdef FC_CAPABILITY
|
||||
if (otlayout[0])
|
||||
{
|
||||
@ -655,14 +656,13 @@ ftfont_list (frame, spec)
|
||||
continue;
|
||||
}
|
||||
#endif /* HAVE_LIBOTF */
|
||||
entity = ftfont_pattern_entity (fontset->fonts[i], frame, registry);
|
||||
entity = ftfont_pattern_entity (fontset->fonts[i], registry);
|
||||
if (! NILP (entity))
|
||||
val = Fcons (entity, val);
|
||||
}
|
||||
val = Fvconcat (1, &val);
|
||||
FcFontSetDestroy (fontset);
|
||||
fontset = NULL;
|
||||
}
|
||||
else if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
|
||||
val = ftfont_list_generic_family (spec, frame, registry);
|
||||
goto finish;
|
||||
|
||||
err:
|
||||
@ -671,19 +671,9 @@ ftfont_list (frame, spec)
|
||||
val = Qnil;
|
||||
|
||||
finish:
|
||||
if (charset && charset != cs_iso8859_1) FcCharSetDestroy (charset);
|
||||
if (objset) FcObjectSetDestroy (objset);
|
||||
if (fontset) FcFontSetDestroy (fontset);
|
||||
if (langset) FcLangSetDestroy (langset);
|
||||
if (pattern) FcPatternDestroy (pattern);
|
||||
if (otspec)
|
||||
{
|
||||
if (otspec->nfeatures[0] > 0)
|
||||
free (otspec->features[0]);
|
||||
if (otspec->nfeatures[1] > 0)
|
||||
free (otspec->features[1]);
|
||||
free (otspec);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -692,8 +682,10 @@ ftfont_match (frame, spec)
|
||||
Lisp_Object frame, spec;
|
||||
{
|
||||
Lisp_Object extra, val, entity;
|
||||
FcPattern *pattern = NULL, *match = NULL;
|
||||
FcPattern *pattern, *match = NULL;
|
||||
FcResult result;
|
||||
char otlayout[15]; /* For "otlayout:XXXX" */
|
||||
struct OpenTypeSpec *otspec = NULL;
|
||||
|
||||
if (! fc_initialized)
|
||||
{
|
||||
@ -701,35 +693,35 @@ ftfont_match (frame, spec)
|
||||
fc_initialized = 1;
|
||||
}
|
||||
|
||||
extra = AREF (spec, FONT_EXTRA_INDEX);
|
||||
val = assq_no_quit (QCname, extra);
|
||||
if (! CONSP (val) || ! STRINGP (XCDR (val)))
|
||||
pattern = ftfont_spec_pattern (spec, otlayout, &otspec);
|
||||
if (! pattern)
|
||||
return Qnil;
|
||||
|
||||
entity = Qnil;
|
||||
pattern = FcNameParse (SDATA (XCDR (val)));
|
||||
if (pattern)
|
||||
if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
|
||||
{
|
||||
if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
|
||||
{
|
||||
FcValue value;
|
||||
FcValue value;
|
||||
|
||||
value.type = FcTypeDouble;
|
||||
value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
|
||||
FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
|
||||
}
|
||||
if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
|
||||
{
|
||||
FcDefaultSubstitute (pattern);
|
||||
match = FcFontMatch (NULL, pattern, &result);
|
||||
if (match)
|
||||
{
|
||||
entity = ftfont_pattern_entity (match, frame, Qunicode_bmp);
|
||||
FcPatternDestroy (match);
|
||||
}
|
||||
}
|
||||
FcPatternDestroy (pattern);
|
||||
value.type = FcTypeDouble;
|
||||
value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
|
||||
FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
|
||||
}
|
||||
if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
|
||||
{
|
||||
FcDefaultSubstitute (pattern);
|
||||
match = FcFontMatch (NULL, pattern, &result);
|
||||
if (match)
|
||||
{
|
||||
entity = ftfont_pattern_entity (match, Qunicode_bmp);
|
||||
FcPatternDestroy (match);
|
||||
if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
|
||||
&& NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
|
||||
ftfont_generic_family_list))
|
||||
&& NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
|
||||
AREF (entity, FONT_FAMILY_INDEX))))
|
||||
entity = Qnil;
|
||||
}
|
||||
}
|
||||
FcPatternDestroy (pattern);
|
||||
|
||||
return entity;
|
||||
}
|
||||
@ -767,8 +759,7 @@ ftfont_list_family (frame)
|
||||
FcChar8 *str;
|
||||
|
||||
if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
|
||||
list = Fcons (intern_downcase ((char *) str, strlen ((char *) str)),
|
||||
list);
|
||||
list = Fcons (intern ((char *) str), list);
|
||||
}
|
||||
|
||||
finish:
|
||||
@ -780,17 +771,7 @@ ftfont_list_family (frame)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ftfont_free_entity (entity)
|
||||
Lisp_Object entity;
|
||||
{
|
||||
Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
|
||||
FcPattern *pattern = XSAVE_VALUE (val)->pointer;
|
||||
|
||||
FcPatternDestroy (pattern);
|
||||
}
|
||||
|
||||
static struct font *
|
||||
static Lisp_Object
|
||||
ftfont_open (f, entity, pixel_size)
|
||||
FRAME_PTR f;
|
||||
Lisp_Object entity;
|
||||
@ -801,42 +782,45 @@ ftfont_open (f, entity, pixel_size)
|
||||
FT_Face ft_face;
|
||||
FT_Size ft_size;
|
||||
FT_UInt size;
|
||||
Lisp_Object val;
|
||||
Lisp_Object val, font_object;
|
||||
FcPattern *pattern;
|
||||
FcChar8 *file;
|
||||
FcChar8 *file = NULL, *fmt = NULL;
|
||||
FcBool scalable;
|
||||
int spacing;
|
||||
char *name;
|
||||
int len;
|
||||
char name[256];
|
||||
int i, len;
|
||||
int upEM;
|
||||
|
||||
val = AREF (entity, FONT_EXTRA_INDEX);
|
||||
if (XTYPE (val) != Lisp_Misc
|
||||
|| XMISCTYPE (val) != Lisp_Misc_Save_Value)
|
||||
return NULL;
|
||||
val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
|
||||
if (! CONSP (val))
|
||||
return Qnil;
|
||||
val = XCDR (val);
|
||||
pattern = XSAVE_VALUE (val)->pointer;
|
||||
if (XSAVE_VALUE (val)->integer == 0)
|
||||
{
|
||||
/* We have not yet created FT_Face for this font. */
|
||||
if (! ft_library
|
||||
&& FT_Init_FreeType (&ft_library) != 0)
|
||||
return NULL;
|
||||
return Qnil;
|
||||
if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
|
||||
return NULL;
|
||||
return Qnil;
|
||||
if (FT_New_Face (ft_library, (char *) file, 0, &ft_face) != 0)
|
||||
return NULL;
|
||||
return Qnil;
|
||||
FcPatternAddFTFace (pattern, FC_FT_FACE, ft_face);
|
||||
ft_size = ft_face->size;
|
||||
XSAVE_VALUE (val)->integer++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
|
||||
!= FcResultMatch)
|
||||
return NULL;
|
||||
return Qnil;
|
||||
if (FT_New_Size (ft_face, &ft_size) != 0)
|
||||
return NULL;
|
||||
return Qnil;
|
||||
if (FT_Activate_Size (ft_size) != 0)
|
||||
{
|
||||
FT_Done_Size (ft_size);
|
||||
return NULL;
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
@ -847,84 +831,99 @@ ftfont_open (f, entity, pixel_size)
|
||||
{
|
||||
if (XSAVE_VALUE (val)->integer == 0)
|
||||
FT_Done_Face (ft_face);
|
||||
return NULL;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
ftfont_info = malloc (sizeof (struct ftfont_info));
|
||||
if (! ftfont_info)
|
||||
return NULL;
|
||||
font_object = font_make_object (VECSIZE (struct ftfont_info));
|
||||
ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
|
||||
for (i = 1;i < FONT_ENTITY_MAX; i++)
|
||||
ASET (font_object, i, AREF (entity, i));
|
||||
ASET (font_object, FONT_SIZE_INDEX, make_number (size));
|
||||
len = font_unparse_xlfd (entity, size, name, 256);
|
||||
if (len > 0)
|
||||
ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
|
||||
len = font_unparse_fcname (entity, size, name, 256);
|
||||
if (len > 0)
|
||||
ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
|
||||
else
|
||||
ASET (font_object, FONT_FULLNAME_INDEX,
|
||||
AREF (font_object, FONT_NAME_INDEX));
|
||||
if (! file
|
||||
&& ! FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
|
||||
return Qnil;
|
||||
ASET (font_object, FONT_FILE_INDEX,
|
||||
make_unibyte_string ((char *) file, strlen ((char *) file)));
|
||||
ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (pattern));
|
||||
font = XFONT_OBJECT (font_object);
|
||||
ftfont_info = (struct ftfont_info *) font;
|
||||
ftfont_info->ft_size = ft_size;
|
||||
#ifdef HAVE_LIBOTF
|
||||
ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
|
||||
ftfont_info->otf = NULL;
|
||||
#endif /* HAVE_LIBOTF */
|
||||
|
||||
font = (struct font *) ftfont_info;
|
||||
font->format = ftfont_font_format (pattern);
|
||||
font->entity = entity;
|
||||
font->pixel_size = size;
|
||||
font->driver = &ftfont_driver;
|
||||
len = 96;
|
||||
name = malloc (len);
|
||||
while (name && font_unparse_fcname (entity, pixel_size, name, len) < 0)
|
||||
{
|
||||
char *new = realloc (name, len += 32);
|
||||
font->encoding_charset = font->repertory_charset = -1;
|
||||
|
||||
if (! new)
|
||||
free (name);
|
||||
name = new;
|
||||
upEM = ft_face->units_per_EM;
|
||||
if (! FcPatternGetBool (pattern, FC_SCALABLE, 0, &scalable) == FcResultMatch)
|
||||
scalable = FcFalse;
|
||||
if (scalable)
|
||||
{
|
||||
font->ascent = ft_face->ascender * size / upEM;
|
||||
font->descent = - ft_face->descender * size / upEM;
|
||||
font->height = ft_face->height * size / upEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
font->ascent = ft_face->size->metrics.ascender >> 6;
|
||||
font->descent = - ft_face->size->metrics.descender >> 6;
|
||||
font->height = ft_face->size->metrics.height >> 6;
|
||||
}
|
||||
font->font.full_name = font->font.name = name;
|
||||
font->file_name = (char *) file;
|
||||
font->font.size = ft_face->size->metrics.max_advance >> 6;
|
||||
if (font->font.size <= 0)
|
||||
font->font.size = size;
|
||||
font->font.charset = font->encoding_charset = font->repertory_charset = -1;
|
||||
font->ascent = ft_face->size->metrics.ascender >> 6;
|
||||
font->descent = - ft_face->size->metrics.descender >> 6;
|
||||
font->font.height = font->ascent + font->descent;
|
||||
if (FcPatternGetInteger (pattern, FC_SPACING, 0, &spacing) != FcResultMatch)
|
||||
spacing = FC_PROPORTIONAL;
|
||||
if (spacing != FC_PROPORTIONAL)
|
||||
font->font.average_width = font->font.space_width = font->font.size;
|
||||
font->min_width = font->average_width = font->space_width
|
||||
= (scalable ? ft_face->max_advance_width * size / upEM
|
||||
: ft_face->size->metrics.max_advance >> 6);
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
|
||||
font->font.average_width = font->font.space_width = 0;
|
||||
for (i = 32; i < 127; i++)
|
||||
{
|
||||
if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) != 0)
|
||||
break;
|
||||
if (i == 32)
|
||||
font->font.space_width = ft_face->glyph->metrics.horiAdvance >> 6;
|
||||
font->font.average_width += ft_face->glyph->metrics.horiAdvance >> 6;
|
||||
}
|
||||
if (i == 127)
|
||||
{
|
||||
/* The font contains all ASCII printable characters. */
|
||||
font->font.average_width /= 95;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == 32)
|
||||
font->font.space_width = font->font.size;
|
||||
font->font.average_width = font->font.size;
|
||||
}
|
||||
font->min_width = font->average_width = font->space_width = 0;
|
||||
for (i = 32, n = 0; i < 127; i++)
|
||||
if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) != 0)
|
||||
{
|
||||
int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
|
||||
|
||||
if (this_width > 0
|
||||
&& (! font->min_width || font->min_width > this_width))
|
||||
font->min_width = this_width;
|
||||
if (i == 32)
|
||||
font->space_width = this_width;
|
||||
font->average_width += this_width;
|
||||
n++;
|
||||
}
|
||||
if (n > 0)
|
||||
font->average_width /= n;
|
||||
}
|
||||
|
||||
/* Unfortunately FreeType doesn't provide a way to get minimum char
|
||||
width. So, we use space_width instead. */
|
||||
font->min_width = font->font.space_width;
|
||||
font->baseline_offset = 0;
|
||||
font->relative_compose = 0;
|
||||
font->default_ascent = 0;
|
||||
font->vertical_centering = 0;
|
||||
if (scalable)
|
||||
{
|
||||
font->underline_position = -ft_face->underline_position * size / upEM;
|
||||
font->underline_thickness = -ft_face->underline_thickness * size / upEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
font->underline_position = -1;
|
||||
font->underline_thickness = 0;
|
||||
}
|
||||
|
||||
font->font.baseline_offset = 0;
|
||||
font->font.relative_compose = 0;
|
||||
font->font.default_ascent = 0;
|
||||
font->font.vertical_centering = 0;
|
||||
|
||||
(XSAVE_VALUE (val)->integer)++;
|
||||
|
||||
return font;
|
||||
return font_object;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -933,9 +932,10 @@ ftfont_close (f, font)
|
||||
struct font *font;
|
||||
{
|
||||
struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
|
||||
Lisp_Object entity = font->entity;
|
||||
Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
|
||||
Lisp_Object val;
|
||||
|
||||
val = assq_no_quit (QCfont_entity, font->props[FONT_EXTRA_INDEX]);
|
||||
val = XCDR (val);
|
||||
(XSAVE_VALUE (val)->integer)--;
|
||||
if (XSAVE_VALUE (val)->integer == 0)
|
||||
{
|
||||
@ -947,8 +947,6 @@ ftfont_close (f, font)
|
||||
}
|
||||
else
|
||||
FT_Done_Size (ftfont_info->ft_size);
|
||||
|
||||
free (font);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -960,7 +958,8 @@ ftfont_has_char (entity, c)
|
||||
FcPattern *pattern;
|
||||
FcCharSet *charset;
|
||||
|
||||
val = AREF (entity, FONT_EXTRA_INDEX);
|
||||
val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
|
||||
val = XCDR (val);
|
||||
pattern = XSAVE_VALUE (val)->pointer;
|
||||
if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
|
||||
return -1;
|
||||
@ -1019,7 +1018,7 @@ ftfont_text_extents (font, code, nglyphs, metrics)
|
||||
}
|
||||
else
|
||||
{
|
||||
width += font->font.space_width;
|
||||
width += font->space_width;
|
||||
}
|
||||
}
|
||||
if (metrics)
|
||||
@ -1161,7 +1160,7 @@ ftfont_get_metrics (font, gstring, from, to)
|
||||
else
|
||||
{
|
||||
g->lbearing = 0;
|
||||
g->rbearing = g->xadv = flt_font_ft->font->font.space_width << 6;
|
||||
g->rbearing = g->xadv = flt_font_ft->font->space_width << 6;
|
||||
g->ascent = flt_font_ft->font->ascent << 6;
|
||||
g->descent = flt_font_ft->font->descent << 6;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user