Package: emacs-gtk Version: 1:29.1+1-5 Severity: important Tags: patch X-Debbugs-Cc: creic...@gmail.com
Dear Maintainer, (This is a resubmission; the previous bug may have been lost to spam filtering.) As of the upgrade to 29.1 on 2023-09-06, Emacs seems to be disregarding some user preferences for the font for the "default" face. * What led up to the situation? The upgrade to Emacs 29.1 on 2023-09-06. * What exactly did you do (or not do) that was effective (or ineffective)? Executing the following steps: - (customize-face 'default) - Font Family: setting "Terminus (TTF)" - Font Foundry: setting "PfEd" - Optionally (does not affect outcome): - Weight: setting "medium" - Disabling any font attributes (inlcuding Weight) - [Apply] Equivalently: (custom-set-faces '(default ((t (:inherit nil :extend nil :stipple nil :background "black" :foreground "white" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight medium :height 120 :width normal :foundry "PfEd" :family "Terminus (TTF)")))) ) * What was the outcome of this action? Emacs used the "Purisa" font as default font. This font has the same Font Foundry as "Terminus (TTF)" but is a "Comic Sans"-like special-purpose font and unsuitable for normal operations. * What outcome did you expect instead? I expected Emacs 29.1 to honour my configuration settings, as Emacs 28 did before. * Observations - This only affects the default face. Based on my attempte to debug the problem (see below), the bug is caused by special treatment for the default face. - This bug is likely related to #1029710, which was reported at the same time as my original (regrettably spam-filtered?) report. - I have narrowed down the bug somewhat (see below) and am using a local workaround. - This issue affects emacs-gtk and emacs-pgtk equally. - This issue affects X11 and wayland equally. * Debugging results ** Why this seems to happen Here is the flow of events that leads to the problem, to the best of my (very limited) understanding: 1. At some point, the font spec for the default face is set up 2. I set my preferences for the default face 3. My preferences are applied to the default face spec in some order 4. During "Font Family" selection, the following happens at some point: a) While searching for suitable fonts, Emacs calls font_list_entities(f, spec) b) font_list_entities(f, spec) (font.c, L2540) does some preprocessing and then: 1. asks the driver for a list `vec' of suitable fonts (L2585) 2. and filters out unsuitable fonts (L2602), calling c) font_delete_unmatched(vec, spec, size) in turn scans the `vec' to remove elements that don't match `spec'. 1. Specifically, for properties like font weight (FONT_WEIGHT_INDEX), L2486 checks if the requested property is an exact match and otherwise removes the candidate (L2502). 2. I assume that L2477 skips checks for properties that are left unconstrained (nil) in the spec but have not verified that. The unexpected behaviour happens at 4.c: 4.c.2 always seems to allow filtering by font weight, no matter what I select in the font face 4.c.1 always seems to require a font weigth of 80 ("regular"), no matter what I select in the font face interface. I have tried to investigate further to check: - Does the wrong weight come from a hardcoded value? - Does the wrong weight come from a stale font spec attribute? *** Hardcoded value? I tried modifying the `font_weights' table in font.c, but was only able to "fix" the behaviour by entirely removing the entry for weight 80. My interpretation is that the value "80" probably comes from one of the default fallback fonts and is accidentally retained in the font spec (i.e., the weight doesn't seem to be hardcoded anywhere in Emacs). *** Stale font attribute? I traced the calls to `internal-set-lisp-face-attribute' immediately after updating the font. Below is the order in which the attributes are set (some appear more than once): :underline :overline :strike-through :box :inverse-video :stipple :inherit :extend :family :foundry :inherit :extend :stipple :background :foreground :inverse-video :box :strike-through :overline :underline :slant :weight :height :width Note how :family is set before :weight is updated (to the correct value): - After setting :family, the font spec is associated with a font object for the "Purisa" font, but at least retains :family (of the font that I requested). - Once :weight is updated, internal-set-lisp-face-attribute calls set_font_frame_param(), at which point :family becomes "nil". My current interpretation (based on the above) is that font_list_entities() gets called after the "Font Family" entry has been updated in the `spec' but before the weight is updated; instead, the spec probably inherits the weight of the current font for the default face, as associated with the current frame. Since that weight is different from the weight of the font I requested, font_delete_unmatched() kicks that font out. *** How should this be fixed? I don't understand enough of the rationale behind the font selection logic to propose a fix. Changing the order in which font spec entries are updated _might_ fix the problem, but there is some special-case handling for the default font that I haven't wrapped my head around. *** Threats to validity The above is based on some manual tracing, and I may have made mistakes while logging. I am also unfamiliar with the Emacs internals and font selection algorithm. ** Why this didn't happen before I previously used the "Terminus" bitmap font, which is no longer supported due to limitations in the GTK-based font renderer (ftcrhb). Older Emacs versions might still have behaved "more correctly" due to the presence of the X font renderer (which is no longer included, to my understanding). This bug report is unrelated to the question of whether Emacs should or should not support bitmap fonts. ** My current workaround My current workaround replicates a pre-existing Windows NT kludge and allows fonts to be considered "matching" if the differences in font weight are small: ===================================================================== --- emacs-29.1+1/src/font.c 2023-07-30 15:32:46.000000000 +0000 +++ emacs-kludge/src/font.c 2023-09-08 21:03:11.584666482 +0000 @@ -2484,6 +2484,8 @@ int candidate = XFIXNUM (AREF (entity, prop)) >> 8; if (candidate != required + && (prop != FONT_WEIGHT_INDEX + || eabs (candidate - required) > 25) #ifdef HAVE_NTGUI /* A kludge for w32 font search, where listing a family returns only 4 standard weights: regular, ===================================================================== (The value of 25 should allow both "semi-light" and "medium" fonts to be used in place of "regular" fonts.) I don't consider this patch to be a solution to the problem, since I strongly suspect that it has some undesirable side effects during font selection (possibly only on specific platforms or for specific fonts / font weights), but it works well enough for me as a stop-gap fix, and if this patch also fixes #1029710, I would propose including it in Debian/sid as a workaround until there is a "proper" fix. ** Other possible workarounds My reading of `xfns.c' is that Emacs tries to inherit fonts from the environment, so it may be possible to work around this bug by changing Gtk defaults. (This is not something that I have tried, since I am not very familiar with Gtk.) -- System Information: Debian Release: trixie/sid APT prefers testing APT policy: (990, 'testing'), (900, 'stable'), (500, 'stable-updates'), (500, 'stable-security'), (5, 'unstable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 6.5.0-4-amd64 (SMP w/32 CPU threads; PREEMPT) Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE=en_CA:en Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages emacs-gtk depends on: ii emacs-bin-common 1:29.1+1-5 ii emacs-common 1:29.1+1-5 ii libacl1 2.3.1-3 ii libasound2 1.2.10-1 ii libc6 2.37-12 ii libcairo2 1.18.0-1 ii libdbus-1-3 1.14.10-3 ii libfontconfig1 2.14.2-6 ii libfreetype6 2.13.2+dfsg-1 ii libgccjit0 13.2.0-5 ii libgdk-pixbuf-2.0-0 2.42.10+dfsg-2 ii libgif7 5.2.1-2.5 ii libglib2.0-0 2.78.1-2 ii libgmp10 2:6.3.0+dfsg-2 ii libgnutls30 3.8.1-4+b1 ii libgpm2 1.20.7-10+b1 ii libgtk-3-0 3.24.38-6 ii libharfbuzz0b 8.0.1-1 ii libice6 2:1.0.10-1 ii libjansson4 2.14-2 ii libjpeg62-turbo 1:2.1.5-2 ii liblcms2-2 2.14-2 ii libm17n-0 1.8.4-1 ii libotf1 0.9.16-4 ii libpango-1.0-0 1.51.0+ds-3 ii libpng16-16 1.6.40-2 ii librsvg2-2 2.54.7+dfsg-2 ii libselinux1 3.5-1 ii libsm6 2:1.2.3-1 ii libsqlite3-0 3.44.0-1 ii libsystemd0 254.5-1 ii libtiff6 4.5.1+git230720-1 ii libtinfo6 6.4-4 ii libtree-sitter0 0.20.8-2 ii libwebp7 1.3.2-0.3 ii libwebpdemux2 1.3.2-0.3 ii libx11-6 2:1.8.7-1 ii libxcomposite1 1:0.4.5-1 ii libxext6 2:1.3.4-1+b1 ii libxfixes3 1:6.0.0-2 ii libxi6 2:1.8-1+b1 ii libxinerama1 2:1.1.4-3 ii libxml2 2.9.14+dfsg-1.3 ii libxrandr2 2:1.5.2-2+b1 ii libxrender1 1:0.9.10-1.1 ii zlib1g 1:1.2.13.dfsg-3 Versions of packages emacs-gtk recommends: ii fonts-noto-color-emoji 2.038-1 Versions of packages emacs-gtk suggests: pn emacs-common-non-dfsg <none> -- no debconf information