emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Akira Kyle <akira@akirakyle.com>
To: yantar92@gmail.com
Cc: emacs-orgmode@gnu.org,reza@housseini.me
Subject: Re: svg file from tikz picture
Date: Thu, 22 Sep 2022 20:28:57 -0600	[thread overview]
Message-ID: <87czbmg6xi.fsf@akirakyle.com> (raw)
In-Reply-To: <875yhhxece.fsf@localhost>

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

I've been using the attached patch for the last few years and I've meaning to send it here/start a discussion about ob-latex.el since I used it pretty much daily to write tikz figures in org mode. So I'm glad to see this discussion has been started!

I've found it to be incredibly productive to use babel to develop tikz diagrams as I can make come changes and quickly `org-ctrl-c-ctrl-c` to render them in the same buffer.

I think when I made this patch I had been caught by some of the quirks of the svg export. For example, sometimes I would have some latex equation which I use ~org-latex-preview~ on as I was writing it, but then it would fail to render as mathjax upon html export since I would use some latex package that isn't available under mathjax. So by using ob-latex I could easily fix this by using the ~:file .svg~ header and get a nice html export. However due to the different way of assembling the ~.tex~ file sometimes ~org-latex-preview~ would work but ob-latex wouldn't. I think my use case may be fairly common and so I think ob-latex really should be updated so svg uses the ~org-latex-preview~ code. o

Also I think the ~.tikz~ extension doesn't really make any sense since one really can but arbitrary tex code in such a block, and I think that's why I renamed it in my patch. However I'm now realizing that this evaluation method probably doesn't make much since `:tangle` will already do this, with the added benefit of handling noweb references correctly. So perhaps this should be removed and document using tangling in lieu of ~:file *.tikz~?

PS: I'm not currently subbed to this mailing list, so please try to cc me

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ob-latex-Create-svg-images-the-same-way-as-png-image.patch --]
[-- Type: text/x-patch, Size: 9977 bytes --]

From 5d94745dfbe0858d4fd7d6530b821445b06d5013 Mon Sep 17 00:00:00 2001
From: Akira Kyle <akira@akirakyle.com>
Date: Tue, 4 Jan 2022 14:33:05 -0700
Subject: [PATCH] ob-latex: Create svg images the same way as png images

Also some cleanup of generation .html and .pdf files
 lisp/ob-latex.el | 161 +++++++++++++++--------------------------------
 1 file changed, 50 insertions(+), 111 deletions(-)

diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el
index a86699e22..71b01058c 100644
--- a/lisp/ob-latex.el
+++ b/lisp/ob-latex.el
@@ -39,7 +39,7 @@
 (declare-function org-create-formula-image "org" (string tofile options buffer &optional type))
 (declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
-(declare-function org-latex-guess-inputenc "ox-latex" (header))
+(declare-function org-latex-make-preamble "ox-latex" (info &optional template snippet?))
 (declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p &optional extra))
 (declare-function org-at-heading-p "org" (&optional _))
 (declare-function org-back-to-heading "org" (&optional invisible-ok))
@@ -115,12 +115,6 @@ exporting the literal LaTeX source."
   :group 'org-babel
   :type 'string)
-(defcustom org-babel-latex-htlatex-packages
-  '("[usenames]{color}" "{tikz}" "{color}" "{listings}" "{amsmath}")
-  "Packages to use for htlatex export."
-  :group 'org-babel
-  :type '(repeat (string)))
 (defun org-babel-expand-body:latex (body params)
   "Expand BODY according to PARAMS, return the expanded body."
   (mapc (lambda (pair) ;; replace variables
@@ -142,132 +136,82 @@ This function is called by `org-babel-execute-src-block'."
 	     (extension (file-name-extension out-file))
 	     (tex-file (org-babel-temp-file "latex-" ".tex"))
 	     (border (cdr (assq :border params)))
-	     (imagemagick (cdr (assq :imagemagick params)))
-	     (im-in-options (cdr (assq :iminoptions params)))
-	     (im-out-options (cdr (assq :imoutoptions params)))
 	     (fit (or (cdr (assq :fit params)) border))
 	     (height (and fit (cdr (assq :pdfheight params))))
 	     (width (and fit (cdr (assq :pdfwidth params))))
 	     (headers (cdr (assq :headers params)))
 	     (in-buffer (not (string= "no" (cdr (assq :buffer params)))))
+	     (imagemagick (cdr (assq :imagemagick params)))
+	     (im-in-options (cdr (assq :iminoptions params)))
+	     (im-out-options (cdr (assq :imoutoptions params)))
-	      (append (cdr (assq :packages params)) org-latex-packages-alist)))
+	      (append (cdr (assq :packages params)) org-latex-packages-alist))
+	     (org-format-latex-header
+	      (concat org-format-latex-header
+		      (mapconcat #'identity (cdr (assq :headers params)) "\n")
+		      (if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
+		      (if border
+			  (format "\\setlength{\\PreviewBorder}{%s}" border) "")
+		      (if height
+			  (concat "\n" (format "\\pdfpageheight %s" height)) "")
+		      (if width
+			  (concat "\n" (format "\\pdfpagewidth %s" width)) "")))
+	     (body (if fit 
+		       (concat "\n\\begin{preview}\n" body "\n\\end{preview}\n")
+		     body)))
          ((and (string-suffix-p ".png" out-file) (not imagemagick))
           (let ((org-format-latex-header
 		 (concat org-format-latex-header "\n"
 			 (mapconcat #'identity headers "\n"))))
-	    (org-create-formula-image
-             body out-file org-format-latex-options in-buffer)))
-	 ((string= "svg" extension)
-	  (with-temp-file tex-file
-	    (insert (concat (funcall org-babel-latex-preamble params)
-			    (mapconcat #'identity headers "\n")
-			    (funcall org-babel-latex-begin-env params)
-			    body
-			    (funcall org-babel-latex-end-env params))))
-	  (let ((tmp-pdf (org-babel-latex-tex-to-pdf tex-file)))
-            (let* ((log-buf (get-buffer-create "*Org Babel LaTeX Output*"))
-                   (err-msg "org babel latex failed")
-                   (img-out (org-compile-file
-	                     tmp-pdf
-                             (list org-babel-latex-pdf-svg-process)
-                             extension err-msg log-buf)))
-              (shell-command (format "mv %s %s" img-out out-file)))))
-         ((string-suffix-p ".tikz" out-file)
+	   (org-create-formula-image
+            body out-file org-format-latex-options in-buffer 'dvipng)))
+         ((and (string= "svg" extension) (not imagemagick))
+          (org-create-formula-image
+           body out-file org-format-latex-options in-buffer 'dvisvgm))
+         ((string-suffix-p ".tex" out-file)
 	  (when (file-exists-p out-file) (delete-file out-file))
 	  (with-temp-file out-file
 	    (insert body)))
-	 ((and (string= "html" extension)
+	 ((and (string= "html" extension) (not imagemagick)
 	       (executable-find org-babel-latex-htlatex))
-	  ;; TODO: this is a very different way of generating the
-	  ;; frame latex document than in the pdf case.  Ideally, both
-	  ;; would be unified.  This would prevent bugs creeping in
-	  ;; such as the one fixed on Aug 16 2014 whereby :headers was
-	  ;; not included in the SVG/HTML case.
-	  (with-temp-file tex-file
-	    (insert (concat
-		     "\\documentclass[preview]{standalone}
-		     (mapconcat (lambda (pkg)
-				  (concat "\\usepackage" pkg))
-				org-babel-latex-htlatex-packages
-				"\n")
-		     (if headers
-			 (concat "\n"
-				 (if (listp headers)
-				     (mapconcat #'identity headers "\n")
-				   headers) "\n")
-		       "")
-		     "\\begin{document}"
-		     body
-		     "\\end{document}")))
+	  (let ((org-format-latex-header
+		 (concat org-format-latex-header
+			 "\\def\\pgfsysdriver{pgfsys-tex4ht.def}")))
+	    (org-babel-latex-format-tex tex-file body))
 	  (when (file-exists-p out-file) (delete-file out-file))
 	  (let ((default-directory (file-name-directory tex-file)))
 	    (shell-command (format "%s %s" org-babel-latex-htlatex tex-file)))
-	  (cond
-	   ((file-exists-p (concat (file-name-sans-extension tex-file) "-1.svg"))
-	    (if (string-suffix-p ".svg" out-file)
-		(progn
-		  (shell-command "pwd")
-		  (shell-command (format "mv %s %s"
-					 (concat (file-name-sans-extension tex-file) "-1.svg")
-					 out-file)))
-	      (error "SVG file produced but HTML file requested")))
-	   ((file-exists-p (concat (file-name-sans-extension tex-file) ".html"))
-	    (if (string-suffix-p ".html" out-file)
-		(shell-command "mv %s %s"
-			       (concat (file-name-sans-extension tex-file)
-				       ".html")
-			       out-file)
-	      (error "HTML file produced but SVG file requested")))))
+	  (rename-file (concat (file-name-sans-extension tex-file) ".html")
+			 out-file))
 	 ((or (string= "pdf" extension) imagemagick)
-	  (with-temp-file tex-file
-	    (require 'ox-latex)
-	    (insert
-	     (org-latex-guess-inputenc
-	      (org-splice-latex-header
-	       org-format-latex-header
-	       (delq
-		nil
-		(mapcar
-		 (lambda (el)
-		   (unless (and (listp el) (string= "hyperref" (cadr el)))
-		     el))
-		 org-latex-default-packages-alist))
-	       org-latex-packages-alist
-	       nil))
-	     (if fit "\n\\usepackage[active, tightpage]{preview}\n" "")
-	     (if border (format "\\setlength{\\PreviewBorder}{%s}" border) "")
-	     (if height (concat "\n" (format "\\pdfpageheight %s" height)) "")
-	     (if width  (concat "\n" (format "\\pdfpagewidth %s" width))   "")
-	     (if headers
-		 (concat "\n"
-			 (if (listp headers)
-			     (mapconcat #'identity headers "\n")
-			   headers) "\n")
-	       "")
-	     (if fit
-		 (concat "\n\\begin{document}\n\\begin{preview}\n" body
-			 "\n\\end{preview}\n\\end{document}\n")
-	       (concat "\n\\begin{document}\n" body "\n\\end{document}\n"))))
-          (when (file-exists-p out-file) (delete-file out-file))
-	  (let ((transient-pdf-file (org-babel-latex-tex-to-pdf tex-file)))
+	  (org-babel-latex-format-tex tex-file body)
+	  (let ((default-directory (file-name-directory tex-file)))
+	    (org-latex-compile tex-file))
+	  (let ((transient-pdf-file
+		 (concat (file-name-sans-extension tex-file) ".pdf")))
+	    (when (file-exists-p out-file) (delete-file out-file))
 	     ((string= "pdf" extension)
 	      (rename-file transient-pdf-file out-file))
-	       transient-pdf-file out-file im-in-options im-out-options)
-	      (when (file-exists-p transient-pdf-file)
-		(delete-file transient-pdf-file)))
-	     (t
-	      (error "Can not create %s files, please specify a .png or .pdf file or try the :imagemagick header argument"
-		     extension))))))
+	       transient-pdf-file out-file im-in-options im-out-options)))))
+	 (t
+	  (error "Can't create %s files, please specify a .tex, .pdf, .png, or .svg file, or try the :imagemagick header argument"
+		 extension)))
         nil) ;; signal that output has already been written to file
+(defun org-babel-latex-format-tex (tex-file body)
+  "Generate a temporary tex file from execute params."
+  (with-temp-file tex-file
+    (insert
+     (org-latex-make-preamble
+      (org-export-get-environment (org-export-get-backend 'latex))
+      org-format-latex-header)
+     (concat "\n\\begin{document}\n" body "\n\\end{document}\n"))))
 (defun org-babel-latex-convert-pdf (pdffile out-file im-in-options im-out-options)
   "Generate a file from a pdf file using imagemagick."
   (let ((cmd (concat "convert " im-in-options " " pdffile " "
@@ -275,11 +219,6 @@ This function is called by `org-babel-execute-src-block'."
     (message "Converting pdffile file %s..." cmd)
     (shell-command cmd)))
-(defun org-babel-latex-tex-to-pdf (file)
-  "Generate a pdf file according to the contents FILE."
-  (require 'ox-latex)
-  (org-latex-compile file))
 (defun org-babel-prep-session:latex (_session _params)
   "Return an error because LaTeX doesn't support sessions."
   (error "LaTeX does not support sessions"))

  reply	other threads:[~2022-09-23 15:52 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <3bc47afb-0bac-f6e8-1097-13dcb6f2be1f@housseini.me>
2022-08-15 18:50 ` svg file from tikz picture reza
2022-08-16  9:42   ` Ihor Radchenko
     [not found]     ` <964a4117-ef6c-8d41-a25d-00e61c0c93d8@housseini.me>
2022-08-16 10:00       ` reza
2022-08-16 10:13         ` Ihor Radchenko
     [not found]           ` <0931497c-9075-c214-c7f2-6507340a6d74@housseini.me>
2022-08-16 10:19             ` reza
2022-08-16 10:31               ` Ihor Radchenko
     [not found]                 ` <6daeb56b-163c-f862-5866-da624b43edd9@housseini.me>
2022-08-16 11:06                   ` reza
2022-08-16 11:22                     ` Ihor Radchenko
     [not found]                       ` <7dcd1348-6faf-8464-38b5-8efac7c69250@housseini.me>
2022-08-16 11:25                         ` reza
     [not found]                           ` <be3e5412-37ff-c1c7-7a27-3793d72842d4@housseini.me>
2022-09-20  9:55                             ` reza
2022-09-20 20:53                               ` Edouard Debry
2022-09-21  9:32                               ` Ihor Radchenko
2022-09-23  2:28                                 ` Akira Kyle [this message]
2022-09-25  7:52                                   ` Ihor Radchenko
2022-11-14  5:52                                     ` Ihor Radchenko

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=87czbmg6xi.fsf@akirakyle.com \
    --to=akira@akirakyle.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=reza@housseini.me \
    --cc=yantar92@gmail.com \


* 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).