emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Matt Huszagh <huszaghmatt@gmail.com>
To: sebastien.miquel@posteo.eu
Cc: , "emacs-orgmode@gnu.org" <emacs-orgmode@gnu.org>
Subject: Re: Patch to align baseline of latex fragments and surrounding text
Date: Thu, 09 Dec 2021 14:18:40 -0800	[thread overview]
Message-ID: <87ilvxmngf.fsf@gmail.com> (raw)
In-Reply-To: <c5cf414c-5a55-de0f-7ddb-4a2a60aedc53@posteo.eu>

[-- Attachment #1: Type: text/plain, Size: 2821 bytes --]

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

> This looks great indeed but I've failed to reproduce in my
> environment.

Thanks for testing this Sébastien.

> I couldn't get ~org--match-text-baseline-ascent~ to compute the
> ascent : the ~xml-get-attribute~ call returns
>   : ("-16.945024" "12.153473" "16.148855" "8.064997")
> which gives an ascent < -100, and the code then defaults to 'center.

I'd need to know more about your setup for generating latex
fragments. Did you follow all the directions in
org--match-text-baseline-ascent? How is your org-format-latex-header
set? In particular, are you using \documentclass[preview]{standalone}?
If you can provide me with the TeX file used to generate the fragment,
as well as the SVG file you get as a result, that would be helpful too.

> The options described in your =my-dvisvgm= seem outdated, you can
> check the latest default value of =dvisvgm= : =use-xcolor= is
> deprecated and a =:image-size-adjust= property is provided for the
> images to be sized properly. Are the arguments =--no-fonts= and
> =--exact-bbox= necessary ?

Hm, I'm not actually sure why I put use-xcolor in there, but it isn't
necessary. I've removed it in the updated patch (attached).

:image-size-adjust isn't necessary, I just mentioned it to point out
that baseline alignment works regardless of the size of a latex fragment
(I have another open PR that allows setting the size of fragments in a
context dependent way, which can be used for instance, to keep fragments
size-aligned to the surrounding text). I expect using the scale
parameter in org-format-latex-options will work similarly, but I'll

--no-fonts is the same as -n. The --exact-bbox flag is necessary to
avoid cropping in certain cases (see
https://github.com/mgieseki/dvisvgm/issues/8). You're free to use
--bbox=min, but your glyphs may be cut off in places and this may affect
the baseline location too, though I haven't tested it.

> If there are no drawbacks, perhaps this behaviour should be the
> default. Otherwise, it should at least be easier to toggle.

I didn't attempt to make this the default because it requires a specific
setup, which is also different from the current default setup in other
respects. Most importantly, it requires using the standalone document
class, though I believe article is used at the moment.

> Can something similar be done with =dvipng= ?

Unfortunately I don't think so. This code isn't doing anything fancy; it
has no way of computing the text baseline from some arbitrary image file
displaying text. Instead, it relies on some other tool providing this
information inside the image file. In this case, standalone encodes this
information in the viewbox of the SVG file.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-make-preview-overlay-Add-ability-to-set-vertical.patch --]
[-- Type: text/x-patch, Size: 4934 bytes --]

From 2640b24d2cce8e2b61101125c348db35800570ff Mon Sep 17 00:00:00 2001
From: Matt Huszagh <huszaghmatt@gmail.com>
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}
+  (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
+  :type '(symbol function integer)
+  :group 'org)
 ;;; 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.

  reply	other threads:[~2021-12-09 22:33 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-10 23:23 Patch to align baseline of latex fragments and surrounding text Matt Huszagh
2021-10-10 23:29 ` Matt Huszagh
2021-12-03  2:32   ` Matt Huszagh
2021-12-09 20:59     ` Sébastien Miquel
2021-12-09 22:18       ` Matt Huszagh [this message]
2021-12-10 15:49         ` Sébastien Miquel
2021-12-11  4:53           ` [Patch] Align " Matt Huszagh
2022-07-30  9:55             ` Ihor Radchenko
2024-01-19  6:41               ` Matt Huszagh
2024-01-19  9:33                 ` Timothy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ilvxmngf.fsf@gmail.com \
    --to=huszaghmatt@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=sebastien.miquel@posteo.eu \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).