1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-18 18:05:07 +00:00

Unset the weight/slant/width in the spec when realizing a font

Between commits bf0d3f76dc (2014) and 6b1ed2f2c9 (2022),
realize_gui_face called font_load_for_lface with an empty or
partly emptied font spec, i.e. it ignored a part of its attrs
argument.  The rationale given in bug#17973, which led to
bf0d3f76dc, is not clear.  However, 6b1ed2f2c9, which passes
the full font spec to font_load_for_lface and
font_find_for_lface, leads to suboptimal font choices, for
example when the font chosen for the default face has a
weight, slant or width that is not supported by other
available fonts on the system, such as 'medium' or 'heavy'.

If these attributes are not unset here, the call to
font_list_entities in font_find_for_lface arbitrarily limits
the candidate font list to those that are perfect matches for
these attributes, which means that the scoring mechanism is
bypassed.  Note that the size attribute in spec is also unset,
in font_find_for_lface.

Also allow unsetting the other attributes, for debugging purposes.

* src/xfaces.c (realize_gui_face): Unset the weight, slant and
width of the font spec.  Fixes bug#57555 and bug#59347.
(syms_of_xfaces): New variable
'realize-gui-face-ignored-spec-attributes'.
This commit is contained in:
Gregory Heytings 2022-12-10 22:13:58 +00:00
parent 0115416605
commit 30e3cb2135

View File

@ -6071,8 +6071,42 @@ 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]);
#define MAYBE_UNSET_ATTRIBUTE(ATTR) \
if (realize_gui_face_ignored_spec_attributes \
& (1 << FONT_##ATTR##_INDEX)) \
ASET (spec, FONT_##ATTR##_INDEX, Qnil);
/* The default value of
realize_gui_face_ignored_spec_attributes unsets the
weight, slant and width in spec. The best possible
values for these attributes is determined in
font_find_for_lface, called by font_load_for_lface, when
the candidate list 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 leads to suboptimal or wrong font
choices. See bug#59347. */
MAYBE_UNSET_ATTRIBUTE (WEIGHT);
MAYBE_UNSET_ATTRIBUTE (SLANT);
MAYBE_UNSET_ATTRIBUTE (WIDTH);
/* Also allow unsetting other attributes for debugging
purposes. */
MAYBE_UNSET_ATTRIBUTE (FAMILY);
MAYBE_UNSET_ATTRIBUTE (FOUNDRY);
MAYBE_UNSET_ATTRIBUTE (REGISTRY);
MAYBE_UNSET_ATTRIBUTE (ADSTYLE);
MAYBE_UNSET_ATTRIBUTE (SIZE);
MAYBE_UNSET_ATTRIBUTE (DPI);
MAYBE_UNSET_ATTRIBUTE (SPACING);
MAYBE_UNSET_ATTRIBUTE (AVGWIDTH);
MAYBE_UNSET_ATTRIBUTE (EXTRA);
#undef MAYBE_UNSET_ATTRIBUTE
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]);
@ -7360,6 +7394,28 @@ 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_INT ("realize-gui-face-ignored-spec-attributes",
realize_gui_face_ignored_spec_attributes,
doc: /* Ignored font-spec attributes in realize_gui_face.
The value is an integer number and represents a bit mask.
The attribute corresponding to each bit that is set is cleared in
realize_gui_face. The bits are: 1 = :foundry, 2 = :family,
3 = :adstyle, 4 = :registry, 5 = :weight, 6 = :slant, 7 = :width,
8 = :size, 9 = :dpi, 10 = :spacing, 11 = :avgwidth, 12 = extra
attributes (:name, :script, :lang and :otf).
Bits 5 to 7 are set in the default value. When these bits are not
set, and when the font chosen for the default face has a weight, slant
or width that is not supported by other available fonts on the system,
such as 'medium', Emacs may select suboptimal fonts for other faces.
There is no reason to change that value except for debugging purposes. */);
realize_gui_face_ignored_spec_attributes =
(1 << FONT_WEIGHT_INDEX) |
(1 << FONT_SLANT_INDEX) |
(1 << FONT_WIDTH_INDEX);
#ifdef HAVE_WINDOW_SYSTEM
defsubr (&Sbitmap_spec_p);
defsubr (&Sx_list_fonts);