From 2640b24d2cce8e2b61101125c348db35800570ff Mon Sep 17 00:00:00 2001 From: Matt Huszagh Date: Sun, 10 Oct 2021 15:46:05 -0700 Subject: [PATCH] org--make-preview-overlay: Add ability to set vertical alignment of latex fragments * lisp/org.el (org--match-text-baseline-ascent): Add function that computes the value of :ascent to match the baseline of the fragment to the surrounding text. (org-latex-fragment-overlay-ascent): Add custom variable that allows a function to be used to compute the value of :ascent. (org--make-preview-overlay): Incorporate the custom variable. --- lisp/org.el | 88 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index 405f0f0f9..91a4d0bf5 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -320,6 +320,73 @@ identifier." :version "24.1" :group 'org-id) +(defun org--match-text-baseline-ascent (imagefile imagetype) + "Set :ascent to match the text baseline of an image to the surrounding text. +IMAGEFILE is the path of the image file and IMAGETYPE is the +image file type. + +This function currently only works for SVG images (defaulting to +'center otherwise). It also requires that the SVG's viewbox is +correctly set according to the text baseline position. +Specifically, it computes + +ascent = 100 * -min-y / height + +where min-y and height are taken from the viewbox. If this +computation returns a non-sensical value (below 0 or above 100), +it will return 'center instead. + +It's possible to include text baseline information in the viewbox +by using \\documentclass[preview]{standalone} in the input LaTeX +file, compiling first to DVI and then converting this to an SVG +image with dvisvgm. + +For example, + +(setq my-dvisvgm + '(my-dvisvgm :programs (\"latex\" \"dvisvgm\") + :description \"dvi > svg\" + :message \"you need to install latex and dvisvgm.\" + :image-input-type \"dvi\" + :image-output-type \"svg\" + :latex-compiler (\"latex -output-directory=%o %f\") + :image-converter (\"dvisvgm --no-fonts --exact-bbox -c %S -o %O %f\"))) + +(add-to-list 'org-preview-latex-process-alist my-dvisvgm) +(setq org-preview-latex-default-process 'my-dvisvgm) + +(setq org-format-latex-header + \"\\documentclass[preview]{standalone} + [PACKAGES] + [DEFAULT-PACKAGES]\")" + (if (eq imagetype 'svg) + (let* ((viewbox (split-string + (xml-get-attribute (car (xml-parse-file imagefile)) 'viewBox))) + (min-y (string-to-number (nth 1 viewbox))) + (height (string-to-number (nth 3 viewbox))) + (ascent (round (* -100 (/ min-y height))))) + (if (or (< ascent 0) (> ascent 100)) + 'center + ascent)) + 'center)) + +(defcustom org-latex-fragment-overlay-ascent 'center + "Value of :ascent used for LaTeX image fragments. +Org uses `overlay-put' to overlay LaTeX image fragments on inline +math. `overlay-put' takes an :ascent parameter that can specify +the vertical offset of this image fragment. See the 'Image +Descriptors' section of the elisp manual for more information. + +If this variable is a symbol or integer it will be passed +directly to :ascent. It can also be a function that takes the +image file as an argument. The function will be evaluated and +its return value passed to :ascent. The primary benefit of this +option is to be able to compute the baseline of the latex +fragment and to align it with the baseline of the surrounding +text." + :type '(symbol function integer) + :group 'org) + ;;; Version (org-check-version) @@ -15928,15 +15995,18 @@ Argument IMAGETYPE is the extension of the displayed image, as a string. It defaults to \"png\"." (let ((ov (make-overlay beg end)) (imagetype (or (intern imagetype) 'png))) - (overlay-put ov 'org-overlay-type 'org-latex-overlay) - (overlay-put ov 'evaporate t) - (overlay-put ov - 'modification-hooks - (list (lambda (o _flag _beg _end &optional _l) - (delete-overlay o)))) - (overlay-put ov - 'display - (list 'image :type imagetype :file image :ascent 'center)))) + (let ((ascent (if (functionp org-latex-fragment-overlay-ascent) + (funcall org-latex-fragment-overlay-ascent image imagetype) + org-latex-fragment-overlay-ascent))) + (overlay-put ov 'org-overlay-type 'org-latex-overlay) + (overlay-put ov 'evaporate t) + (overlay-put ov + 'modification-hooks + (list (lambda (o _flag _beg _end &optional _l) + (delete-overlay o)))) + (overlay-put ov + 'display + (list 'image :type imagetype :file image :ascent ascent))))) (defun org-clear-latex-preview (&optional beg end) "Remove all overlays with LaTeX fragment images in current buffer. -- 2.31.1