};
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))
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;
FcChar8 *str;
int numeric;
double dbl;
+ FcBool b;
if (FcPatternGetString (p, FC_FILE, 0, &file) != FcResultMatch)
return Qnil;
#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;
|| (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;
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)
- goto err;
- pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString,
- SYMBOL_FcChar8 (family), (char *) 0);
- if (! pattern)
+ if (strcmp ((char *) fam, (char *) SYMBOL_FcChar8 (family)) == 0)
+ continue;
+ if (! FcPatternAddString (pat, FC_FAMILY, fam))
goto err;
- pat = FcPatternCreate ();
- if (! pat)
+ fontset = FcFontList (NULL, pat, objset);
+ if (! fontset)
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));
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. */
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)))
{
{
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)
&& ! 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);
}
}
}
- 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;
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])
{
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:
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;
}
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)
{
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)
+ 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)
{
- FcDefaultSubstitute (pattern);
- match = FcFontMatch (NULL, pattern, &result);
- if (match)
- {
- entity = ftfont_pattern_entity (match, frame, Qunicode_bmp);
- FcPatternDestroy (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);
}
+ FcPatternDestroy (pattern);
return entity;
}
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:
}
-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;
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;
}
}
{
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->font.baseline_offset = 0;
- font->font.relative_compose = 0;
- font->font.default_ascent = 0;
- font->font.vertical_centering = 0;
-
- (XSAVE_VALUE (val)->integer)++;
+ 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;
+ }
- return font;
+ return font_object;
}
static void
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)
{
}
else
FT_Done_Size (ftfont_info->ft_size);
-
- free (font);
}
static int
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;
}
else
{
- width += font->font.space_width;
+ width += font->space_width;
}
}
if (metrics)
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;
}