summaryrefslogtreecommitdiff
path: root/src/xfaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xfaces.c')
-rw-r--r--src/xfaces.c90
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);