Improve last change to xfaces.c

* src/xfaces.c (font_unset_attribute): New function.
(realize_gui_face): Improve commentary and use list instead of
bitmask.
(syms_of_xfaces): Get rid of bitmask.  Replace it by a list,
there is no reason any user should have to think about bitmasks
in Emacs lisp.
This commit is contained in:
Po Lu 2022-12-11 09:32:20 +08:00
parent 7013b0179c
commit 05ece1eb8b

View file

@ -6014,6 +6014,23 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
} }
#endif /* HAVE_WINDOW_SYSTEM */ #endif /* HAVE_WINDOW_SYSTEM */
/* Remove the attribute at INDEX from the font object if SYMBOL
appears in `font-fallback-ignored-attributes'. */
static void
font_unset_attribute (Lisp_Object font_object, enum font_property_index index,
Lisp_Object symbol)
{
Lisp_Object tail;
tail = Vfont_fallback_ignored_attributes;
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 /* Realize the fully-specified face with attributes ATTRS in face
cache CACHE for ASCII characters. Do it for GUI frame CACHE->f. cache CACHE for ASCII characters. Do it for GUI frame CACHE->f.
@ -6029,7 +6046,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
#ifdef HAVE_WINDOW_SYSTEM #ifdef HAVE_WINDOW_SYSTEM
struct face *default_face; struct face *default_face;
struct frame *f; struct frame *f;
Lisp_Object stipple, underline, overline, strike_through, box; Lisp_Object stipple, underline, overline, strike_through, box, spec;
eassert (FRAME_WINDOW_P (cache->f)); eassert (FRAME_WINDOW_P (cache->f));
@ -6072,39 +6089,34 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
} }
if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
{ {
Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]); spec = copy_font_spec (attrs[LFACE_FONT_INDEX]);
#define MAYBE_UNSET_ATTRIBUTE(ATTR) \
if (realize_gui_face_ignored_spec_attributes \ /* Unset several values in SPEC, usually the width, slant,
& (1 << FONT_##ATTR##_INDEX)) \ and weight. The best possible values for these
ASET (spec, FONT_##ATTR##_INDEX, Qnil); attributes is determined in font_find_for_lface, called
/* The default value of by font_load_for_lface, when the candidate list returned
realize_gui_face_ignored_spec_attributes unsets the by font_list_entities is sorted by font_select_entity
weight, slant and width in spec. The best possible (which calls font_sort_entities, which calls font_score).
values for these attributes is determined in If these attributes are not unset here, the candidate
font_find_for_lface, called by font_load_for_lface, when font list returned by font_list_entities only contains
the candidate list returned by font_list_entities is fonts that are exact matches for these weight, slant and
sorted by font_select_entity (which calls width attributes, which leads to suboptimal or wrong font
font_sort_entities, which calls font_score). If these choices. (bug#5934) */
attributes are not unset here, the candidate font list font_unset_attribute (spec, FONT_WEIGHT_INDEX, QCwidth);
returned by font_list_entities only contains fonts that font_unset_attribute (spec, FONT_SLANT_INDEX, QCslant);
are exact matches for these weight, slant and width font_unset_attribute (spec, FONT_WIDTH_INDEX, QCwidth);
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 /* Also allow unsetting other attributes for debugging
purposes. */ purposes. But not FONT_EXTRA_INDEX; that is not safe to
MAYBE_UNSET_ATTRIBUTE (FAMILY); touch in the Haiku font backend. */
MAYBE_UNSET_ATTRIBUTE (FOUNDRY); font_unset_attribute (spec, FONT_FAMILY_INDEX, QCfamily);
MAYBE_UNSET_ATTRIBUTE (REGISTRY); font_unset_attribute (spec, FONT_FOUNDRY_INDEX, QCfoundry);
MAYBE_UNSET_ATTRIBUTE (ADSTYLE); font_unset_attribute (spec, FONT_REGISTRY_INDEX, QCregistry);
MAYBE_UNSET_ATTRIBUTE (SIZE); font_unset_attribute (spec, FONT_ADSTYLE_INDEX, QCadstyle);
MAYBE_UNSET_ATTRIBUTE (DPI); font_unset_attribute (spec, FONT_SIZE_INDEX, QCsize);
MAYBE_UNSET_ATTRIBUTE (SPACING); font_unset_attribute (spec, FONT_DPI_INDEX, QCdpi);
MAYBE_UNSET_ATTRIBUTE (AVGWIDTH); font_unset_attribute (spec, FONT_SPACING_INDEX, QCspacing);
MAYBE_UNSET_ATTRIBUTE (EXTRA); font_unset_attribute (spec, FONT_AVGWIDTH_INDEX, QCavgwidth);
#undef MAYBE_UNSET_ATTRIBUTE
attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec); attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec);
} }
if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
@ -7394,27 +7406,22 @@ Lisp programs that change the value of this variable should also
clear the face cache, see `clear-face-cache'. */); clear the face cache, see `clear-face-cache'. */);
face_near_same_color_threshold = 30000; face_near_same_color_threshold = 30000;
DEFVAR_INT ("realize-gui-face-ignored-spec-attributes", DEFVAR_LISP ("font-fallback-ignored-attributes",
realize_gui_face_ignored_spec_attributes, Vfont_fallback_ignored_attributes,
doc: /* Ignored font-spec attributes in realize_gui_face. doc: /* A list of face attributes to ignore.
The value is an integer number and represents a bit mask. List of font-related face attributes to ignore when realizing a face.
The attribute corresponding to each bit that is set is cleared in This is a list of symbols representing face attributes that will be
realize_gui_face. The bits are: 1 = :foundry, 2 = :family, ignored by Emacs when realizing a face, and an exact match couldn't be
3 = :adstyle, 4 = :registry, 5 = :weight, 6 = :slant, 7 = :width, found for its preferred font. For example:
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 (:weight :slant :width)
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. */); tells Emacs to ignore the `:weight', `:slant' and `:width' face
realize_gui_face_ignored_spec_attributes = attributes when searching for a font and an exact match could not be
(1 << FONT_WEIGHT_INDEX) | found for the font attributes specified in the face being realized. */);
(1 << FONT_SLANT_INDEX) | Vfont_fallback_ignored_attributes
(1 << FONT_WIDTH_INDEX); = list3 (QCwidth, QCslant, QCwidth);
#ifdef HAVE_WINDOW_SYSTEM #ifdef HAVE_WINDOW_SYSTEM
defsubr (&Sbitmap_spec_p); defsubr (&Sbitmap_spec_p);