Browse Source

Use dvisvgm to preview latex formulas

* ox-html.el (org-html-with-latex): Add dvisvgm support.
(org-html-with-latex): Add dvisvgm support.
(org-html-format-latex): "ltxpng" -> "ltximg".
(org-html-latex-environment): Add dvisvgm support.
(org-html-latex-fragment): Add dvisvgm support.

* org.el (org-preview-latex-default-process): New variable.
(org-latex-create-formula-image-program): Rename it to `org-preview-latex-default-process'.
(org-latex-preview-ltximg-directory): Rename it to `org-preview-latex-image-directory'.
(org-preview-latex-image-directory): New variable.
(org--format-latex-make-overlay): Add optional image-type, which used to deal with svg.
(org-toggle-latex-fragment): "org-ltxpng" -> "org-ltximg".
(org-format-latex): Add dvisvgm support.
(org-create-formula-image): Big refactor, merge dvipng and imagemagick
backend's feature.  Add dvisvgm feature.
(org-preview-latex-process-alist): Add new variable, which used to set
latex preview processes.
(org-create-formula-image-with-dvipng):
(org-create-formula-image-with-imagemagick): Useless, removed.

* org.texi (@LaTeX{} fragments):
(Previewing @LaTeX{} fragments):
(Math formatting in HTML export):
(Working with @LaTeX{} math snippets): Add dvisvgm information.
Feng Shu 3 years ago
parent
commit
bf93e166be
3 changed files with 285 additions and 230 deletions
  1. 27 16
      doc/org.texi
  2. 222 175
      lisp/org.el
  3. 36 39
      lisp/ox-html.el

+ 27 - 16
doc/org.texi

@@ -10395,10 +10395,10 @@ snippets will be identified as @LaTeX{} source code:
 @item
 Environments of any kind@footnote{When MathJax is used, only the
 environments recognized by MathJax will be processed.  When
-@file{dvipng} program or @file{imagemagick} suite is used to create images,
-any @LaTeX{} environment will be handled.}.  The only requirement is that the
-@code{\begin} statement appears on a new line, at the beginning of the line
-or after whitespaces only.
+@file{dvipng} program, @file{dvisvgm} program or @file{imagemagick} suite is
+used to create images, any @LaTeX{} environment will be handled.}.  The only
+requirement is that the @code{\begin} statement appears on a new line, at the
+beginning of the line or after whitespaces only.
 @item
 Text within the usual @LaTeX{} math delimiters.  To avoid conflicts with
 currency specifications, single @samp{$} characters are only recognized as
@@ -10445,12 +10445,12 @@ lines:
 @subsection Previewing @LaTeX{} fragments
 @cindex @LaTeX{} fragments, preview
 
-@vindex org-latex-create-formula-image-program
-If you have a working @LaTeX{} installation and either @file{dvipng} or
-@file{convert} installed@footnote{These are respectively available at
-@url{http://sourceforge.net/projects/dvipng/} and from the @file{imagemagick}
-suite. Choose the converter by setting the variable
-@code{org-latex-create-formula-image-program} accordingly.}, @LaTeX{}
+@vindex org-preview-latex-default-process
+If you have a working @LaTeX{} installation and @file{dvipng}, @file{dvisvgm}
+or @file{convert} installed@footnote{These are respectively available at
+@url{http://sourceforge.net/projects/dvipng/}, @url{http://dvisvgm.bplaced.net/}
+and from the @file{imagemagick} suite.  Choose the converter by setting the
+variable @code{org-preview-latex-default-process} accordingly.}, @LaTeX{}
 fragments can be processed to produce images of the typeset expressions to be
 used for inclusion while exporting to HTML (see @pxref{@LaTeX{} fragments}),
 or for inline previewing within Org mode.
@@ -11715,6 +11715,7 @@ You could use @code{http} addresses just as well.
 @subsection Math formatting in HTML export
 @cindex MathJax
 @cindex dvipng
+@cindex dvisvgm
 @cindex imagemagick
 
 @LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be displayed in two
@@ -11739,13 +11740,18 @@ template can be configure via @code{org-html-mathjax-template}.
 If you prefer, you can also request that @LaTeX{} fragments are processed
 into small images that will be inserted into the browser page.  Before the
 availability of MathJax, this was the default method for Org files.  This
-method requires that the @file{dvipng} program or @file{imagemagick} suite is
-available on your system.  You can still get this processing with
+method requires that the @file{dvipng} program, @file{dvisvgm} or
+@file{imagemagick} suite is available on your system.  You can still get
+this processing with
 
 @example
 #+OPTIONS: tex:dvipng
 @end example
 
+@example
+#+OPTIONS: tex:dvisvgm
+@end example
+
 or:
 
 @example
@@ -12910,6 +12916,7 @@ and open the formula file with the system-registered application.
 @end table
 
 @cindex dvipng
+@cindex dvisvgm
 @cindex imagemagick
 @item PNG images
 
@@ -12919,16 +12926,20 @@ This option is activated on a per-file basis with
 #+OPTIONS: tex:dvipng
 @end example
 
+@example
+#+OPTIONS: tex:dvisvgm
+@end example
+
 or:
 
 @example
 #+OPTIONS: tex:imagemagick
 @end example
 
-With this option, @LaTeX{} fragments are processed into PNG images and the
-resulting images are embedded in the exported document.  This method requires
-that the @file{dvipng} program or @file{imagemagick} suite be available on
-your system.
+With this option, @LaTeX{} fragments are processed into PNG or SVG images and
+the resulting images are embedded in the exported document.  This method requires
+that the @file{dvipng} program, @file{dvisvgm} or @file{imagemagick} suite be
+available on your system.
 @end enumerate
 
 @node Working with MathML or OpenDocument formula files

+ 222 - 175
lisp/org.el

@@ -3991,27 +3991,122 @@ When using LaTeXML set this option to
 	  (const :tag "None" nil)
 	  (string :tag "\nShell command")))
 
-(defcustom org-latex-create-formula-image-program 'dvipng
-  "Program to convert LaTeX fragments with.
-
-dvipng          Process the LaTeX fragments to dvi file, then convert
-                dvi files to png files using dvipng.
-                This will also include processing of non-math environments.
-imagemagick     Convert the LaTeX fragments to pdf files and use imagemagick
-                to convert pdf files to png files"
+(define-obsolete-variable-alias
+  'org-latex-create-formula-image-program
+  'org-preview-latex-default-process "25.1")
+
+(defcustom org-preview-latex-default-process 'dvipng
+  "The default process to convert LaTeX fragments to image files.
+All available processes and theirs documents can be found in
+`org-preview-latex-process-alist', which see."
   :group 'org-latex
-  :version "24.1"
-  :type '(choice
-	  (const :tag "dvipng" dvipng)
-	  (const :tag "imagemagick" imagemagick)))
+  :version "25.2"
+  :package-version '(Org . "9.0")
+  :type 'symbol)
+
+(defcustom org-preview-latex-process-alist
+  '((dvipng
+     :programs ("latex" "dvipng" "gs")
+     :description "dvi > png"
+     :message "you need to install programs: latex, dvipng and ghostscript."
+     :image-input-type "dvi"
+     :image-output-type "png"
+     :image-size-adjust (1.0 . 1.0)
+     :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
+     :image-converter ("dvipng -fg %F -bg %B -D %D -T tight -o %b.png %f"))
+    (dvisvgm
+     :programs ("latex" "dvisvgm" "gs")
+     :description "dvi > svg"
+     :message "you need to install programs: latex, dvisvgm and ghostscript."
+     :use-xcolor t
+     :image-input-type "dvi"
+     :image-output-type "svg"
+     :image-size-adjust (1.7 . 1.5)
+     :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
+     :image-converter ("dvisvgm %f -n -b min -c %S -o %b.svg"))
+    (imagemagick
+     :programs ("latex" "convert" "gs")
+     :description "pdf > png"
+     :message
+     "you need to install programs: latex, imagemagick and ghostscript."
+     :use-xcolor t
+     :image-input-type "pdf"
+     :image-output-type "png"
+     :image-size-adjust (1.0 . 1.0)
+     :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
+     :image-converter
+     ("convert -density %S -trim -antialias %f -quality 100 %b.png")))
+  "Definitions of external processes for LaTeX previewing.
+Org mode can use some external commands to generate TeX snippet's images for
+previewing or inserting into HTML files, e.g., \"dvipng\".  This variable tells
+`org-create-formula-image' how to call them.
+
+The value is an alist with the pattern (NAME . PROPERTIES).  NAME is a symbol.
+PROPERTIES accepts the following attributes:
+
+  :programs           list of strings, required programs.
+  :description        string, describe the process.
+  :message            string, message it when required programs cannot be found.
+  :image-input-type   string, input file type of image converter (e.g., \"dvi\").
+  :image-output-type  string, output file type of image converter (e.g., \"png\").
+  :use-xcolor         boolean, when non-nil, LaTeX \"xcolor\" macro is used to
+                      deal with background and foreground color of image.
+                      Otherwise, dvipng style background and foregroud color
+                      format are generated.  You may then refer to them in
+                      command options with \"%F\" and \"%B\".
+  :image-size-adjust  cons of numbers, the car element is used to adjust LaTeX
+                      image size showed in buffer and the cdr element is for
+                      HTML file.  This option is only useful for process
+                      developers, users should use variable
+                      `org-format-latex-options' instead.
+  :post-clean         list of strings, files matched are to be cleaned up once
+                      the image is generated.  When nil, the files with \".dvi\",
+                      \".xdv\", \".pdf\", \".tex\", \".aux\", \".log\", \".svg\",
+                      \".png\", \".jpg\", \".jpeg\" or \".out\" extension will
+                      be cleaned up.
+  :latex-header       list of strings, the LaTeX header of the snippet file.
+                      When nil, the fallback value is used instead, which is
+                      controlled by `org-format-latex-header',
+                      `org-latex-default-packages-alist' and
+                      `org-latex-packages-alist', which see.
+  :latex-compiler     list of LaTeX commands, as strings.  Each of them is given
+                      to the shell.  Place-holders \"%t\", \"%b\" and \"%o\" are
+                      replaced with values defined below.
+  :image-converter    list of image converter commands strings.  Each of them is
+                      given to the shell and supports any of the following
+                      place-holders defined below.
+
+Place-holders used by `:image-converter' and `:latex-compiler':
+
+  %i    input file name.
+  %b    base name of input file.
+  %o    base directory of input file.
+
+Place-holders only used by `:image-converter':
+
+  %F    foreground of image
+  %B    background of image
+  %D    dpi, which is used to adjust image size by some processing commands.
+  %S    the image size scale ratio, which is used to adjust image size by some
+        processing commands."
+  :group 'org-latex
+  :version "25.2"
+  :package-version '(Org . "9.0")
+  :type '(alist :tag "LaTeX to image backends"
+		:value-type (plist)))
+
+(define-obsolete-variable-alias
+ 'org-latex-preview-ltxpng-directory
+ 'org-preview-latex-image-directory "25.1")
 
-(defcustom org-latex-preview-ltxpng-directory "ltxpng/"
+(defcustom org-preview-latex-image-directory "ltximg/"
   "Path to store latex preview images.
 A relative path here creates many directories relative to the
 processed org files paths.  An absolute path puts all preview
 images at the same place."
   :group 'org-latex
-  :version "24.3"
+  :version "25.1"
+  :package-version '(Org . "9.0")
   :type 'string)
 
 (defun org-format-latex-mathml-available-p ()
@@ -19013,9 +19108,12 @@ looks only before point, not after."
     (org-in-regexp
      "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")))
 
-(defun org--format-latex-make-overlay (beg end image)
-  "Build an overlay between BEG and END using IMAGE file."
-  (let ((ov (make-overlay beg end)))
+(defun org--format-latex-make-overlay (beg end image &optional imagetype)
+  "Build an overlay between BEG and END using IMAGE file.
+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
@@ -19025,10 +19123,10 @@ looks only before point, not after."
     (if (featurep 'xemacs)
 	(progn
 	  (overlay-put ov 'invisible t)
-	  (overlay-put ov 'end-glyph (make-glyph (vector 'png :file image))))
+	  (overlay-put ov 'end-glyph (make-glyph (vector imagetype :file image))))
       (overlay-put ov
 		   'display
-		   (list 'image :type 'png :file image :ascent 'center)))))
+		   (list 'image :type imagetype :file image :ascent 'center)))))
 
 (defun org--list-latex-overlays (&optional beg end)
   "List all Org LaTeX overlays in current buffer.
@@ -19109,14 +19207,13 @@ for all fragments in the buffer."
 		   (narrow-to-region beg end))))))
 	    (let ((file (buffer-file-name (buffer-base-buffer))))
 	      (org-format-latex
-	       (concat org-latex-preview-ltxpng-directory "org-ltxpng")
+	       (concat org-preview-latex-image-directory "org-ltximg")
 	       ;; Emacs cannot overlay images from remote hosts.
 	       ;; Create it in `temporary-file-directory' instead.
 	       (if (or (not file) (file-remote-p file))
 		   temporary-file-directory
 		 default-directory)
-	       'overlays msg 'forbuffer
-	       org-latex-create-formula-image-program)))
+	       'overlays msg 'forbuffer org-preview-latex-default-process)))
 	  ;; Work around a bug that doesn't restore window's start
 	  ;; when widening back the buffer.
 	  (set-window-start nil window-start)
@@ -19156,8 +19253,8 @@ Some of the options can be changed using the variable
 			   (goto-char (org-element-property :end context))
 			   (skip-chars-backward " \r\t\n")
 			   (point))))
-		(cl-case processing-type
-		  (mathjax
+		(cond
+		  ((eq processing-type 'mathjax)
 		   ;; Prepare for MathJax processing.
 		   (if (not (string-match "\\`\\$\\$?" value))
 		       (goto-char end)
@@ -19165,11 +19262,13 @@ Some of the options can be changed using the variable
 		     (if (string= (match-string 0 value) "$$")
 			 (insert "\\[" (substring value 2 -2) "\\]")
 		       (insert "\\(" (substring value 1 -1) "\\)"))))
-		  ((dvipng imagemagick)
+		  ((assq processing-type org-preview-latex-process-alist)
 		   ;; Process to an image.
 		   (cl-incf cnt)
 		   (goto-char beg)
-		   (let* ((face (face-at-point))
+		   (let* ((processing-info
+			   (cdr (assq processing-type org-preview-latex-process-alist)))
+			  (face (face-at-point))
 			  ;; Get the colors from the face at point.
 			  (fg
 			   (let ((color (plist-get org-format-latex-options
@@ -19189,9 +19288,10 @@ Some of the options can be changed using the variable
 					     org-latex-packages-alist
 					     org-format-latex-options
 					     forbuffer value fg bg))))
+			  (imagetype (or (plist-get processing-info :image-output-type) "png"))
 			  (absprefix (expand-file-name prefix dir))
-			  (linkfile (format "%s_%s.png" prefix hash))
-			  (movefile (format "%s_%s.png" absprefix hash))
+			  (linkfile (format "%s_%s.%s" prefix hash imagetype))
+			  (movefile (format "%s_%s.%s" absprefix hash imagetype))
 			  (sep (and block-type "\n\n"))
 			  (link (concat sep "[[file:" linkfile "]]" sep))
 			  (options
@@ -19213,7 +19313,7 @@ Some of the options can be changed using the variable
 			     (when (eq (overlay-get o 'org-overlay-type)
 				       'org-latex-overlay)
 			       (delete-overlay o)))
-			   (org--format-latex-make-overlay beg end movefile)
+			   (org--format-latex-make-overlay beg end movefile imagetype)
 			   (goto-char end))
 		       (delete-region beg end)
 		       (insert
@@ -19222,7 +19322,7 @@ Some of the options can be changed using the variable
 				  (replace-regexp-in-string "\"" "" value)
 				  'org-latex-src-embed-type
 				  (if block-type 'paragraph 'character)))))))
-		  (mathml
+		  ((eq processing-type 'mathml)
 		   ;; Process to MathML.
 		   (unless (org-format-latex-mathml-available-p)
 		     (user-error "LaTeX to MathML converter not configured"))
@@ -19232,8 +19332,8 @@ Some of the options can be changed using the variable
 		   (delete-region beg end)
 		   (insert (org-format-latex-as-mathml
 			    value block-type prefix dir)))
-		  (otherwise
-		   (error "Unknown conversion type %s for LaTeX fragments"
+		  (t
+		   (error "Unknown conversion process %s for LaTeX fragments"
 			  processing-type)))))))))))
 
 (defun org-create-math-formula (latex-frag &optional mathml-file)
@@ -19330,31 +19430,6 @@ inspection."
       ;; Failed conversion.  Return the LaTeX fragment verbatim
       latex-frag)))
 
-(defun org-create-formula-image (string tofile options buffer &optional type)
-  "Create an image from LaTeX source using dvipng or convert.
-This function calls either `org-create-formula-image-with-dvipng'
-or `org-create-formula-image-with-imagemagick' depending on the
-value of `org-latex-create-formula-image-program' or on the value
-of the optional TYPE variable.
-
-Note: ultimately these two function should be combined as they
-share a good deal of logic."
-  (org-check-external-command
-   "latex" "needed to convert LaTeX fragments to images")
-  (funcall
-   (cl-case (or type org-latex-create-formula-image-program)
-     (dvipng
-      (org-check-external-command
-       "dvipng" "needed to convert LaTeX fragments to images")
-      #'org-create-formula-image-with-dvipng)
-     (imagemagick
-      (org-check-external-command
-       "convert" "you need to install imagemagick")
-      #'org-create-formula-image-with-imagemagick)
-     (t (error
-         "Invalid value of `org-latex-create-formula-image-program'")))
-   string tofile options buffer))
-
 (declare-function org-export-get-backend "ox" (name))
 (declare-function org-export--get-global-options "ox" (&optional backend))
 (declare-function org-export--get-inbuffer-options "ox" (&optional backend))
@@ -19385,133 +19460,105 @@ horizontal and vertical directions."
 		(/ (display-mm-height) 25.4)))
     (error "Attempt to calculate the dpi of a non-graphic display")))
 
-;; This function borrows from Ganesh Swami's latex2png.el
-(defun org-create-formula-image-with-dvipng (string tofile options buffer)
-  "This calls dvipng."
-  (require 'ox-latex)
-  (let* ((tmpdir (if (featurep 'xemacs)
-		     (temp-directory)
-		   temporary-file-directory))
+(defun org-create-formula-image
+    (string tofile options buffer &optional processing-type)
+  "Create an image from LaTeX source using external processes.
+
+The LaTeX STRING is saved to a temporary LaTeX file, then
+converted to an image file by process PROCESSING-TYPE defined in
+`org-preview-latex-process-alist'.  A nil value defaults to
+`org-preview-latex-default-process'.
+
+The generated image file is eventually moved to TOFILE.
+
+The OPTIONS argument controls the size, foreground color and
+background color of the generated image.
+
+When BUFFER non-nil, this function is used for LaTeX previewing.
+Otherwise, it is used to deal with LaTeX snippets showed in
+a HTML file."
+  (let* ((processing-type (or processing-type
+			      org-preview-latex-default-process))
+	 (processing-info
+	  (cdr (assq processing-type org-preview-latex-process-alist)))
+	 (programs (plist-get processing-info :programs))
+	 (error-message (or (plist-get processing-info :message) ""))
+	 (use-xcolor (plist-get processing-info :use-xcolor))
+	 (image-input-type (plist-get processing-info :image-input-type))
+	 (image-output-type (plist-get processing-info :image-output-type))
+	 (post-clean (or (plist-get processing-info :post-clean)
+			 '(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log"
+			   ".svg" ".png" ".jpg" ".jpeg" ".out")))
+	 (latex-header (or (plist-get processing-info :latex-header)
+			   (org-create-formula--latex-header)))
+	 (latex-compiler (plist-get processing-info :latex-compiler))
+	 (image-converter (plist-get processing-info :image-converter))
+	 (tmpdir temporary-file-directory)
 	 (texfilebase (make-temp-name
 		       (expand-file-name "orgtex" tmpdir)))
 	 (texfile (concat texfilebase ".tex"))
-	 (dvifile (concat texfilebase ".dvi"))
-	 (pngfile (concat texfilebase ".png"))
-	 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
-	 ;; This assumes that the display has the same pixel width in
-	 ;; the horizontal and vertical directions
-	 (dpi (number-to-string (* scale (if buffer (org--get-display-dpi) 120))))
+	 (font-height (face-attribute 'default :height nil))
+	 (image-size-adjust (or (plist-get processing-info :image-size-adjust)
+				'(1.0 . 1.0)))
+	 (scale (* (if buffer (car image-size-adjust) (cdr image-size-adjust))
+		   (or (plist-get options (if buffer :scale :html-scale)) 1.0)))
+	 (dpi (* scale (floor (if buffer font-height 140.0))))
 	 (fg (or (plist-get options (if buffer :foreground :html-foreground))
 		 "Black"))
 	 (bg (or (plist-get options (if buffer :background :html-background))
-		 "Transparent")))
-    (if (eq fg 'default) (setq fg (org-dvipng-color :foreground))
-      (unless (string= fg "Transparent") (setq fg (org-dvipng-color-format fg))))
-    (if (eq bg 'default) (setq bg (org-dvipng-color :background))
-      (unless (string= bg "Transparent") (setq bg (org-dvipng-color-format bg))))
-    (let ((latex-header (org-create-formula--latex-header)))
+		 "Transparent"))
+	 (log-buf (get-buffer-create "*Org Preview LaTeX Output*"))
+	 (resize-mini-windows nil)) ;Fix Emacs flicker when creating image.
+    (dolist (program programs)
+      (org-check-external-command program error-message))
+    (if use-xcolor
+	(progn (if (eq fg 'default)
+		   (setq fg (org-latex-color :foreground))
+		 (setq fg (org-latex-color-format fg)))
+	       (if (eq bg 'default)
+		   (setq bg (org-latex-color :background))
+		 (setq bg (org-latex-color-format
+			   (if (string= bg "Transparent") "white" bg))))
+	       (with-temp-file texfile
+		 (insert latex-header)
+		 (insert "\n\\begin{document}\n"
+			 "\\definecolor{fg}{rgb}{" fg "}\n"
+			 "\\definecolor{bg}{rgb}{" bg "}\n"
+			 "\n\\pagecolor{bg}\n"
+			 "\n{\\color{fg}\n"
+			 string
+			 "\n}\n"
+			 "\n\\end{document}\n")))
+      (if (eq fg 'default)
+	  (setq fg (org-dvipng-color :foreground))
+	(unless (string= fg "Transparent")
+	  (setq fg (org-dvipng-color-format fg))))
+      (if (eq bg 'default)
+	  (setq bg (org-dvipng-color :background))
+	(unless (string= bg "Transparent")
+	  (setq bg (org-dvipng-color-format bg))))
       (with-temp-file texfile
 	(insert latex-header)
 	(insert "\n\\begin{document}\n" string "\n\\end{document}\n")))
-    (let ((dir default-directory))
-      (ignore-errors
-	(cd tmpdir)
-	(call-process "latex" nil nil nil texfile))
-      (cd dir))
-    (if (not (file-exists-p dvifile))
-	(progn (message "Failed to create dvi file from %s" texfile) nil)
-      (ignore-errors
-	(if (featurep 'xemacs)
-	    (call-process "dvipng" nil nil nil
-			  "-fg" fg "-bg" bg
-			  "-T" "tight"
-			  "-o" pngfile
-			  dvifile)
-	  (call-process "dvipng" nil nil nil
-			"-fg" fg "-bg" bg
-			"-D" dpi
-			;;"-x" scale "-y" scale
-			"-T" "tight"
-			"-o" pngfile
-			dvifile)))
-      (if (not (file-exists-p pngfile))
-	  (if org-format-latex-signal-error
-	      (error "Failed to create png file from %s" texfile)
-	    (message "Failed to create png file from %s" texfile)
-	    nil)
-	;; Use the requested file name and clean up
-	(copy-file pngfile tofile 'replace)
-	(dolist (e '(".dvi" ".tex" ".aux" ".log" ".png" ".out"))
-	  (when (file-exists-p (concat texfilebase e))
-	    (delete-file (concat texfilebase e))))
-	pngfile))))
-
-(declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
-(defun org-create-formula-image-with-imagemagick (string tofile options buffer)
-  "This calls convert, which is included into imagemagick."
-  (require 'ox-latex)
-  (let* ((tmpdir (if (featurep 'xemacs)
-		     (temp-directory)
-		   temporary-file-directory))
-	 (texfilebase (make-temp-name
-		       (expand-file-name "orgtex" tmpdir)))
-	 (texfile (concat texfilebase ".tex"))
-	 (pdffile (concat texfilebase ".pdf"))
-	 (pngfile (concat texfilebase ".png"))
-	 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
-	 (dpi (number-to-string (* scale (if buffer (org--get-display-dpi) 120))))
-	 (fg (or (plist-get options (if buffer :foreground :html-foreground))
-		 "black"))
-	 (bg (or (plist-get options (if buffer :background :html-background))
-		 "white")))
-    (if (eq fg 'default) (setq fg (org-latex-color :foreground))
-      (setq fg (org-latex-color-format fg)))
-    (if (eq bg 'default) (setq bg (org-latex-color :background))
-      (setq bg (org-latex-color-format
-		(if (string= bg "Transparent") "white" bg))))
-    (let ((latex-header (org-create-formula--latex-header)))
-      (with-temp-file texfile
-	(insert latex-header)
-	(insert "\n\\begin{document}\n"
-		"\\definecolor{fg}{rgb}{" fg "}\n"
-		"\\definecolor{bg}{rgb}{" bg "}\n"
-		"\n\\pagecolor{bg}\n"
-		"\n{\\color{fg}\n"
-		string
-		"\n}\n"
-		"\n\\end{document}\n")))
-    (org-latex-compile texfile t)
-    (if (not (file-exists-p pdffile))
-	(progn (message "Failed to create pdf file from %s" texfile) nil)
-      (ignore-errors
-	(if (featurep 'xemacs)
-	    (call-process "convert" nil nil nil
-			  "-density" "96"
-			  "-trim"
-			  "-antialias"
-			  pdffile
-			  "-quality" "100"
-			  ;; "-sharpen" "0x1.0"
-			  pngfile)
-	  (call-process "convert" nil nil nil
-			"-density" dpi
-			"-trim"
-			"-antialias"
-			pdffile
-			"-quality" "100"
-			;; "-sharpen" "0x1.0"
-			pngfile)))
-      (if (not (file-exists-p pngfile))
-	  (if org-format-latex-signal-error
-	      (error "Failed to create png file from %s" texfile)
-	    (message "Failed to create png file from %s" texfile)
-	    nil)
-	;; Use the requested file name and clean up
-	(copy-file pngfile tofile 'replace)
-	(dolist (e '(".pdf" ".tex" ".aux" ".log" ".png"))
-	  (when (file-exists-p (concat texfilebase e))
-	    (delete-file (concat texfilebase e))))
-	pngfile))))
+
+    (let* ((err-msg (format "Please adjust '%s' part of \
+`org-preview-latex-process-alist'."
+			    processing-type))
+	   (image-input-file
+	    (org-compile-file
+	     texfile latex-compiler image-input-type err-msg log-buf))
+	   (image-output-file
+	    (org-compile-file
+	     image-input-file image-converter image-output-type err-msg log-buf
+	     `((?F . ,(shell-quote-argument fg))
+	       (?B . ,(shell-quote-argument bg))
+	       (?D . ,(shell-quote-argument (format "%s" dpi)))
+	       (?S . ,(shell-quote-argument (format "%s" (/ dpi 140.0))))))))
+      (copy-file image-output-file tofile 'replace)
+      (dolist (e post-clean)
+	(when (file-exists-p (concat texfilebase e))
+	  (delete-file (concat texfilebase e))))
+      image-output-file)))
 
 (defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra)
   "Fill a LaTeX header template TPL.

+ 36 - 39
lisp/ox-html.el

@@ -816,24 +816,20 @@ fragments.
 This option can also be set with the +OPTIONS line,
 e.g. \"tex:mathjax\".  Allowed values are:
 
-nil            Ignore math snippets.
-`verbatim'     Keep everything in verbatim
-`dvipng'       Process the LaTeX fragments to images.  This will also
-               include processing of non-math environments.
-`imagemagick'  Convert the LaTeX fragments to pdf files and use
-               imagemagick to convert pdf files to png files.
-`mathjax'      Do MathJax preprocessing and arrange for MathJax.js to
-               be loaded.
-t              Synonym for `mathjax'."
+  nil           Ignore math snippets.
+  `verbatim'    Keep everything in verbatim
+  `mathjax', t  Do MathJax preprocessing and arrange for MathJax.js to
+                be loaded.
+  SYMBOL        Any symbol defined in `org-preview-latex-process-alist',
+                e.g., `dvipng'."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
   :type '(choice
 	  (const :tag "Do not process math in any way" nil)
-	  (const :tag "Use dvipng to make images" dvipng)
-	  (const :tag "Use imagemagick to make images" imagemagick)
+	  (const :tag "Leave math verbatim" verbatim)
 	  (const :tag "Use MathJax to display math" mathjax)
-	  (const :tag "Leave math verbatim" verbatim)))
+	  (symbol :tag "Convert to image to display math" :value dvipng)))
 
 ;;;; Links :: Generic
 
@@ -2759,10 +2755,11 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 
 (defun org-html-format-latex (latex-frag processing-type info)
   "Format a LaTeX fragment LATEX-FRAG into HTML.
-PROCESSING-TYPE designates the tool used for conversion.  It is
-a symbol among `mathjax', `dvipng', `imagemagick', `verbatim' nil
-and t.  See `org-html-with-latex' for more information.  INFO is
-a plist containing export properties."
+PROCESSING-TYPE designates the tool used for conversion.  It can
+be `mathjax', `verbatim', nil, t or symbols in
+`org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or
+`imagemagick'.  See `org-html-with-latex' for more information.
+INFO is a plist containing export properties."
   (let ((cache-relpath "") (cache-dir ""))
     (unless (eq processing-type 'mathjax)
       (let ((bfn (or (buffer-file-name)
@@ -2777,7 +2774,7 @@ a plist containing export properties."
 			     "\n")
 			    "\n")))))
 	(setq cache-relpath
-	      (concat "ltxpng/"
+	      (concat (file-name-as-directory org-preview-latex-image-directory)
 		      (file-name-sans-extension
 		       (file-name-nondirectory bfn)))
 	      cache-dir (file-name-directory bfn))
@@ -2798,19 +2795,19 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 	(latex-frag (org-remove-indentation
 		     (org-element-property :value latex-environment)))
 	(attributes (org-export-read-attribute :attr_html latex-environment)))
-    (case processing-type
-      ((t mathjax)
-       (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
-       (let ((formula-link
-	      (org-html-format-latex latex-frag processing-type info)))
-	 (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
-	   ;; Do not provide a caption or a name to be consistent with
-	   ;; `mathjax' handling.
-	   (org-html--wrap-image
-	    (org-html--format-image
-	     (match-string 1 formula-link) attributes info) info))))
-      (t latex-frag))))
+    (cond
+     ((memq processing-type '(t mathjax))
+      (org-html-format-latex latex-frag 'mathjax info))
+     ((assq processing-type org-preview-latex-process-alist)
+      (let ((formula-link
+	     (org-html-format-latex latex-frag processing-type info)))
+	(when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+	  ;; Do not provide a caption or a name to be consistent with
+	  ;; `mathjax' handling.
+	  (org-html--wrap-image
+	   (org-html--format-image
+	    (match-string 1 formula-link) attributes info) info))))
+     (t latex-frag))))
 
 ;;;; Latex Fragment
 
@@ -2819,15 +2816,15 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((latex-frag (org-element-property :value latex-fragment))
 	(processing-type (plist-get info :with-latex)))
-    (case processing-type
-      ((t mathjax)
-       (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
-       (let ((formula-link
-	      (org-html-format-latex latex-frag processing-type info)))
-	 (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
-	   (org-html--format-image (match-string 1 formula-link) nil info))))
-      (t latex-frag))))
+    (cond
+     ((memq processing-type '(t mathjax))
+      (org-html-format-latex latex-frag 'mathjax info))
+     ((assq processing-type org-preview-latex-process-alist)
+      (let ((formula-link
+	     (org-html-format-latex latex-frag processing-type info)))
+	(when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
+	  (org-html--format-image (match-string 1 formula-link) nil info))))
+     (t latex-frag))))
 
 ;;;; Line Break