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 5dfjMit2Y2G3cAEAgWs5BA (envelope-from ) for ; Mon, 11 Oct 2021 01:24:27 +0200 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 wLk2LCt2Y2E5RgAAB5/wlQ (envelope-from ) for ; Sun, 10 Oct 2021 23:24:27 +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 DE122A6D5 for ; Mon, 11 Oct 2021 01:24:26 +0200 (CEST) Received: from localhost ([::1]:53834 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mZiB7-00025Q-Tr for larch@yhetil.org; Sun, 10 Oct 2021 19:24:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38506) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mZiAi-000250-Pk for emacs-orgmode@gnu.org; Sun, 10 Oct 2021 19:24:00 -0400 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]:34565) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mZiAg-0002N4-Rt for emacs-orgmode@gnu.org; Sun, 10 Oct 2021 19:24:00 -0400 Received: by mail-pf1-x42f.google.com with SMTP id g14so13256123pfm.1 for ; Sun, 10 Oct 2021 16:23:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version; bh=U3ZlYaGf7FNPVC84znq/k/N3vKpFY+1gwaym5EPa+DM=; b=GP+ONP0hX7Y0TEMTqU1RYe5xN0dsUgU9ZqoD/ctxGJkega7PNgZh7UGIGfY8kLpmtA mvHBH9QQbALiuE3syBEH+ZvtiQAmt+oH4IzLhoL5iNLI/DPJnQa8ax4t7v0+xqOK3jbp 4cm1tpn7nBOSRVoe4cogxmAzeTbgsUvvF1TV+fzfSxfNw+LQypFQFGSFqJN/iEq7totX GpiFv3NpXwTsWKIuoNdA3GJjM5EfSun3fPb4660/DbaC3EsUD0U0mMde6aEiOpkkXFbl uciDUCKtKmJ6SjDsxZ1gpTdxASQoBM1FUFmosC8vDYT7h9ILSv24GVaZoMJrwYUe2KOo /pAQ== 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:subject:date:message-id:mime-version; bh=U3ZlYaGf7FNPVC84znq/k/N3vKpFY+1gwaym5EPa+DM=; b=l5LUw8UO/158ksMUdv+cZVTHwc1dBf9B4qg7QtPvGOBYbK36eVrptrkWCaMYByVkCe mpWjV0JEcq8giuuF5tcWRMkAoWQBenTFCYZhvg9pm+CN/7WTaARPBx1pUx1I3D5WZkyM 5nlFY00f94RIiBXauAO+G+WoTN8tCHNnP9l9TMDtx/Ho1qPKhx+ZjR2ikXvJysAWpdl9 8uamAe9Gi0W2rQvCbv/PV+QLC/TNRxYfC76yWCKodZFxzhBkruv8wRxpJunYKEZosxO8 y9sqkFZ1FzNbqJiXEE1U+G75HZ0GJ1CT3QzuM1c2pvnEzsd9JfsA/c1WrQxG6tp0knsA 5mQg== X-Gm-Message-State: AOAM5324UAEkpgAUjgJSWlRKwbB2RXYmllCGUM9tOtkWK2RVMuJ0PxVF JHr2yW+h5Te/4gE5xV8epztsytWDpx0= X-Google-Smtp-Source: ABdhPJxfdKr3ehRCY38yK34/yWE6vOOCk35R+NOLP/ho9xX9OG8I0Q7OeaiIL92cEEAPfEUxVc6/Rg== X-Received: by 2002:a63:f313:: with SMTP id l19mr15627515pgh.40.1633908236672; Sun, 10 Oct 2021 16:23:56 -0700 (PDT) Received: from ryzen3950 (c-73-170-21-48.hsd1.ca.comcast.net. [73.170.21.48]) by smtp.gmail.com with ESMTPSA id y3sm5987953pge.44.2021.10.10.16.23.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Oct 2021 16:23:55 -0700 (PDT) From: Matt Huszagh To: "emacs-orgmode@gnu.org" Cc: Subject: Patch to align baseline of latex fragments and surrounding text Date: Sun, 10 Oct 2021 16:23:51 -0700 Message-ID: <874k9oxy48.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2607:f8b0:4864:20::42f; envelope-from=huszaghmatt@gmail.com; helo=mail-pf1-x42f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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=1633908267; 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:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=U3ZlYaGf7FNPVC84znq/k/N3vKpFY+1gwaym5EPa+DM=; b=HtTBkxcRioNJJ3s1891wx38kRup5iOozLvB2pebeEGq6MrRxoLLQ6g2QhMERpYJ5jgp6AE 2Uuq3X21i9BcV+4JDR0ijip5hMgOo3BETNzOll5Jz0LGwsk3Lmz0hy8r0xu9TFQl09rM9B KHiTmuyTJgvpOmzGzCCCnwt2yui4Ilnd6qThQGCtyswpgKIowYI8WV6uf0jufdwVrMc5q6 An5yVAthtABKM+CcyTil2rcief9+lqu0bYgcl8hs94i8Kq6UxMNGiKDIxj2jCl8TEwgLPo OAiGTsr1gbb5ZHd1lNogFo81pimWghOXfGvcZOz8LfrdVzzxLz9Lyq0erFevow== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1633908267; a=rsa-sha256; cv=none; b=UUH24YYXJBgP8lfzGY7Whh3DpJDbM2xiXac5qotWOtz2XlB6sSHx6E8te19XGZlp7cJbiz qp3pDltetN3JBOftTuM5Mb6tHFJHZmiuPjqskU+2k9mrBgdNmxRTfwtZKFF9pQX9JOiLQT QY0WR7Iq3/vZUSj1LEoeLuaqgKHP22uVqacrUF4KsJf/sHFVyjLJeyI4a7xrBUmiBaonWt RBMz9fu7MvVSOZsWBAe+fLGoXAXQVaqaxP3pqdmbuG9BK+0M6E5MP8Ek4Wzw6V0TKDMBbA R8EZplP+8gu1x21SwEt25m57hZeH4JmDV5Z7FRA0EoZZcGJJKBccEgjeQXb4Uw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=GP+ONP0h; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Spam-Score: -1.61 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=GP+ONP0h; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Queue-Id: DE122A6D5 X-Spam-Score: -1.61 X-Migadu-Scanner: scn0.migadu.com X-TUID: s4VI6/aAZXYj --=-=-= Content-Type: text/plain Hello, I've created a patch to align the baseline of latex image fragments to the surrounding text. The patch consists of several parts. First, it adds a customizable variable that can be set to a user supplied function to compute the value of :ascent passed to `overlay-put'. It can also be set to a symbol (e.g., 'center, which is the current setting and still the default), or an integer (:ascent can take an integer percentage). The patch also modifies `org--make-preview-overlay' to use this new variable. The other part of the patch is a new function that computes the correct value for :ascent from an SVG file. Unfortunately, this isn't a general-purpose solution to baseline text alignment. It currently only works with SVG images and requires that these SVG images encode the text baseline in the viewBox attribute (I've explained in the function documentation how to achieve this). I was not initially planning to include the function because it only works in certain special cases (though if you setup your SVG image generation as I've described in the documentation it should work correctly for all of your LaTeX fragments). However, I ultimately decided it was beneficial to include it for several reasons: (1) it would not be obvious for many users how to write this function on their own, (2) by including it, others can improve upon it, and (3) I tried to minimize corner cases by leaving the default value as 'center and having the function return 'center whenever it detects an incorrect :ascent value. Let me know what you think! Best Matt --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-org-make-preview-overlay-Add-ability-to-set-vertical.patch >From 6c33fa1875cc169616d878b59054d50980f741f3 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 | 89 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index 405f0f0f9..dbc288a3c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -320,6 +320,74 @@ 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.\" + :use-xcolor t + :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 +15996,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 --=-=-=--