I already had this problem in a different unanswered question here. I would expect different fonts at the same size to have the same heights, but this doesn't seem to be the case, so I will show my ad-hoc approach to fixing this.
Leaving aside accents, and focusing only on plain characters, different fonts are necessary to display all the different characters simply because some fonts omit entire blocks of characters that are present in other fonts. To make sure that uncommon characters (such as "𝚫") have at least one font for them, install a font such as Symbola, and see the list of fonts in the readme of the unicode-fonts package.
If you install the package unicode-fonts
and a number of good fonts, all characters should be supported, but some will have wrong displayed heights in emacs.
Suppose that Monaco has incorrect heights, but Symbola appears to have correct heights for mathematical symbols (such as SUBSET OF OR EQUAL TO ⊆; use C-x 8 RET or insert-char
to test different characters.). In my case, not using Monaco, Noto Sans Symbols and Apple Symbols was sufficient; one good font for me was DejaVu Sans Mono.
The first thing is that you can forbid unicode-fonts
from using Monaco by adding it to unicode-fonts-skip-fonts
; whatever font it selects next might have the right height. Alternatively, you can tell unicode-fonts
to use a specific font for a Unicode block (such as Mathematical Operators; here is a list of all blocks) by modifying an entry of unicode-fonts-block-font-mapping
.
The second is that you can easily do this manually for a very precise set of characters by using set-fontset-font
. If Symbola is a good font for mathematical symbols (in this case the range 0x2100..0x23ff
), the following should work:
(set-fontset-font t '(#x2100 . #x23ff)
;; this should throw an error if there is no such font
(font-xlfd-name (find-font (font-spec :family "Symbola"))))
Other ranges I needed to modify myself were 2000..206f
, 27c0..27ff
, 2900..2bff
, 1d400..1d7ff
.
Finally, it is not necessary to search for misconfigured characters by hand. Assuming unicode-fonts
is installed, the following function will generate a list of all characters with incorrect heights:
(defun debug-unicode-heights (&optional block-name)
"Find all characters in a given block that have incorrect heights.
BLOCK-NAME can be anything that
`unicode-fonts-debug-insert-block' accepts, such as `'all-math',
or a string naming a Unicode block."
(interactive "sBlock name:")
(unless block-name (setq block-name 'all-math))
(let ((buffer (generate-new-buffer (format "debug-unicode-heights:%s" block-name)))
expected-height
bad-characters)
(pop-to-buffer buffer)
(with-current-buffer buffer
(unicode-fonts-debug-insert-block block-name)
(goto-char (point-min))
(setq expected-height (line-pixel-height))
;; (message "Expected height %d" expected-height)
(while (< (point) (point-max))
(if (or (= (line-pixel-height) expected-height)
;; Some characters are invalid, they have no name
;; (their name is just their hex code), and their
;; heights do not matter to us.
(looking-at-p "^.[^\"]*\"#"))
(delete-region (line-beginning-position)
(1+ (line-end-position)))
(push (char-after (line-beginning-position)) bad-characters)
(forward-line))))
;; (display-message-or-buffer buffer)
(apply #'string (reverse bad-characters))))
For example:
M-: (debug-unicode-heights 'all-math)
and then
M-: (debug-unicode-heights 'all-greek)
would show all bad mathematical symbols. You can then examine which font they are displayed with, and change it.
I have OS X 10.9.5, so my font settings would likely be different from yours. It is not necessary to install unicode-fonts
; it is possible to manually specify your preferred font choices entirely through set-fontset-font
whenever you find that emacs's default choices don't work well.
P.S. There is an alternative: when a font is consistently too large/small, you can add an entry to face-font-rescale-alist
to tell emacs to always multiply that font's size by a factor of, say, 0.95, like so:
(add-to-list 'face-font-rescale-alist (cons (font-spec :family "STIXGeneral") 0.95) t)
When I tried this, it didn't quite work right (my bug report is here), but this is also a possible approach.