diff options
Diffstat (limited to 'src/xfaces.c')
-rw-r--r-- | src/xfaces.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/src/xfaces.c b/src/xfaces.c index f96e538360b..0189e612128 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6013,6 +6013,23 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object, } #endif /* HAVE_WINDOW_SYSTEM */ +/* Remove the attribute at INDEX from the font object if SYMBOL + appears in `font-fallback-ignored-attributes'. */ + +static void +font_maybe_unset_attribute (Lisp_Object font_object, + enum font_property_index index, Lisp_Object symbol) +{ + Lisp_Object tail = Vface_font_lax_matched_attributes; + + eassert (CONSP (tail)); + + FOR_EACH_TAIL_SAFE (tail) + { + if (EQ (XCAR (tail), symbol)) + ASET (font_object, index, Qnil); + } +} /* Realize the fully-specified face with attributes ATTRS in face cache CACHE for ASCII characters. Do it for GUI frame CACHE->f. @@ -6070,8 +6087,48 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] emacs_abort (); } if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) - attrs[LFACE_FONT_INDEX] - = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]); + { + Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]); + + /* Maybe unset several values in SPEC, usually the width, + slant, and weight. The best possible values for these + attributes are determined in font_find_for_lface, called + by font_load_for_lface, when the list of candidate fonts + returned by font_list_entities is sorted by font_select_entity + (which calls font_sort_entities, which calls font_score). + If these attributes are not unset here, the candidate + font list returned by font_list_entities only contains + fonts that are exact matches for these weight, slant, and + width attributes, which could lead to suboptimal or wrong + font selection. (bug#5934) */ + if (EQ (Vface_font_lax_matched_attributes, Qt)) + { + /* The default case: clear the font attributes that + affect its appearance the least, to try to find some + font that is close, if not exact, match. */ + ASET (spec, FONT_WEIGHT_INDEX, Qnil); + ASET (spec, FONT_SLANT_INDEX, Qnil); + ASET (spec, FONT_WIDTH_INDEX, Qnil); + } + else if (!NILP (Vface_font_lax_matched_attributes)) + { + /* Also allow unsetting specific attributes for + debugging purposes. */ + font_maybe_unset_attribute (spec, FONT_WEIGHT_INDEX, QCweight); + font_maybe_unset_attribute (spec, FONT_SLANT_INDEX, QCslant); + font_maybe_unset_attribute (spec, FONT_WIDTH_INDEX, QCwidth); + font_maybe_unset_attribute (spec, FONT_FAMILY_INDEX, QCfamily); + font_maybe_unset_attribute (spec, FONT_FOUNDRY_INDEX, QCfoundry); + font_maybe_unset_attribute (spec, FONT_REGISTRY_INDEX, QCregistry); + font_maybe_unset_attribute (spec, FONT_ADSTYLE_INDEX, QCadstyle); + font_maybe_unset_attribute (spec, FONT_SIZE_INDEX, QCsize); + font_maybe_unset_attribute (spec, FONT_DPI_INDEX, QCdpi); + font_maybe_unset_attribute (spec, FONT_SPACING_INDEX, QCspacing); + font_maybe_unset_attribute (spec, FONT_AVGWIDTH_INDEX, QCavgwidth); + } + + attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec); + } if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) { face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]); @@ -7359,6 +7416,35 @@ Lisp programs that change the value of this variable should also clear the face cache, see `clear-face-cache'. */); face_near_same_color_threshold = 30000; + DEFVAR_LISP ("face-font-lax-matched-attributes", + Vface_font_lax_matched_attributes, + doc: /* Whether to match some face attributes in lax manner when realizing faces. + +If non-nil, some font-related face attributes will be matched in a lax +manner when looking for candidate fonts. +If the value is t, the default, the search for fonts will not insist +on exact match for 3 font attributes: weight, width, and slant. +Instead, it will examine the available fonts with various values of +these attributes, and select the font that is the closest possible +match. (If an exact match is available, it will still be selected, +as that is the closest match.) For example, looking for a semi-bold +font might select a bold or a medium-weight font if no semi-bold font +matching other attributes can be found. This is especially important +when the `default' face specifies unusual values for one or more of +these 3 attributes, which other installed fonts don't support. + +The value can also be a list of font-related face attribute symbols; +see `set-face-attribute' for the full list of attributes. Then the +corresponding face attributes will be treated as "soft" constraints +in the manner described above, instead of the default 3 attributes. + +If the value is nil, candidate fonts might be rejected if the don't +have exactly the same values of attributes as the face requests. + +This variable exists for debugging of the font-selection process, +and we advise not to change it otherwise. */); + Vface_font_lax_matched_attributes = Qt; + #ifdef HAVE_WINDOW_SYSTEM defsubr (&Sbitmap_spec_p); defsubr (&Sx_list_fonts); |