Unexpected Result from face-font-rescale-alist in Emacs – Solution

emacs

I am trying to modify the default size of a font using

(add-to-list 'face-font-rescale-alist (cons "^.*STIXGeneral.*$" 0.95) t)

This is supposed to rescale all fonts with name STIXGeneral by 0.95, because for me that font is a little taller than the standard font. The resulting value of face-font-rescale-alist is:

(("-cdac$" . 1.3) ("^.*STIXGeneral.*$" . 0.95))

However, with emacs 24.3 (also the git version, and also pre-release 24.3.92.1), the result of adding the above to .emacs is that the font is wrong on every frame apart from the initial frame. Running 24.3 with -Q --eval="<expression above>" gives:

(message "%s" (face-all-attributes 'default (selected-frame)))
New frame: ((:family . Geneva) (:foundry . apple) (:width . normal) (:height . 120) (:weight . normal) (:slant . normal) (:underline) (:overline) (:strike-through) (:box) (:inverse-video) (:foreground . Black) (:background . White) (:stipple) (:inherit))
Initial frame: ((:family . Menlo) (:foundry . apple) (:width . normal) (:height . 120) (:weight . normal) (:slant . normal) (:underline) (:overline) (:strike-through) (:box) (:inverse-video) (:foreground . Black) (:background . White) (:stipple) (:inherit))

With my regular .emacs on git version:

New frame: "((:family . Helvetica) (:foundry . nil) (:width . normal) (:height . 110) (:weight . normal) (:slant . normal) (:underline) (:overline) (:strike-through) (:box) (:inverse-video) (:foreground . #000000) (:background . AliceBlue) (:stipple) (:inherit))"
Initial frame: ((:family . Source Code Pro) (:foundry . nil) (:width . normal) (:height . 110) (:weight . normal) (:slant . normal) (:underline) (:overline) (:strike-through) (:box) (:inverse-video) (:foreground . #000000) (:background . AliceBlue) (:stipple) (:inherit))

The face in the initial frame is the one I expect. The place where face-font-rescale-alist influences the font is in font_score in font.c (link). The same problem occurs in git version if I replace (add-to-list ...) with (setq face-font-rescale-alist nil).

What am I doing wrong here?

Best Answer

Hm. In startup.el the following code detects changes in face-font-rescale-alist, and resets the default font, while also ignoring changes coming from custom-set-face (which is how I was setting the font with the customization interface):

;; startup.el:670
(unless (eq face-font-rescale-alist old-face-font-rescale-alist)
 (set-face-attribute 'default nil :font (font-spec)))

It is therefore necessary to set face-font-rescale-alist after the code that tries to erase customizations. This can be done by attaching advice to frame-notice-user-settings, which runs after the face-resetting code:

;; in .emacs
(defadvice frame-notice-user-settings (before my:rescale-alist)
  (message "Set face-font-rescale-alist")
  (add-to-list 'face-font-rescale-alist
               (cons (font-spec :family "STIXGeneral") 0.95) t))
(ad-activate 'frame-notice-user-settings)

This applies face-font-rescale-alist as I would have expected it to work from reading documentation.

Related Question