Scaling Latex previews in Emacs
This is a post in my Latex editing series, an awkward solution to a tiny problem.
The Problem
A common issue with Latex previews in Emacs: The preview images don’t scale when you rescale text in latex-mode
or org-mode
:
This makes it cumbersome to work with Latex math in Emacs when dealing with different sized monitors or when presenting from Emacs with Org Tree Slide, for example.
A good solution would be to re-render these fragment images at a higher resolution when applying text scaling. The current version of org-mode (9.52 as of this writing) is very slow to render Latex previews and locks up Emacs for a while, this is not a workable solution.
There are a couple of ways this could be improved: For Org, call an async process to render Latex fragments, or better yet, reuse AucTeX’s preview-latex
library for fast, near instant updates.
Instant Org previews with preview-latex are now feasible, see the next post in this series.
For Latex, adjust the preview-scale
variable and regenerate the fragments at each new text scale. These are projects for another day, or for someone more proficient.
The Hack
After asking around for an alternative, I settled on writing a big ol’ hack: Just zoom in on the preview images when increasing the text scale:
This is fast and cheap, but the downside is that the images get blurry:
Using SVG fragments can mitigate this problem, at least for Org previews:
(setq org-preview-latex-default-process 'dvisvgm) ;No blur when scaling
The Recipe
Preview images are handled using overlays, so the image scaling is done by scanning for and adjusting appropriate overlay properties when changing the text scale:
(defun my/text-scale-adjust-latex-previews ()
"Adjust the size of latex preview fragments when changing the
buffer's text scale."
(pcase major-mode
('latex-mode
(dolist (ov (overlays-in (point-min) (point-max)))
(if (eq (overlay-get ov 'category)
'preview-overlay)
(my/text-scale--resize-fragment ov))))
('org-mode
(dolist (ov (overlays-in (point-min) (point-max)))
(if (eq (overlay-get ov 'org-overlay-type)
'org-latex-overlay)
(my/text-scale--resize-fragment ov))))))
(defun my/text-scale--resize-fragment (ov)
(overlay-put
ov 'display
(cons 'image
(plist-put
(cdr (overlay-get ov 'display))
:scale (+ 1.0 (* 0.25 text-scale-mode-amount))))))
(add-hook 'text-scale-mode-hook #'my/text-scale-adjust-latex-previews)