aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGregory Heytings2022-12-10 22:13:58 +0000
committerGregory Heytings2022-12-10 23:46:16 +0100
commit30e3cb213517461c7dbfe7b4875c92b2606fa2d5 (patch)
tree8f03a8256f271a65d85e7af38e706d72a51fc18e /src
parent01154166057e7cf289318a8cfa4d43716f26ca20 (diff)
downloademacs-30e3cb213517461c7dbfe7b4875c92b2606fa2d5.tar.gz
emacs-30e3cb213517461c7dbfe7b4875c92b2606fa2d5.zip
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'.
Diffstat (limited to 'src')
-rw-r--r--src/xfaces.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/src/xfaces.c b/src/xfaces.c
index df078227c8a..643f4365896 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6071,8 +6071,42 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6071 emacs_abort (); 6071 emacs_abort ();
6072 } 6072 }
6073 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) 6073 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6074 attrs[LFACE_FONT_INDEX] 6074 {
6075 = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]); 6075 Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]);
6076#define MAYBE_UNSET_ATTRIBUTE(ATTR) \
6077 if (realize_gui_face_ignored_spec_attributes \
6078 & (1 << FONT_##ATTR##_INDEX)) \
6079 ASET (spec, FONT_##ATTR##_INDEX, Qnil);
6080 /* The default value of
6081 realize_gui_face_ignored_spec_attributes unsets the
6082 weight, slant and width in spec. The best possible
6083 values for these attributes is determined in
6084 font_find_for_lface, called by font_load_for_lface, when
6085 the candidate list returned by font_list_entities is
6086 sorted by font_select_entity (which calls
6087 font_sort_entities, which calls font_score). If these
6088 attributes are not unset here, the candidate font list
6089 returned by font_list_entities only contains fonts that
6090 are exact matches for these weight, slant and width
6091 attributes, which leads to suboptimal or wrong font
6092 choices. See bug#59347. */
6093 MAYBE_UNSET_ATTRIBUTE (WEIGHT);
6094 MAYBE_UNSET_ATTRIBUTE (SLANT);
6095 MAYBE_UNSET_ATTRIBUTE (WIDTH);
6096 /* Also allow unsetting other attributes for debugging
6097 purposes. */
6098 MAYBE_UNSET_ATTRIBUTE (FAMILY);
6099 MAYBE_UNSET_ATTRIBUTE (FOUNDRY);
6100 MAYBE_UNSET_ATTRIBUTE (REGISTRY);
6101 MAYBE_UNSET_ATTRIBUTE (ADSTYLE);
6102 MAYBE_UNSET_ATTRIBUTE (SIZE);
6103 MAYBE_UNSET_ATTRIBUTE (DPI);
6104 MAYBE_UNSET_ATTRIBUTE (SPACING);
6105 MAYBE_UNSET_ATTRIBUTE (AVGWIDTH);
6106 MAYBE_UNSET_ATTRIBUTE (EXTRA);
6107#undef MAYBE_UNSET_ATTRIBUTE
6108 attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec);
6109 }
6076 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) 6110 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6077 { 6111 {
6078 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]); 6112 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
@@ -7360,6 +7394,28 @@ Lisp programs that change the value of this variable should also
7360clear the face cache, see `clear-face-cache'. */); 7394clear the face cache, see `clear-face-cache'. */);
7361 face_near_same_color_threshold = 30000; 7395 face_near_same_color_threshold = 30000;
7362 7396
7397 DEFVAR_INT ("realize-gui-face-ignored-spec-attributes",
7398 realize_gui_face_ignored_spec_attributes,
7399 doc: /* Ignored font-spec attributes in realize_gui_face.
7400
7401The value is an integer number and represents a bit mask.
7402The attribute corresponding to each bit that is set is cleared in
7403realize_gui_face. The bits are: 1 = :foundry, 2 = :family,
74043 = :adstyle, 4 = :registry, 5 = :weight, 6 = :slant, 7 = :width,
74058 = :size, 9 = :dpi, 10 = :spacing, 11 = :avgwidth, 12 = extra
7406attributes (:name, :script, :lang and :otf).
7407
7408Bits 5 to 7 are set in the default value. When these bits are not
7409set, and when the font chosen for the default face has a weight, slant
7410or width that is not supported by other available fonts on the system,
7411such as 'medium', Emacs may select suboptimal fonts for other faces.
7412
7413There is no reason to change that value except for debugging purposes. */);
7414 realize_gui_face_ignored_spec_attributes =
7415 (1 << FONT_WEIGHT_INDEX) |
7416 (1 << FONT_SLANT_INDEX) |
7417 (1 << FONT_WIDTH_INDEX);
7418
7363#ifdef HAVE_WINDOW_SYSTEM 7419#ifdef HAVE_WINDOW_SYSTEM
7364 defsubr (&Sbitmap_spec_p); 7420 defsubr (&Sbitmap_spec_p);
7365 defsubr (&Sx_list_fonts); 7421 defsubr (&Sx_list_fonts);