From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id mP/PGkCEsmFj1QAAgWs5BA (envelope-from ) for ; Thu, 09 Dec 2021 23:33:36 +0100 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id iHGQFkCEsmH4PAAAB5/wlQ (envelope-from ) for ; Thu, 09 Dec 2021 22:33:36 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id CC18A27C1D for ; Thu, 9 Dec 2021 23:33:35 +0100 (CET) Received: from localhost ([::1]:50812 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mvRyn-0005tP-07 for larch@yhetil.org; Thu, 09 Dec 2021 17:33:33 -0500 Received: from eggs.gnu.org ([209.51.188.92]:35636) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mvRkV-0007mI-DR for emacs-orgmode@gnu.org; Thu, 09 Dec 2021 17:18:48 -0500 Received: from [2607:f8b0:4864:20::634] (port=42612 helo=mail-pl1-x634.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mvRkS-00073x-Nk for emacs-orgmode@gnu.org; Thu, 09 Dec 2021 17:18:47 -0500 Received: by mail-pl1-x634.google.com with SMTP id u17so4940863plg.9 for ; Thu, 09 Dec 2021 14:18:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=RAq1sJllZvY4DqlKBUXWFZ45UM4lG6LqeAFS0XFBolc=; b=ADxHJPYvgiY2B4Nda3bRqWCIQ441F6SNoWTPSGGa8Qku3Gg1JHn0vLQWkn2X63CYgE jxE3s1YU5LI1DqSI1FjtU1g7qTCUcJCpeBBRJyTl5HyU4JZNQmMSZAE3egIYoM5y0vzA wcfl+i9LcuDDEp8qAODRKdhtLkAqu/hM3IdpAV17ariVlwCRghPSve74K81aRWuEquom snqKKx2vXgWXL0F1e6nsEU2w1hfLnt3eIJey9e2soSJWTZoiXa49YLPXBBk6yWWit305 8DVmnS8QEiPWHbe7MH4opf954yZPC4lYWk7++TjTEipJLCEdsXjyK/7p8lqC+MC3uWcp 9BMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:cc:subject:in-reply-to:references :date:message-id:mime-version; bh=RAq1sJllZvY4DqlKBUXWFZ45UM4lG6LqeAFS0XFBolc=; b=OupG0GTb2ymLTaOLvdjG6zAT0ynzYlVd69bBYneSPxGKAcblm1XyNH3bW5j+Wdd1ub 9w456oz1KT5f2nNHYnICc4ewon6xv96lXMncp/Jfcdv7CEzvixx5L7tbP4f5X46ztUYK 584iRbZfeLXAGEHrCPhUS24OtemtezpfYMuF6hebR8CrGr4/p386dyQAcq6ZWU4w0coI oNYqT39wS77nvM8sShcWH2hCZF/8jTmPyusrvgn8djfac7PtPVKcd4xdjQiDWW+htciz hw8oTG0C1ve3+8bOLyREQd70wCTr+ochlVBrNVWi6K6CqswqMOKZ9sXXoZn3575B9UB7 /D1Q== X-Gm-Message-State: AOAM532wMZnz2zCCz0+KDUKjlFwvhig8Gn7BS1UEE4i0gBoP0UymjvG4 a7IGK72F7G3aq00VjNS8YGORi6XpKfw= X-Google-Smtp-Source: ABdhPJwG3y96lUFwdoizT+dcCdflYitnxcp9Clyz7uHwyDGgMKpFH0SF16S1hs6zorYS7BLhc/GNwQ== X-Received: by 2002:a17:90a:e395:: with SMTP id b21mr18498219pjz.103.1639088321477; Thu, 09 Dec 2021 14:18:41 -0800 (PST) Received: from ryzen3950 (c-208-82-98-189.rev.sailinternet.net. [208.82.98.189]) by smtp.gmail.com with ESMTPSA id h20sm557436pgh.13.2021.12.09.14.18.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Dec 2021 14:18:40 -0800 (PST) From: Matt Huszagh To: sebastien.miquel@posteo.eu Subject: Re: Patch to align baseline of latex fragments and surrounding text In-Reply-To: References: <874k9oxy48.fsf@gmail.com> <871r4sxxuv.fsf@gmail.com> <87v906bepp.fsf@gmail.com> Date: Thu, 09 Dec 2021 14:18:40 -0800 Message-ID: <87ilvxmngf.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::634 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=huszaghmatt@gmail.com; helo=mail-pl1-x634.google.com X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, PDS_HP_HELO_NORDNS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: , "emacs-orgmode@gnu.org" Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1639089215; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=RAq1sJllZvY4DqlKBUXWFZ45UM4lG6LqeAFS0XFBolc=; b=bRdXCN8yx50vlNkJQucProi2qP22k7nr8od7hyYbg63PfUvPiAEGxUzTeyFs1taVnV0M6d laPC1UiHWXwwJv2g59b5aFDByEpWH/ZoYVRdeIQ1AshXdhuNZY0e/K+U32b4ndPGmpIKx4 G1v1n7eJpqWnfpM2HitHRulz1cFkG6kjYex/y2dnCaimbLAu8NS8V7tzbjdfmTY0NBBvy8 UxeIe43VgyZMzkxPW4VWxhtoWgjrn+CWrE1daToBF+mq6F43GwacH+oLnu7Png39dBpj5t U44VvZr9GBVC4uC2R7aMwtOb4u7h2FgLypM2nFrQJj5pgLM3zHbMqR/V6PFtcw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1639089215; a=rsa-sha256; cv=none; b=FDBVeDXp+aYrLUjnH/DacjS0lAJnuTQNy+0hT1BpldsBJ5ygT17gsdldKtGK64B4GafL5p LwU93y0C17IkWiGhXN8NCw4jUQuOUjS+WGom9nfDCtzAUmIj6K6X0TBxlBlcfeJa/kupLU 8Z7xRmthaCOo5WnHZbfszR8/8Q26BjfQ9vxpBsAs80rLqQBdto9KEWRXTQwMXYejmkWndY ncxL0aJ4tg4ZLv9Bjnoc0TDceTDcsb5q2B0c8jUjU1+NIuP74jx97vVCSEtzWmhPiypKRp iyPyOnmdJXpKRhkiVMNX9JufLUDvnRlQqkgAU5IMfbzJQh5CvFR4BY/aTSWEmA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gmail.com header.s=20210112 header.b=ADxHJPYv; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -1.86 Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gmail.com header.s=20210112 header.b=ADxHJPYv; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: CC18A27C1D X-Spam-Score: -1.86 X-Migadu-Scanner: scn1.migadu.com X-TUID: MdtpLol3UUZR --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable S=C3=A9bastien Miquel writes: > This looks great indeed but I've failed to reproduce in my > environment. Thanks for testing this S=C3=A9bastien. > I couldn't get ~org--match-text-baseline-ascent~ to compute the > ascent : the ~xml-get-attribute~ call returns > =C2=A0: ("-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 =3Dmy-dvisvgm=3D seem outdated, you can > check the latest default value of =3Ddvisvgm=3D : =3Duse-xcolor=3D is > deprecated and a =3D:image-size-adjust=3D property is provided for the > images to be sized properly. Are the arguments =3D--no-fonts=3D and > =3D--exact-bbox=3D 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 investigate. --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=3Dmin, 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 =3Ddvipng=3D ? 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. Thanks Matt --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-org-make-preview-overlay-Add-ability-to-set-vertical.patch >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 --=-=-=--