Improve resetting face attributes when looking for suitable fonts

* src/xfaces.c (syms_of_xfaces)<face-font-lax-matched-attributes>:
Change the default value to t.  Update doc string.
(realize_gui_face): When 'Vface_font_lax_matched_attributes' is t,
reset the 3 default font attributes efficiently.  Call
'font_maybe_unset_attribute' only if the value is neither nil nor
t.  (Bug#59347)
This commit is contained in:
Eli Zaretskii 2022-12-13 17:35:17 +02:00
parent c4b8bc90a8
commit 4ef8b9f544

View file

@ -6023,6 +6023,8 @@ font_maybe_unset_attribute (Lisp_Object font_object,
{ {
Lisp_Object tail = Vface_font_lax_matched_attributes; Lisp_Object tail = Vface_font_lax_matched_attributes;
eassert (CONSP (tail));
FOR_EACH_TAIL_SAFE (tail) FOR_EACH_TAIL_SAFE (tail)
{ {
if (EQ (XCAR (tail), symbol)) if (EQ (XCAR (tail), symbol))
@ -6100,20 +6102,31 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
fonts that are exact matches for these weight, slant, and fonts that are exact matches for these weight, slant, and
width attributes, which could lead to suboptimal or wrong width attributes, which could lead to suboptimal or wrong
font selection. (bug#5934) */ font selection. (bug#5934) */
font_maybe_unset_attribute (spec, FONT_WEIGHT_INDEX, QCweight); if (EQ (Vface_font_lax_matched_attributes, Qt))
font_maybe_unset_attribute (spec, FONT_SLANT_INDEX, QCslant); {
font_maybe_unset_attribute (spec, FONT_WIDTH_INDEX, QCwidth); /* The default case: clear the font attributes that
/* Also allow unsetting other attributes for debugging affect its appearance the least, to try to find some
purposes. But not FONT_EXTRA_INDEX; that is not safe to font that is close, if not exact, match. */
touch, at least in the Haiku font backend. */ ASET (spec, FONT_WEIGHT_INDEX, Qnil);
font_maybe_unset_attribute (spec, FONT_FAMILY_INDEX, QCfamily); ASET (spec, FONT_SLANT_INDEX, Qnil);
font_maybe_unset_attribute (spec, FONT_FOUNDRY_INDEX, QCfoundry); ASET (spec, FONT_WIDTH_INDEX, Qnil);
font_maybe_unset_attribute (spec, FONT_REGISTRY_INDEX, QCregistry); }
font_maybe_unset_attribute (spec, FONT_ADSTYLE_INDEX, QCadstyle); else if (!NILP (Vface_font_lax_matched_attributes))
font_maybe_unset_attribute (spec, FONT_SIZE_INDEX, QCsize); {
font_maybe_unset_attribute (spec, FONT_DPI_INDEX, QCdpi); /* Also allow unsetting specific attributes for
font_maybe_unset_attribute (spec, FONT_SPACING_INDEX, QCspacing); debugging purposes. */
font_maybe_unset_attribute (spec, FONT_AVGWIDTH_INDEX, QCavgwidth); 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); attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec);
} }
@ -7406,22 +7419,32 @@ clear the face cache, see `clear-face-cache'. */);
DEFVAR_LISP ("face-font-lax-matched-attributes", DEFVAR_LISP ("face-font-lax-matched-attributes",
Vface_font_lax_matched_attributes, Vface_font_lax_matched_attributes,
doc: /* Font-related face attributes to match in lax manner when realizing faces. doc: /* Whether to match some face attributes in lax manner when realizing faces.
The value should be a list of font-related face attribute symbols; If non-nil, some font-related face attributes will be matched in a lax
see `set-face-attribute' for the full list of attributes. The 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 corresponding face attributes will be treated as "soft" constraints
when looking for suitable fonts: if an exact match is not possible, in the manner described above, instead of the default 3 attributes.
a font can be selected that is a close, but not an exact, match. For
example, looking for a semi-bold font might select a bold or a medium
font if no semi-bold font matching other attributes is found. Emacs
still tries to find a font that is the closest possible match; in
particular, if a font is available that matches the face attributes
exactly, it will be selected.
Note that if the `:extra' attribute is present in the value, it If the value is nil, candidate fonts might be rejected if the don't
will be ignored. */); have exactly the same values of attributes as the face requests.
Vface_font_lax_matched_attributes = list3 (QCweight, QCslant, QCwidth);
This variable exists for debugging of the font-selection process,
and we advise not to change it othersie. */);
Vface_font_lax_matched_attributes = Qt;
#ifdef HAVE_WINDOW_SYSTEM #ifdef HAVE_WINDOW_SYSTEM
defsubr (&Sbitmap_spec_p); defsubr (&Sbitmap_spec_p);