Sunday, February 20, 2022

JuliaMono and face-font-rescale-alist on Emacs

I have been a happy user of Inconsolata font for a long time. But since I started to use Julia,I've switched to JuliaMono font. Whenever I change the fonts on my Emacs, Org Mode's Agenda Views (with Habits tracker) starts to break.

This is because each glyph has its own "Holizontal Advance" for the given size, shown in the image from freetype.org:

A font usually doesn't have all glyphs for all Unicode scripts, but has only subsets of it. I use Emacs for writing code as well as writing Japanese and English documents. Thus, I need both a good programming font and decent Japanese fonts. But they tend to disagree with pixel width against each font size.

Here is a list of Holizontal Advance in pixel, taken from each font for each size. This is generated by this gist.

font size: 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Inconsolata.otf
   U+0061:  7  7  8  9  9 10 11 11 12 13 13 14 15 15 16 17 17 18 19 19 20
   U+3042: (not found)
JetBrainsMono-Regular.ttf
   U+0061:  8  9 10 10 11 12 13 14 14 15 16 17 17 19 19 20 21 22 22 23 24
   U+3042: (not found)
JuliaMono-Regular.ttf
   U+0061:  8  9 10 10 11 12 13 14 14 15 16 17 18 18 19 20 21 22 22 23 24
   U+3042: (not found)
DejaVuSans.ttf
   U+0061:  8  9 10 10 12 12 13 14 15 15 17 17 18 19 20 20 21 22 23 24 25
   U+3042: (not found)
Vera.ttf
   U+0061:  8  9 10 10 12 12 13 14 15 15 17 17 18 19 20 20 21 22 23 24 25
   U+3042: (not found)
NotoMono-Regular.ttf
   U+0061:  8  9 10 10 11 12 13 14 14 15 16 17 17 19 19 20 21 22 22 23 24
   U+3042: (not found)
RobotoCondensed-Regular.ttf
   U+0061:  7  7  7  8  9  9 10 11 11 12 12 14 15 15 15 16 16 17 18 19 19
   U+3042: (not found)
NotoSansCJK-Regular.ttc
   U+0061:  8  8  9 10 11 11 12 13 14 14 15 16 17 17 18 19 20 20 21 22 23
   U+3042: 13 15 16 17 19 20 21 23 24 25 27 28 29 31 32 33 35 36 37 39 40
hiragino-kaku-gothic-pron-w3.otf
   U+0061:  8  8  9 10 11 12 12 13 14 15 15 16 17 18 18 19 20 21 21 22 23
   U+3042: 13 15 16 17 19 20 21 23 24 25 27 28 29 31 32 33 35 36 37 39 40
hiragino-min-pron-w3.otf
   U+0061:  7  8  9  9 10 11 12 12 13 14 15 15 16 17 17 18 19 20 20 21 22
   U+3042: 13 15 16 17 19 20 21 23 24 25 27 28 29 31 32 33 35 36 37 39 40

To match font width, Emacs can scale fonts. You have to tell Emacs which font you want to scale and how much. To do this, you set face-font-rescale-alist.

(let* ((default-font "JuliaMono-15") ; or "Inconsolata-18"
         (scale (cond ((string-prefix-p "inconsolata" default-font t) 1.05)
                      ((string-prefix-p "juliamono" default-font t) 1.20)))
         (spec (font-spec :family "Hiragino Kaku Gothic ProN W3")))
    (set-face-attribute 'default nil :font default-font)
    (set-face-attribute 'fixed-pitch nil :font default-font)
    (set-fontset-font t 'japanese-jisx0208 spec)
    (set-fontset-font t 'greek (font-spec :family default-font))
    (add-to-list 'face-font-rescale-alist `(".*Hiragino.*" . ,scale)))

In the above code, I also set the default fontset for two scripts, 'japanese-jisx0208 and 'greek. This is because 'japanese-jisx0208 also includes Greek script. Thus, we must explicitly set 'greek back to the default font.