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 9 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
 @item
 Environments of any kind@footnote{When MathJax is used, only the
 Environments of any kind@footnote{When MathJax is used, only the
 environments recognized by MathJax will be processed.  When
 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
 @item
 Text within the usual @LaTeX{} math delimiters.  To avoid conflicts with
 Text within the usual @LaTeX{} math delimiters.  To avoid conflicts with
 currency specifications, single @samp{$} characters are only recognized as
 currency specifications, single @samp{$} characters are only recognized as
@@ -10445,12 +10445,12 @@ lines:
 @subsection Previewing @LaTeX{} fragments
 @subsection Previewing @LaTeX{} fragments
 @cindex @LaTeX{} fragments, preview
 @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
 fragments can be processed to produce images of the typeset expressions to be
 used for inclusion while exporting to HTML (see @pxref{@LaTeX{} fragments}),
 used for inclusion while exporting to HTML (see @pxref{@LaTeX{} fragments}),
 or for inline previewing within Org mode.
 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
 @subsection Math formatting in HTML export
 @cindex MathJax
 @cindex MathJax
 @cindex dvipng
 @cindex dvipng
+@cindex dvisvgm
 @cindex imagemagick
 @cindex imagemagick
 
 
 @LaTeX{} math snippets (@pxref{@LaTeX{} fragments}) can be displayed in two
 @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
 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
 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
 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
 @example
 #+OPTIONS: tex:dvipng
 #+OPTIONS: tex:dvipng
 @end example
 @end example
 
 
+@example
+#+OPTIONS: tex:dvisvgm
+@end example
+
 or:
 or:
 
 
 @example
 @example
@@ -12910,6 +12916,7 @@ and open the formula file with the system-registered application.
 @end table
 @end table
 
 
 @cindex dvipng
 @cindex dvipng
+@cindex dvisvgm
 @cindex imagemagick
 @cindex imagemagick
 @item PNG images
 @item PNG images
 
 
@@ -12919,16 +12926,20 @@ This option is activated on a per-file basis with
 #+OPTIONS: tex:dvipng
 #+OPTIONS: tex:dvipng
 @end example
 @end example
 
 
+@example
+#+OPTIONS: tex:dvisvgm
+@end example
+
 or:
 or:
 
 
 @example
 @example
 #+OPTIONS: tex:imagemagick
 #+OPTIONS: tex:imagemagick
 @end example
 @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
 @end enumerate
 
 
 @node Working with MathML or OpenDocument formula files
 @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)
 	  (const :tag "None" nil)
 	  (string :tag "\nShell command")))
 	  (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
   :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.
   "Path to store latex preview images.
 A relative path here creates many directories relative to the
 A relative path here creates many directories relative to the
 processed org files paths.  An absolute path puts all preview
 processed org files paths.  An absolute path puts all preview
 images at the same place."
 images at the same place."
   :group 'org-latex
   :group 'org-latex
-  :version "24.3"
+  :version "25.1"
+  :package-version '(Org . "9.0")
   :type 'string)
   :type 'string)
 
 
 (defun org-format-latex-mathml-available-p ()
 (defun org-format-latex-mathml-available-p ()
@@ -19013,9 +19108,12 @@ looks only before point, not after."
     (org-in-regexp
     (org-in-regexp
      "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")))
      "\\\\[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 'org-overlay-type 'org-latex-overlay)
     (overlay-put ov 'evaporate t)
     (overlay-put ov 'evaporate t)
     (overlay-put ov
     (overlay-put ov
@@ -19025,10 +19123,10 @@ looks only before point, not after."
     (if (featurep 'xemacs)
     (if (featurep 'xemacs)
 	(progn
 	(progn
 	  (overlay-put ov 'invisible t)
 	  (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
       (overlay-put ov
 		   'display
 		   '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)
 (defun org--list-latex-overlays (&optional beg end)
   "List all Org LaTeX overlays in current buffer.
   "List all Org LaTeX overlays in current buffer.
@@ -19109,14 +19207,13 @@ for all fragments in the buffer."
 		   (narrow-to-region beg end))))))
 		   (narrow-to-region beg end))))))
 	    (let ((file (buffer-file-name (buffer-base-buffer))))
 	    (let ((file (buffer-file-name (buffer-base-buffer))))
 	      (org-format-latex
 	      (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.
 	       ;; Emacs cannot overlay images from remote hosts.
 	       ;; Create it in `temporary-file-directory' instead.
 	       ;; Create it in `temporary-file-directory' instead.
 	       (if (or (not file) (file-remote-p file))
 	       (if (or (not file) (file-remote-p file))
 		   temporary-file-directory
 		   temporary-file-directory
 		 default-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
 	  ;; Work around a bug that doesn't restore window's start
 	  ;; when widening back the buffer.
 	  ;; when widening back the buffer.
 	  (set-window-start nil window-start)
 	  (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))
 			   (goto-char (org-element-property :end context))
 			   (skip-chars-backward " \r\t\n")
 			   (skip-chars-backward " \r\t\n")
 			   (point))))
 			   (point))))
-		(cl-case processing-type
-		  (mathjax
+		(cond
+		  ((eq processing-type 'mathjax)
 		   ;; Prepare for MathJax processing.
 		   ;; Prepare for MathJax processing.
 		   (if (not (string-match "\\`\\$\\$?" value))
 		   (if (not (string-match "\\`\\$\\$?" value))
 		       (goto-char end)
 		       (goto-char end)
@@ -19165,11 +19262,13 @@ Some of the options can be changed using the variable
 		     (if (string= (match-string 0 value) "$$")
 		     (if (string= (match-string 0 value) "$$")
 			 (insert "\\[" (substring value 2 -2) "\\]")
 			 (insert "\\[" (substring value 2 -2) "\\]")
 		       (insert "\\(" (substring value 1 -1) "\\)"))))
 		       (insert "\\(" (substring value 1 -1) "\\)"))))
-		  ((dvipng imagemagick)
+		  ((assq processing-type org-preview-latex-process-alist)
 		   ;; Process to an image.
 		   ;; Process to an image.
 		   (cl-incf cnt)
 		   (cl-incf cnt)
 		   (goto-char beg)
 		   (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.
 			  ;; Get the colors from the face at point.
 			  (fg
 			  (fg
 			   (let ((color (plist-get org-format-latex-options
 			   (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-latex-packages-alist
 					     org-format-latex-options
 					     org-format-latex-options
 					     forbuffer value fg bg))))
 					     forbuffer value fg bg))))
+			  (imagetype (or (plist-get processing-info :image-output-type) "png"))
 			  (absprefix (expand-file-name prefix dir))
 			  (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"))
 			  (sep (and block-type "\n\n"))
 			  (link (concat sep "[[file:" linkfile "]]" sep))
 			  (link (concat sep "[[file:" linkfile "]]" sep))
 			  (options
 			  (options
@@ -19213,7 +19313,7 @@ Some of the options can be changed using the variable
 			     (when (eq (overlay-get o 'org-overlay-type)
 			     (when (eq (overlay-get o 'org-overlay-type)
 				       'org-latex-overlay)
 				       'org-latex-overlay)
 			       (delete-overlay o)))
 			       (delete-overlay o)))
-			   (org--format-latex-make-overlay beg end movefile)
+			   (org--format-latex-make-overlay beg end movefile imagetype)
 			   (goto-char end))
 			   (goto-char end))
 		       (delete-region beg end)
 		       (delete-region beg end)
 		       (insert
 		       (insert
@@ -19222,7 +19322,7 @@ Some of the options can be changed using the variable
 				  (replace-regexp-in-string "\"" "" value)
 				  (replace-regexp-in-string "\"" "" value)
 				  'org-latex-src-embed-type
 				  'org-latex-src-embed-type
 				  (if block-type 'paragraph 'character)))))))
 				  (if block-type 'paragraph 'character)))))))
-		  (mathml
+		  ((eq processing-type 'mathml)
 		   ;; Process to MathML.
 		   ;; Process to MathML.
 		   (unless (org-format-latex-mathml-available-p)
 		   (unless (org-format-latex-mathml-available-p)
 		     (user-error "LaTeX to MathML converter not configured"))
 		     (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)
 		   (delete-region beg end)
 		   (insert (org-format-latex-as-mathml
 		   (insert (org-format-latex-as-mathml
 			    value block-type prefix dir)))
 			    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)))))))))))
 			  processing-type)))))))))))
 
 
 (defun org-create-math-formula (latex-frag &optional mathml-file)
 (defun org-create-math-formula (latex-frag &optional mathml-file)
@@ -19330,31 +19430,6 @@ inspection."
       ;; Failed conversion.  Return the LaTeX fragment verbatim
       ;; Failed conversion.  Return the LaTeX fragment verbatim
       latex-frag)))
       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-backend "ox" (name))
 (declare-function org-export--get-global-options "ox" (&optional backend))
 (declare-function org-export--get-global-options "ox" (&optional backend))
 (declare-function org-export--get-inbuffer-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)))
 		(/ (display-mm-height) 25.4)))
     (error "Attempt to calculate the dpi of a non-graphic display")))
     (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
 	 (texfilebase (make-temp-name
 		       (expand-file-name "orgtex" tmpdir)))
 		       (expand-file-name "orgtex" tmpdir)))
 	 (texfile (concat texfilebase ".tex"))
 	 (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))
 	 (fg (or (plist-get options (if buffer :foreground :html-foreground))
 		 "Black"))
 		 "Black"))
 	 (bg (or (plist-get options (if buffer :background :html-background))
 	 (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
       (with-temp-file texfile
 	(insert latex-header)
 	(insert latex-header)
 	(insert "\n\\begin{document}\n" string "\n\\end{document}\n")))
 	(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)
 (defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra)
   "Fill a LaTeX header template TPL.
   "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,
 This option can also be set with the +OPTIONS line,
 e.g. \"tex:mathjax\".  Allowed values are:
 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
   :group 'org-export-html
   :version "24.4"
   :version "24.4"
   :package-version '(Org . "8.0")
   :package-version '(Org . "8.0")
   :type '(choice
   :type '(choice
 	  (const :tag "Do not process math in any way" nil)
 	  (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 "Use MathJax to display math" mathjax)
-	  (const :tag "Leave math verbatim" verbatim)))
+	  (symbol :tag "Convert to image to display math" :value dvipng)))
 
 
 ;;;; Links :: Generic
 ;;;; 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)
 (defun org-html-format-latex (latex-frag processing-type info)
   "Format a LaTeX fragment LATEX-FRAG into HTML.
   "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 ""))
   (let ((cache-relpath "") (cache-dir ""))
     (unless (eq processing-type 'mathjax)
     (unless (eq processing-type 'mathjax)
       (let ((bfn (or (buffer-file-name)
       (let ((bfn (or (buffer-file-name)
@@ -2777,7 +2774,7 @@ a plist containing export properties."
 			     "\n")
 			     "\n")
 			    "\n")))))
 			    "\n")))))
 	(setq cache-relpath
 	(setq cache-relpath
-	      (concat "ltxpng/"
+	      (concat (file-name-as-directory org-preview-latex-image-directory)
 		      (file-name-sans-extension
 		      (file-name-sans-extension
 		       (file-name-nondirectory bfn)))
 		       (file-name-nondirectory bfn)))
 	      cache-dir (file-name-directory 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
 	(latex-frag (org-remove-indentation
 		     (org-element-property :value latex-environment)))
 		     (org-element-property :value latex-environment)))
 	(attributes (org-export-read-attribute :attr_html 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
 ;;;; 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."
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (let ((latex-frag (org-element-property :value latex-fragment))
   (let ((latex-frag (org-element-property :value latex-fragment))
 	(processing-type (plist-get info :with-latex)))
 	(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
 ;;;; Line Break