emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-29 30e3cb21351: Unset the weight/slant/width in the spec when real


From: Gregory Heytings
Subject: emacs-29 30e3cb21351: Unset the weight/slant/width in the spec when realizing a font
Date: Sat, 10 Dec 2022 17:46:42 -0500 (EST)

branch: emacs-29
commit 30e3cb213517461c7dbfe7b4875c92b2606fa2d5
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>

    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'.
---
 src/xfaces.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file 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]
            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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]