2

Say I create a fontset and populate it with fonts:

(create-fontset-from-fontset-spec
 (font-xlfd-name (font-spec :registry "fontset-mine")))
(set-fontset-font "fontset-mine" 'latin "Noto Serif")
(set-fontset-font "fontset-mine" 'kana "Noto Serif CJK JP")

I can't find a way to get a face to use this fontset. For example, if I set it like (set-face-attribute 'my-test-face nil :font "fontset-mine"), then my-test-face will show kana scripts in Noto Sans CJK KR, not JP (presumably a fallback specified by fontset-standard or something).

According to investigations by Yuan Fu, when set-face-attribute or similar is given a fontset as :font, it merely extracts the ASCII font of that set and copies its family, height, etc. onto the face (corroborated by a comparison of describe-face before and after set-face-attribute). This means I can't use it to set more than one font to a face simultaneously; anything not supported by the one font that is set, will use some Emacs-wide fallback. The bug report talks about setting the :fontset attribute, but that doesn't seem to do anything either. (EDIT: this last statement was wrong; see the answer.)

So my question is: is there a way to apply user-defined fontsets to any faces? By user-defined, I mean those created in init.el with create-fontset-from-fontset-spec, as opposed to built-in ones like fontset-standard. If not, are user-defined fontsets useful for anything?

My particular use case is as follows. I want to switch between these sets of fonts, depending on the type of document I'm editing.

  • ETbb for latin, Noto Serif CJK JP for kana.
  • Noto Sans for latin, Noto Sans CJK JP for kana.

(There are lots more scripts I'm interested in, but I'll focus on two.) Right now I can produce a face that has any of the following, none of which is what I want.

  • ETbb for latin and some fallback font for kana
  • Noto Sans for latin and some fallback font for kana
  • Some fallback font for latin and Noto Serif CJK JP for kana
  • Some fallback font for latin and Noto Sans CJK JP for kana

The point is, without a way to apply a fontset as one indivisible unit, I can only control latin or kana, not both; one of them will get specified by default, not by me.

Jun Inoue
  • 195
  • 6
  • What does `describe-fontset` show you for your new fontset? – db48x Jan 31 '22 at 13:55
  • @db48x It shows `C-@ .. DEL -*-Noto Serif-*-*-*-*-*-*-*-*-*-*-*-*` for ASCII and `぀ .. ヿ (#x3040 .. #x30FF) -*-Noto Serif CJK JP-*-*-*-*-*-*-*-*-*-*-*-*` for Japanese, so `set-fontset-font` is working as it should, AFAICT. (FYI, a sample kana is あ at #x3042) – Jun Inoue Jan 31 '22 at 15:01
  • I'm not very familiar with this stuff. But did you try `set-face-font`? It sets attribute `:font`, whose value can be a font **or a fontset**. – Drew Jan 31 '22 at 16:04
  • I think the doc in the Elisp manual isn't obvious enough about the value of `:font` being able to be a fontset. But that seems to be what lets a face have different fonts for different chars. I filed Emacs bug [#53664](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=53664) to improve this aspect of the manual. – Drew Jan 31 '22 at 16:08
  • @Drew Thanks, I hadn't considered `set-face-font`. Unfortunately, it's the same deal as setting `:font` with `set-face-attribute`. The doc is wrong in this respect. – Jun Inoue Feb 01 '22 at 03:11
  • It almost seems like the people who implemented this stuff were planning on making fontset usable just like fonts. They initially settled on this ASCII extraction as a temporary measure, but then stuff happened and it got forgotten. That's just speculation, but in any case, it looks like the maintainers right now don't have the resources to overhaul the code to match the docs, so perhaps retracting that statement on the docs is the most prudent thing to do. – Jun Inoue Feb 01 '22 at 03:18
  • I see from your answer that your previous comment about it not working was mistaken. You can delete comments, if you like, to avoid confusion. – Drew Feb 01 '22 at 16:19

1 Answers1

1

Yikes. I had a fresh look at this after a good night's sleep, and it turns out I was wrong to say that setting the :fontset attribute doesn't work. My test code had a critical typo, and I also tried custom-theme-set-faces etc. in addition to set-face-attribute, and then mixed things up. Sorry for the confusion.

To set the record straight:

  • You can apply a fontset to a face by setting its :fontset attribute with set-face-attribute. The face will then use all fonts in the set as expected. EDIT: the values of :font, :family etc. override :fontset, so if you're modifying a pre-existing face like variable-pitch, be sure to adjust those other attributes as well.
  • However, you cannot set the :fontset attribute using custom-theme-set-faces or defface, which ignore that attribute.
  • The manual currently says in some places that you can pass in a fontset for the :font attribute or the font argument of set-face-font, but this is misleading at best: the fontset will be stripped of the "set" part and be treated as just an ASCII font.

I think the second bullet means that there's no way to enable/disable fontsets with themes, but someone more knowledgeable on themes will have to set me straight on this.

Jun Inoue
  • 195
  • 6