Mercurial > emacs
changeset 94931:37f386db63ed
(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.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Wed, 14 May 2008 01:28:01 +0000 |
parents | aa7f14981acf |
children | 4ac20761f264 |
files | src/ftfont.c |
diffstat | 1 files changed, 332 insertions(+), 333 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ftfont.c Wed May 14 01:27:45 2008 +0000 +++ b/src/ftfont.c Wed May 14 01:28:01 2008 +0000 @@ -71,10 +71,8 @@ }; 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 @@ 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 @@ FcChar8 *str; int numeric; double dbl; + FcBool b; if (FcPatternGetString (p, FC_FILE, 0, &file) != FcResultMatch) return Qnil; @@ -120,38 +121,48 @@ #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 @@ || (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 @@ 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)) - { - /* Not yet listed. */ - FcObjectSet *objset = NULL; - FcPattern *pattern = NULL, *pat = NULL; - FcFontSet *fontset = NULL; - FcChar8 *fam; - int i, j; + if (! EQ (list, Qt)) + return list; - 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) - goto err; - pat = FcPatternCreate (); - if (! pat) + 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++) + { + if (strcmp ((char *) fam, (char *) SYMBOL_FcChar8 (family)) == 0) + continue; + if (! FcPatternAddString (pat, FC_FAMILY, fam)) 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; + fontset = FcFontList (NULL, pat, objset); + if (! fontset) + goto err; + 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 @@ 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 @@ 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 @@ { 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 @@ && ! 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 @@ } } - 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 @@ 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; - - if (pixel_size > 0) - { - double this; + int n; + double dbl; - 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 @@ 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 @@ 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 @@ 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 @@ 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; + + 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) { - FcValue value; - - value.type = FcTypeDouble; - value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX)); - FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse); + 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; } - 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); } + FcPatternDestroy (pattern); return entity; } @@ -767,8 +759,7 @@ 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 @@ } -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 @@ 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 @@ { 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) + font->encoding_charset = font->repertory_charset = -1; + + upEM = ft_face->units_per_EM; + if (! FcPatternGetBool (pattern, FC_SCALABLE, 0, &scalable) == FcResultMatch) + scalable = FcFalse; + if (scalable) { - char *new = realloc (name, len += 32); - - if (! new) - free (name); - name = new; + font->ascent = ft_face->ascender * size / upEM; + font->descent = - ft_face->descender * size / upEM; + font->height = ft_face->height * size / upEM; } - 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; + 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; + } 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->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; - 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; - } + 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 @@ 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 @@ } else FT_Done_Size (ftfont_info->ft_size); - - free (font); } static int @@ -960,7 +958,8 @@ 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 @@ } else { - width += font->font.space_width; + width += font->space_width; } } if (metrics) @@ -1161,7 +1160,7 @@ 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; }