Subject: bug#70993: set-fontset-font doesn't use specified font for some scripts

From: Eli Zaretskii <[email-masked]>
Date: Fri, 17 May 2024 10:10:29 +0300

> Date: Thu, 16 May 2024 22:30:56 -0500
> From: Rodrigo Morales <[email-masked]>
> 
> 
> I downloaded the font =cozette.bdf= from https://github.com/slavfox/Cozette/releases/tag/v.1.24.1 . This is a bitmap font that define glyphs for a small set of characters since it is intended for programming.
> 
> I launched emacs using =emacs -Q=. I opened the file =/tmp/a.txt=. The contents of that file are shown below.
> 
> #+HEADER: :tangle /tmp/a.txt
> #+BEGIN_SRC text
> The following lines were retrieved from the HELLO buffer which is
> opened by calling view-hello-file in GNU Emacs 29.3.
> Brahmi (𑀩𑁆𑀭𑀸𑀳𑁆𑀫𑀻)	𑀦𑀫𑀲𑁆𑀢𑁂
> Egyptian Hieroglyphs (𓂋𓏤𓈖𓆎𓅓‌𓏏𓊖)	𓅓𓊵𓏏𓊪, 𓇍𓇋𓂻𓍘𓇋
> Amharic (አማርኛ)	ሠላም
> Tagbanwa (ᝦᝪᝯ)	ᝫᝩᝬᝥ ᝣᝮᝧᝯ
> Chinese (中文,普通话,汉语)	你好
> #+END_SRC
> 
> I called =what-cursor-position= with a prefix argument in the first character of the word from each script to take note of the font that is used by default:
> 
> Brahmi: ftcrhb:-GOOG-Noto Sans Brahmi-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x2E)
> Egyptian Hieroglyphs: ftcrhb:-GOOG-Noto Sans Egyptian Hieroglyphs-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x15D)
> Amharic: ftcrhb:-GOOG-Noto Sans Ethiopic-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x2B)
> Tagbanwa: ftcrhb:-GOOG-Noto Sans Tagbanwa-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x0D)
> Chinese: ftcrhb:-GOOG-Noto Sans CJK KR-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x2703)
> 
> I then evaluated the following sexp to force the use of the =Cozette= font in the scripts that are shown in that file. Sidenote: I am aware that =Cozette= doesn't define glyphs for these script symbols. The reason I'm reporting this bug is that the current behavior is not consistent.
> 
> #+BEGIN_SRC elisp
> (progn
>   (set-fontset-font t 'brahmi (font-spec :family "Cozette"))
>   (set-fontset-font t 'egyptian (font-spec :family "Cozette"))
>   (set-fontset-font t 'ethiopic (font-spec :family "Cozette"))
>   (set-fontset-font t 'tagbanwa (font-spec :family "Cozette"))
>   (set-fontset-font t 'han (font-spec :family "Cozette")))
> #+END_SRC
> 
> Upon evaluation, the font changed for the Brahmi and Egyptian Hieroglyphs characters. Because =Cozette= doesn't define glyphs for characters in those scripts, a hexadecimal character code in a box is shown for those scripts. As for Amharic, Tagbanwa and Chinese characters, the font didn't change. I called =what-cursor-position= with a prefix argument in each line to take note of the fonts:
> 
> Brahmi: no font available
> Egyptian Hieroglyphs: no font available
> Amharic: ftcrhb:-GOOG-Noto Sans Ethiopic-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x2B)
> Tagbanwa: ftcrhb:-GOOG-Noto Sans Tagbanwa-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x12)
> Chinese: ftcrhb:-GOOG-Noto Sans CJK KR-regular-normal-normal-*-12-*-*-*-*-0-iso10646-1 (#x2703)
> 
> This is not consistent behavior because even though we forced the use of a single font for all scripts in the file in the sexp shown above, Emacs tried to use "Cozette" in the lines containing the Brahmi and Egyptian Hieroglyphs characters (group A) and because no glyph was found, it displayed the hexadecimal character code in a box, while Emacs didn't change the font in the lines containing Amharic, Tagbanwa and Chinese characters (group B), so it didn't display hexadecimal character code in a box as happened in (group A).
> 
> The consistent behavior would be that characters of all scripts shown in the file /tmp/a.txt display a hexadecimal character code in a box after evaluation of the sexp shown above because Cozette version 1.24.1 (the font used to reproduce the bug) doesn't define glyphs for those scripts. I think some people might think that the current behavior happens because Emacs uses a fallback font, but this still shouldn't happen because I had explicitly set the use of a single font for those scripts (I didn't pass =prepend= or =append= as the 5th parameter of set-fontset-font) so Emacs should honour that and don't assume that I want to use fallback fonts. Users that want to handle fallback fonts should explicitly pass 'prepend or 'append as the 5th parameter to set-fontset-font.

I think you need to evaluate those set-fontset-font expressions
_before_ displaying any characters from the corresponding scripts
(i.e., at the very beginning of the Emacs session), to get reliable
results.  That's because some scripts require characters to be
composed on display, and Emacs caches these compositions together with
the font used to display those characters.  Changing the fontset after
some character compositions were already cached will not change the
font recorded in the cached compositions.

IOW, set-fontset-font cannot be reliably used in the middle of an
Emacs session.