emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] (v6) [PATCH] New feature: Use dvisvgm to preview latex formular


From: Feng Shu
Subject: Re: [O] (v6) [PATCH] New feature: Use dvisvgm to preview latex formular
Date: Mon, 16 May 2016 20:05:21 +0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.92 (gnu/linux)

Nicolas Goaziou <address@hidden> writes:

This is my modified patch (v6), fix the problems you stated. please review
again, thank!

>From 29760e5c5876fb6b772f7a6004b7160bc06efba8 Mon Sep 17 00:00:00 2001
From: Feng Shu <address@hidden>
Date: Sat, 14 May 2016 22:42:53 +0800
Subject: [PATCH] New feature: Use dvisvgm to preview latex formular

* ox-latex.el (org-latex-pdf-process): org-latex-pdf-process can be a
              configure generator (a plist with :generator keyword).
(org-latex-preview-process): new variable, which is used to process
                             latex snippet.
(org-latex-compile): Add a new optional argument: extra-info.

* 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-latex-create-formula-image-program): Add dvisvgm.
(org-latex-preview-ltximg-directory): Rename from 
`org-latex-preview-ltximg-directory'.
(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-latex-to-image-backends): Add new variable, which used to set latex2image 
program.
(org-create-formula-image-with-dvipng): Useless, removed.
(org-create-formula-image-with-imagemagick): Useless, removed.

* org.texi (@LaTeX{} fragments): Add dvisvgm information.
(Previewing @LaTeX{} fragments): Add dvisvgm information.
(Math formatting in HTML export): Add dvisvgm information.
(Working with @LaTeX{} math snippets): Add dvisvgm information.
---
 doc/org.texi     |  39 ++++--
 lisp/org.el      | 380 ++++++++++++++++++++++++++++++++-----------------------
 lisp/ox-html.el  |  28 ++--
 lisp/ox-latex.el | 171 ++++++++++++++++---------
 4 files changed, 374 insertions(+), 244 deletions(-)

diff --git a/doc/org.texi b/doc/org.texi
index 17b01c2..286fabb 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -10393,10 +10393,10 @@ snippets will be identified as @LaTeX{} source code:
 @item
 Environments of any address@hidden MathJax is used, only the
 environments recognized by MathJax will be processed.  When
address@hidden program or @file{imagemagick} suite is used to create images,
-any @LaTeX{} environment will be handled.}.  The only requirement is that the
address@hidden statement appears on a new line, at the beginning of the line
-or after whitespaces only.
address@hidden 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
@@ -10444,10 +10444,10 @@ lines:
 @cindex @LaTeX{} fragments, preview
 
 @vindex org-latex-create-formula-image-program
-If you have a working @LaTeX{} installation and either @file{dvipng} or
address@hidden address@hidden are respectively available at
address@hidden://sourceforge.net/projects/dvipng/} and from the 
@file{imagemagick}
-suite. Choose the converter by setting the variable
+If you have a working @LaTeX{} installation and @file{dvipng}, @file{dvisvgm}
+or @file{convert} address@hidden are respectively available at
address@hidden://sourceforge.net/projects/dvipng/}, 
@url{http://dvisvgm.bplaced.net/}
+and from the @file{imagemagick} suite. Choose the converter by setting the 
variable
 @code{org-latex-create-formula-image-program} accordingly.}, @LaTeX{}
 fragments can be processed to produce images of the typeset expressions to be
 used for inclusion while exporting to HTML (see @address@hidden fragments}),
@@ -11713,6 +11713,7 @@ You could use @code{http} addresses just as well.
 @subsection Math formatting in HTML export
 @cindex MathJax
 @cindex dvipng
address@hidden dvisvgm
 @cindex imagemagick
 
 @LaTeX{} math snippets (@address@hidden fragments}) can be displayed in two
@@ -11737,13 +11738,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
address@hidden suite is available on your system.  You can still get
+this processing with
 
 @example
 #+OPTIONS: tex:dvipng
 @end example
 
address@hidden
+#+OPTIONS: tex:dvisvgm
address@hidden example
+
 or:
 
 @example
@@ -12908,6 +12914,7 @@ and open the formula file with the system-registered 
application.
 @end table
 
 @cindex dvipng
address@hidden dvisvgm
 @cindex imagemagick
 @item PNG images
 
@@ -12917,16 +12924,20 @@ This option is activated on a per-file basis with
 #+OPTIONS: tex:dvipng
 @end example
 
address@hidden
+#+OPTIONS: tex:dvisvgm
address@hidden 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
diff --git a/lisp/org.el b/lisp/org.el
index f45d5d0..459ef2d 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -3985,15 +3985,107 @@ When using LaTeXML set this option to
 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.
+dvisvgm         Process the LaTeX fragments to dvi/xdv file, then convert
+                dvi/xdv files to svg 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"
   :group 'org-latex
   :version "24.1"
   :type '(choice
          (const :tag "dvipng" dvipng)
+         (const :tag "dvisvgm" dvisvgm)
          (const :tag "imagemagick" imagemagick)))
 
-(defcustom org-latex-preview-ltxpng-directory "ltxpng/"
+(defcustom org-latex-to-image-backends
+  '((dvipng
+     :class snippet
+     :name dvipng
+     :programs ("dvipng" "gs")
+     :message "you need to install dvipng and ghostscript."
+     :input dvi
+     :output png
+     :color dvipng
+     :org-latex-compile t
+     :size-adjust (1.0 . 1.0)
+     :need-clean (".dvi" ".tex" ".aux" ".log" ".png" ".out")
+     :commands (("dvipng" "-fg" "%fg%" "-bg" "%bg%" "-D" "%dpi%" "-T" "tight" 
"-o" "%output-file%" "%input-file%")))
+    (dvisvgm
+     :class snippet
+     :name dvisvgm
+     :programs ("dvisvgm" "gs")
+     :message "you needed to install dvisvgm and ghostscript."
+     :input dvi
+     :output svg
+     :color latex
+     :org-latex-compile t
+     :size-adjust (1.7 . 1.5)
+     :post-clean (".dvi" ".xdv" ".tex" ".aux" ".log" ".svg" ".out")
+     :commands (("dvisvgm" "%input-file%" "-n" "-b" "min" "-c" "%scale%" "-o" 
"%output-file%")))
+    (imagemagick
+     :class snippet
+     :name imagemagick
+     :programs ("convert" "gs")
+     :message "you need to install imagemagick and ghostscript."
+     :input pdf
+     :output png
+     :color latex
+     :org-latex-compile t
+     :size-adjust (1.0 . 1.0)
+     :post-clean (".pdf" ".tex" ".aux" ".log" ".png" ".out")
+     :commands (("convert" "-density" "%dpi%" "-trim" "-antialias" 
"%input-file%" "-quality" "100" "%output-file%"))))
+  "List definitions of external processes for LaTeX previewing.
+Org mode can use some external commands to generate TeX snippet's image for
+previewing or inserting into HTML files, e.g. dvipng, dvisvgm or imagemagick
+this variable tells `org-create-formula-image' how to use external commands.
+
+  :class              symbol, this setting may be useful in future.
+  :name               string, the backend's name.
+  :programs           list of strings, required programs.
+  :message            string, message it when required program can't be found.
+  :input              symbol, input file type, for example: dvi.
+  :output             symbol, output file type, for example: png.
+  :color              symbol, if set to `latex', LaTeX \"xcolor\" macro is used
+                      to deal with background and foreground color of image,
+                      if set to `divpng', dvipng style background and 
foregroud color
+                      format will be generated, you should use them in command 
options
+                      with special string: \"%fg\"% and \"%bg%\".
+  :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 backend developers, user
+                      should use variable `org-format-latex-options' instead.
+  :org-latex-compile  boolean, when non-nil, `org-create-formula-image' uses
+                      `org-latex-compile' to compile tex file, otherwise, you 
need
+                      to set latex command in `:commands' option.
+  :need-clean         list of strings, files matched are to be cleaned up once 
the
+                      image is generated.
+  :commands           list, the commands setting, the following special 
strings,
+                      will be replaced to according value before commands 
called.
+
+                      1. %fg%            foreground
+                      2. %bg%            background
+                      3. %dpi%           dpi, which used to adjust image size 
by
+                                         some backend's command.
+                      4. %scale%         the image size scale ratio, which 
used to
+                                         adjust image size by some backend's 
command.
+                      5. %tex-file%      tex file name.
+                      6. %input-file%    input file name of image converter.
+                      7. %output-file%   output file name of image converter.
+                      8. %file-base%     input file name's base name.
+                      9. %temp-dir%      temporary dir used by 
`org-create-formula-image'.
+
+                      For example, \"%temp-dir%/test\" may be replaced to 
\"/tmp/test\"
+                      in linux."
+  :group 'org-latex
+  :version "25.1"
+  :type '(alist :tag "LaTeX to image backends"
+               :value-type (plist)))
+
+(define-obsolete-variable-alias
+ 'org-latex-preview-ltxpng-directory
+ 'org-latex-preview-ltximg-directory "25.1")
+
+(defcustom org-latex-preview-ltximg-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
@@ -18996,9 +19088,10 @@ looks only before point, not after."
     (org-in-regexp
      "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*")))
 
-(defun org--format-latex-make-overlay (beg end image)
+(defun org--format-latex-make-overlay (beg end image &optional imagetype)
   "Build an overlay between BEG and END using IMAGE file."
-  (let ((ov (make-overlay beg end)))
+  (let ((ov (make-overlay beg end))
+       (imagetype (or imagetype 'png)))
     (overlay-put ov 'org-overlay-type 'org-latex-overlay)
     (overlay-put ov 'evaporate t)
     (overlay-put ov
@@ -19008,10 +19101,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.
@@ -19092,7 +19185,7 @@ 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-latex-preview-ltximg-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))
@@ -19123,7 +19216,8 @@ Some of the options can be changed using the variable
           checkdir-flag)
       (goto-char (point-min))
       ;; Optimize overlay creation: (info "(elisp) Managing Overlays").
-      (when (and overlays (memq processing-type '(dvipng imagemagick)))
+      (when (and overlays (memq processing-type
+                               (mapcar #'car org-latex-to-image-backends)))
        (overlay-recenter (point-max)))
       (while (re-search-forward math-regexp nil t)
        (unless (and overlays
@@ -19139,8 +19233,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)
@@ -19148,11 +19242,14 @@ 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)
+                 ((member processing-type
+                          (mapcar #'car org-latex-to-image-backends))
                   ;; Process to an image.
                   (cl-incf cnt)
                   (goto-char beg)
-                  (let* ((face (face-at-point))
+                  (let* ((backend-info
+                          (cdr (assq processing-type 
org-latex-to-image-backends)))
+                         (face (face-at-point))
                          ;; Get the colors from the face at point.
                          (fg
                           (let ((color (plist-get org-format-latex-options
@@ -19172,9 +19269,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 backend-info :output) '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
@@ -19196,7 +19294,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
@@ -19205,7 +19303,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"))
@@ -19215,7 +19313,7 @@ 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
+                 (t
                   (error "Unknown conversion type %s for LaTeX fragments"
                          processing-type)))))))))))
 
@@ -19313,31 +19411,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))
@@ -19368,133 +19441,120 @@ 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))
-        (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))))
-        (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)))
-      (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."
+(defun org-create-formula-image (string tofile options buffer &optional type)
+  "Create an image from LaTeX source using external processes defined
+in `org-latex-to-image-backends'."
   (require 'ox-latex)
-  (let* ((tmpdir (if (featurep 'xemacs)
-                    (temp-directory)
-                  temporary-file-directory))
+  (let* ((type (or type 'dvipng))
+        (backend-info
+         (cdr (assq type org-latex-to-image-backends)))
+        (programs (plist-get backend-info :programs))
+        (error-message (plist-get backend-info :message))
+        (color-style (plist-get backend-info :color))
+        (input-type (plist-get backend-info :input))
+        (output-type (plist-get backend-info :output))
+        (post-clean
+         (delete-dups `(,@(plist-get backend-info :post-clean)
+                        ".dvi" ".xdv" ".tex" ".aux" ".log"
+                        ".svg" ".png" ".jpg" ".jpeg" ".out")))
+        (use-org-latex-compile (plist-get backend-info :org-latex-compile))
+        (commands (plist-get backend-info :commands))
+        (tmpdir 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))))
+        (input-file (format "%s.%s" texfilebase input-type))
+        (output-file (format "%s.%s" texfilebase output-type))
+        (font-height (face-attribute 'default :height nil))
+        (size-adjust (or (plist-get backend-info :size-adjust) '(1.0 . 1.0)))
+        (scale (* (if buffer (car size-adjust) (cdr 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"))
+                "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))
+                "Transparent"))
+        args-alist)
+    (org-check-external-command
+     "latex" "needed to convert LaTeX fragments to images")
+    (dolist (program programs)
+      (org-check-external-command program error-message))
+    (if (eq color-style 'latex)
+       (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))))
+              (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"))))
+      (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)))
+       (with-temp-file texfile
+         (insert latex-header)
+         (insert "\n\\begin{document}\n" string "\n\\end{document}\n"))))
+    (setq args-alist
+         `(("%fg%" . ,fg)
+           ("%bg%" . ,bg)
+           ("%dpi%" . ,(format "%s" dpi))
+           ("%scale%" . ,(format "%s" (/ dpi 140.0)))
+           ("%tex-file%" . ,texfile)
+           ("%input-file%" . ,input-file)
+           ("%output-file%" . ,output-file)
+           ("%file-base%" . ,texfilebase)
+           ("%temp-dir%" . ,tmpdir)))
+    ;; Compile latex snippet file with `org-latex-compile'.
+    (when use-org-latex-compile
+      (org-latex-compile texfile t backend-info)
+      (if (not (file-exists-p input-file))
          (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))))
+             (error "`org-latex-compile' can't compile %s, please adjust 
`org-latex-preview-process'." texfile)
+           (message "`org-latex-compile' can't compile %s, please adjust 
`org-latex-preview-process'." texfile)
+           nil)))
+    (dolist (command commands)
+      (let ((command
+            (mapcar (lambda (c)
+                      (dolist (arg args-alist)
+                        (setq c (replace-regexp-in-string
+                                 (car arg) (cdr arg) c)))
+                      c) command)))
+       (ignore-errors
+         (apply #'call-process
+                `(,(car command) nil nil nil ,@(cdr command))))))
+    (if (not (file-exists-p input-file))
+       (if org-format-latex-signal-error
+           (error "Failed to create %s file from %s" input-file texfile)
+         (message "Failed to create %s file from %s" input-file texfile)
+         nil))
+    (if (not (file-exists-p output-file))
+       (if org-format-latex-signal-error
+           (error "Failed to create %s file from %s" output-file input-file)
+         (message "Failed to create %s file from %s" output-file input-file)
+         nil)
+      ;; Use the requested file name and clean up
+      (copy-file output-file tofile 'replace)
+      (dolist (e post-clean)
+       (when (file-exists-p (concat texfilebase e))
+         (delete-file (concat texfilebase e))))
+      output-file)))
 
 (defun org-splice-latex-header (tpl def-pkg pkg snippets-p &optional extra)
   "Fill a LaTeX header template TPL.
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index b188c38..882acdb 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -818,7 +818,9 @@ 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
+`dvipng'       Process the LaTeX fragments to png images.  This will also
+               include processing of non-math environments.
+`dvisvgm'      Process the LaTeX fragments to svg 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.
@@ -830,7 +832,8 @@ t              Synonym for `mathjax'."
   :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 dvipng to make png images" dvipng)
+         (const :tag "Use dvisvgm to make svg images" dvisvgm)
          (const :tag "Use imagemagick to make images" imagemagick)
          (const :tag "Use MathJax to display math" mathjax)
          (const :tag "Leave math verbatim" verbatim)))
@@ -2760,9 +2763,9 @@ 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."
+a symbol among `mathjax', `dvipng', `dvisvgm', `imagemagick',
+`verbatim' nil and t.  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 +2780,7 @@ a plist containing export properties."
                             "\n")
                            "\n")))))
        (setq cache-relpath
-             (concat "ltxpng/"
+             (concat (file-name-as-directory 
org-latex-preview-ltximg-directory)
                      (file-name-sans-extension
                       (file-name-nondirectory bfn)))
              cache-dir (file-name-directory bfn))
@@ -2798,10 +2801,11 @@ 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)
+    (cond
+      ((member processing-type '(t mathjax))
        (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
+      ((member processing-type
+              (mapcar #'car org-latex-to-image-backends))
        (let ((formula-link
              (org-html-format-latex latex-frag processing-type info)))
         (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
@@ -2819,10 +2823,10 @@ 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)
+    (cond
+      ((member processing-type '(t mathjax))
        (org-html-format-latex latex-frag 'mathjax info))
-      ((dvipng imagemagick)
+      ((member processing-type (mapcar #'car org-latex-to-image-backends))
        (let ((formula-link
              (org-html-format-latex latex-frag processing-type info)))
         (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link))
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 7fa68c5..2dddb5e 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1119,6 +1119,24 @@ A better approach is to use a compiler suit such as 
`latexmk'."
   :version "25.1"
   :package-version '(Org . "9.0"))
 
+(defcustom org-latex-preview-process
+  '("latex -interaction nonstopmode -output-directory %o %f")
+  "Commands to process a LaTeX formula snippet to dvi, xdv or pdf file,
+which will be convert to image for previewing or inserting HTML file.
+
+This variable is similar `org-latex-pdf-process' and the different
+is that `org-latex-preview-process' is used for previewing latex
+while `org-latex-pdf-process' is used to export tex file to pdf file.
+
+More information is showed in `org-latex-pdf-process'."
+  :group 'org-export-pdf
+  :type '(choice
+         (repeat :tag "Shell command sequence"
+                 (string :tag "Shell command"))
+         (const :tag "Use other latex command"
+                ("%latex -interaction nonstopmode -output-directory %o %f"))
+         (function)))
+
 (defcustom org-latex-pdf-process
   '("%latex -interaction nonstopmode -output-directory %o %f"
     "%latex -interaction nonstopmode -output-directory %o %f"
@@ -1143,7 +1161,23 @@ which calls the \"correct\" combinations of auxiliary 
programs.
 Alternatively, this may be a Lisp function that does the
 processing, so you could use this to apply the machinery of
 AUCTeX or the Emacs LaTeX mode.  This function should accept the
-file name as its single argument."
+file name as its single argument.
+
+User can set this variable to a configure generator with
+a property list, for example:
+
+   (setq org-latex-pdf-process
+          '(:generator my-latex-pdf-process-generator))
+
+the value associated with the property name `:generator' is a function
+with three optional arguments: texfile, snippet and extra-info,
+the return of this function is a commands list, which will be
+be used to compile tex file by `org-latex-compile', you can use
+this feature to switch pdf process command dynamically according
+to tex file, snippet status, extra information or environment.
+
+Note: if you want to config latex commands for latex previewing,
+use `org-latex-preview-process' instead of `org-latex-pdf-process'."
   :group 'org-export-pdf
   :type '(choice
          (repeat :tag "Shell command sequence"
@@ -3515,7 +3549,7 @@ Return PDF file's name."
       async subtreep visible-only body-only ext-plist
       (lambda (file) (org-latex-compile file)))))
 
-(defun org-latex-compile (texfile &optional snippet)
+(defun org-latex-compile (texfile &optional snippet extra-info)
   "Compile a TeX file.
 
 TEXFILE is the name of the file being compiled.  Processing is
@@ -3525,6 +3559,11 @@ When optional argument SNIPPET is non-nil, TEXFILE is a 
temporary
 file used to preview a LaTeX snippet.  In this case, do not
 create a log buffer and do not bother removing log files.
 
+When `org-latex-pdf-process' or `org-latex-preview-process' set
+as a configure generator (a property list with key `:generator'),
+information can be translated to the generator function by the
+optional argument EXTRA-INFO.
+
 Return PDF file name or an error if it couldn't be produced."
   (let* ((base-name (file-name-sans-extension (file-name-nondirectory 
texfile)))
         (full-name (file-truename texfile))
@@ -3544,62 +3583,78 @@ Return PDF file name or an error if it couldn't be 
produced."
         (time (current-time))
         warnings)
     (unless snippet (message "Processing LaTeX file %s..." texfile))
-    (save-window-excursion
-      (cond
-       ;; A function is provided: Apply it.
-       ((functionp org-latex-pdf-process)
-       (funcall org-latex-pdf-process (shell-quote-argument texfile)))
-       ;; A list is provided: Replace %b, %f and %o with appropriate
-       ;; values in each command before applying it.  Note that while
-       ;; "%latex" and "%bibtex" is used in `org-latex-pdf-process',
-       ;; they are replaced with "%L" and "%B" to adhere to
-       ;; format-spec.  Output is redirected to "*Org PDF LaTeX
-       ;; Output*" buffer.
-       ((consp org-latex-pdf-process)
-       (let ((outbuf (and (not snippet)
-                          (get-buffer-create "*Org PDF LaTeX Output*")))
-             (spec (list (cons ?B  (shell-quote-argument 
org-latex-bib-compiler))
-                         (cons ?L (shell-quote-argument compiler))
-                         (cons ?b (shell-quote-argument base-name))
-                         (cons ?f (shell-quote-argument full-name))
-                         (cons ?o (shell-quote-argument out-dir)))))
-         (dolist (command org-latex-pdf-process)
-           (let ((c (replace-regexp-in-string
-                     "%\\(latex\\|bibtex\\)\\>"
-                     (lambda (str) (upcase (substring str 0 2)))
-                     command)))
-             (shell-command (format-spec c spec) outbuf)))
-         ;; Collect standard errors from output buffer.
-         (setq warnings (and (not snippet)
-                             (org-latex--collect-warnings outbuf)))))
-       (t (error "No valid command to process to PDF")))
-      (let ((pdffile (concat out-dir base-name ".pdf")))
-       ;; Check for process failure.  Provide collected errors if
-       ;; possible.
-       (if (or (not (file-exists-p pdffile))
-               ;; Only compare times up to whole seconds as some filesystems
-               ;; (e.g. HFS+) do not retain any finer granularity.
-               (time-less-p (cl-subseq (nth 5 (file-attributes pdffile)) 0 2)
-                            (cl-subseq time 0 2)))
-           (error (format "PDF file %s wasn't produced" pdffile))
-         ;; Else remove log files, when specified, and signal end of
-         ;; process to user, along with any error encountered.
-         (unless snippet
-           (when org-latex-remove-logfiles
-             (dolist (file (directory-files
-                            out-dir t
-                            (concat (regexp-quote base-name)
-                                    "\\(?:\\.[0-9]+\\)?"
-                                    "\\."
-                                    (regexp-opt 
org-latex-logfiles-extensions))))
-               (delete-file file)))
-           (message (concat "PDF file produced"
-                            (cond
-                             ((eq warnings 'error) " with errors.")
-                             (warnings (concat " with warnings: " warnings))
-                             (t "."))))))
-       ;; Return output file name.
-       pdffile))))
+    (let* ((latex-process (if snippet
+                             org-latex-preview-process
+                           org-latex-pdf-process))
+          (generator-function (plist-get latex-process :generator))
+          (latex-process
+           (if generator-function
+               (if (functionp generator-function)
+                   (funcall generator-function
+                            (shell-quote-argument texfile) snippet extra-info)
+                 (error "Invalid generator function in `%s'."
+                        (if snippet
+                            'org-latex-preview-process
+                          'org-latex-pdf-process)))
+             latex-process)))
+      (save-window-excursion
+       (cond
+        ;; A function is provided: Apply it.
+        ((functionp latex-process)
+         (funcall latex-process (shell-quote-argument texfile)))
+        ;; A list is provided: Replace %b, %f and %o with appropriate
+        ;; values in each command before applying it.  Note that while
+        ;; "%latex" and "%bibtex" is used in `org-latex-pdf-process',
+        ;; they are replaced with "%L" and "%B" to adhere to
+        ;; format-spec.  Output is redirected to "*Org PDF LaTeX
+        ;; Output*" buffer.
+        ((consp latex-process)
+         (let ((outbuf (and (not snippet)
+                            (get-buffer-create "*Org PDF LaTeX Output*")))
+               (spec (list (cons ?B  (shell-quote-argument 
org-latex-bib-compiler))
+                           (cons ?L (shell-quote-argument compiler))
+                           (cons ?b (shell-quote-argument base-name))
+                           (cons ?f (shell-quote-argument full-name))
+                           (cons ?o (shell-quote-argument out-dir)))))
+           (dolist (command latex-process)
+             (let ((c (replace-regexp-in-string
+                       "%\\(latex\\|bibtex\\)\\>"
+                       (lambda (str) (upcase (substring str 0 2)))
+                       command)))
+               (shell-command (format-spec c spec) outbuf)))
+           ;; Collect standard errors from output buffer.
+           (setq warnings (and (not snippet)
+                               (org-latex--collect-warnings outbuf)))))
+        (t (error "No valid command to process to PDF")))
+       (let ((pdffile (concat out-dir base-name ".pdf")))
+         ;; Check for process failure.  Provide collected errors if
+         ;; possible.
+         (if (or (not (file-exists-p pdffile))
+                 ;; Only compare times up to whole seconds as some filesystems
+                 ;; (e.g. HFS+) do not retain any finer granularity.
+                 (time-less-p (cl-subseq (nth 5 (file-attributes pdffile)) 0 2)
+                              (cl-subseq time 0 2)))
+             ;; When compile a tex snippet, we may only need dvi file
+             (unless snippet
+               (error (format "PDF file %s wasn't produced" pdffile)))
+           ;; Else remove log files, when specified, and signal end of
+           ;; process to user, along with any error encountered.
+           (unless snippet
+             (when org-latex-remove-logfiles
+               (dolist (file (directory-files
+                              out-dir t
+                              (concat (regexp-quote base-name)
+                                      "\\(?:\\.[0-9]+\\)?"
+                                      "\\."
+                                      (regexp-opt 
org-latex-logfiles-extensions))))
+                 (delete-file file)))
+             (message (concat "PDF file produced"
+                              (cond
+                               ((eq warnings 'error) " with errors.")
+                               (warnings (concat " with warnings: " warnings))
+                               (t "."))))))
+         ;; Return output file name.
+         (unless snippet pdffile))))))
 
 (defun org-latex--collect-warnings (buffer)
   "Collect some warnings from \"pdflatex\" command output.
-- 
2.1.4


reply via email to

[Prev in Thread] Current Thread [Next in Thread]