* [PATCH] New feature: Use dvisvgm to preview latex formular @ 2016-05-14 6:30 Feng Shu 2016-05-14 8:47 ` numbchild 2016-05-14 14:56 ` Feng Shu 0 siblings, 2 replies; 25+ messages in thread From: Feng Shu @ 2016-05-14 6:30 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 27914 bytes --] From 4e40deddfb342135b78df83fc5a05ddbce965300 Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Fri, 13 May 2016 20:12:22 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's 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): Add dvisvgm case. (org-create-formula-image-with-dvisvgm): New function, deal with latex formula with dvisvgm command. * 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 | 110 ++++++++++++++++++++++++++++------- lisp/ox-html.el | 23 ++++---- lisp/ox-latex.el | 171 +++++++++++++++++++++++++++++++++++-------------------- 4 files changed, 237 insertions(+), 106 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..87f8d3a 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3983,17 +3983,24 @@ When using LaTeXML set this option to "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. + 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" + 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/" +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(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 +19003,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 image-type) "Build an overlay between BEG and END using IMAGE file." - (let ((ov (make-overlay beg end))) + (let ((ov (make-overlay beg end)) + (image-type (or image-type 'png))) (overlay-put ov 'org-overlay-type 'org-latex-overlay) (overlay-put ov 'evaporate t) (overlay-put ov @@ -19008,10 +19016,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 image-type :file image)))) (overlay-put ov 'display - (list 'image :type 'png :file image :ascent 'center))))) + (list 'image :type image-type :file image :ascent 'center))))) (defun org--list-latex-overlays (&optional beg end) "List all Org LaTeX overlays in current buffer. @@ -19092,7 +19100,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 +19131,7 @@ 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 '(dvipng dvisvgm imagemagick))) (overlay-recenter (point-max))) (while (re-search-forward math-regexp nil t) (unless (and overlays @@ -19148,7 +19156,7 @@ 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) + ((dvipng dvisvgm imagemagick) ;; Process to an image. (cl-incf cnt) (goto-char beg) @@ -19172,9 +19180,11 @@ Some of the options can be changed using the variable org-latex-packages-alist org-format-latex-options forbuffer value fg bg)))) + (imagetype (if (eq processing-type 'dvisvgm) + 'svg '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 +19206,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 @@ -19315,10 +19325,10 @@ inspection." (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. +This function calls `org-create-formula-image-with-dvipng' +`org-create-formula-image-with-dvisvgm' 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." @@ -19330,12 +19340,16 @@ share a good deal of logic." (org-check-external-command "dvipng" "needed to convert LaTeX fragments to images") #'org-create-formula-image-with-dvipng) + (dvisvgm + (org-check-external-command + "dvisvgm" "needed to convert LaTeX fragments to images") + #'org-create-formula-image-with-dvisvgm) (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'"))) + "Invalid value of `org-latex-create-formula-image-program'"))) string tofile options buffer)) (declare-function org-export-get-backend "ox" (name)) @@ -19429,6 +19443,64 @@ horizontal and vertical directions." (delete-file (concat texfilebase e)))) pngfile)))) +(defun org-create-formula-image-with-dvisvgm (string tofile options buffer) + "This calls dvisvgm." + (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")) + (xdvfile (concat texfilebase ".xdv")) + (svgfile (concat texfilebase ".svg")) + (scale (number-to-string (or (plist-get options (if buffer :scale :html-scale)) 2.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-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 '(:name dvisvgm :need dvi)) + (if (not (or (file-exists-p dvifile) + (file-exists-p xdvfile))) + (progn (message "Failed to create dvi or xdv file from %s" texfile) nil) + (ignore-errors + (call-process "dvisvgm" nil nil nil + (if (file-exists-p dvifile) + dvifile + xdvfile) + "-n" + "-b" "min" + "-c" scale + "-o" svgfile)) + (if (not (file-exists-p svgfile)) + (if org-format-latex-signal-error + (error "Failed to create svg file from %s" texfile) + (message "Failed to create svg file from %s" texfile) + nil) + ;; Use the requested file name and clean up + (copy-file svgfile tofile 'replace) + (dolist (e '(".dvi" ".xdv" ".tex" ".aux" ".log" ".svg" ".out")) + (when (file-exists-p (concat texfilebase e)) + (delete-file (concat texfilebase e)))) + svgfile)))) + (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." diff --git a/lisp/ox-html.el b/lisp/ox-html.el index b188c38..182b729 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -818,19 +818,22 @@ 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. +`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. + imagemagick to convert pdf files to png files. `mathjax' Do MathJax preprocessing and arrange for MathJax.js to - be loaded. + be loaded. t Synonym for `mathjax'." :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 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,8 +2763,8 @@ 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 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) @@ -2777,7 +2780,7 @@ a plist containing export properties." "\n") "\n"))))) (setq cache-relpath - (concat "ltxpng/" + (concat "ltximg/" (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) @@ -2801,7 +2804,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (let ((formula-link (org-html-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) @@ -2822,7 +2825,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (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..6599721 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -2300,11 +2325,11 @@ used as a communication channel." (when (org-string-nw-p height) (setq options (concat options ",height=" height))) (let ((search-option (org-element-property :search-option link))) - (when (and search-option - (equal filetype "pdf") - (org-string-match-p "\\`[0-9]+\\'" search-option) - (not (org-string-match-p "page=" options))) - (setq options (concat options ",page=" search-option)))) + (when (and search-option + (equal filetype "pdf") + (org-string-match-p "\\`[0-9]+\\'" search-option) + (not (org-string-match-p "page=" options))) + (setq options (concat options ",page=" search-option)))) (setq image-code (format "\\includegraphics%s{%s}" (cond ((not (org-string-nw-p options)) "") @@ -3515,7 +3540,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 caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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 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 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))) + ;; 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. + pdffile))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4 [-- Attachment #2: Type: text/plain, Size: 5 bytes --] -- ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-14 6:30 [PATCH] New feature: Use dvisvgm to preview latex formular Feng Shu @ 2016-05-14 8:47 ` numbchild 2016-05-14 14:56 ` Feng Shu 1 sibling, 0 replies; 25+ messages in thread From: numbchild @ 2016-05-14 8:47 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel [-- Attachment #1: Type: text/plain, Size: 325 bytes --] This is great! [stardiviner] <Hack this world!> GPG key ID: 47C32433 IRC(freeenode): stardiviner Twitter: @numbchild Key fingerprint = 9BAA 92BC CDDD B9EF 3B36 CB99 B8C4 B8E5 47C3 2433 Blog: http://stardiviner.github.io/ 2016-05-14 14:30 GMT+08:00 Feng Shu <tumashu@163.com>: > > -- > [-- Attachment #2: Type: text/html, Size: 927 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-14 6:30 [PATCH] New feature: Use dvisvgm to preview latex formular Feng Shu 2016-05-14 8:47 ` numbchild @ 2016-05-14 14:56 ` Feng Shu 2016-05-15 2:27 ` Feng Shu 2016-05-15 6:02 ` (version 3) " Feng Shu 1 sibling, 2 replies; 25+ messages in thread From: Feng Shu @ 2016-05-14 14:56 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 84 bytes --] "Feng Shu" <tumashu@163.com> writes: This is version 2, make diff more easy read. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 26431 bytes --] From 66804cf5642256a38beb0b84ad8194562f34bfce Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Sat, 14 May 2016 22:42:53 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's 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): Add dvisvgm case. (org-create-formula-image-with-dvisvgm): New function, deal with latex formula with dvisvgm command. * 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 | 101 ++++++++++++++++++++++++++++------ lisp/ox-html.el | 19 ++++--- lisp/ox-latex.el | 161 +++++++++++++++++++++++++++++++++++-------------------- 4 files changed, 225 insertions(+), 95 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..d86042c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3985,15 +3985,22 @@ 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/" +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(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 +19003,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 +19016,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 +19100,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 +19131,7 @@ 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 '(dvipng dvisvgm imagemagick))) (overlay-recenter (point-max))) (while (re-search-forward math-regexp nil t) (unless (and overlays @@ -19148,7 +19156,7 @@ 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) + ((dvipng dvisvgm imagemagick) ;; Process to an image. (cl-incf cnt) (goto-char beg) @@ -19172,9 +19180,10 @@ Some of the options can be changed using the variable org-latex-packages-alist org-format-latex-options forbuffer value fg bg)))) + (imagetype (if (eq processing-type 'dvisvgm) 'svg '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 +19205,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 @@ -19315,10 +19324,10 @@ inspection." (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. +This function calls `org-create-formula-image-with-dvipng' +`org-create-formula-image-with-dvisvgm' 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." @@ -19330,6 +19339,10 @@ share a good deal of logic." (org-check-external-command "dvipng" "needed to convert LaTeX fragments to images") #'org-create-formula-image-with-dvipng) + (dvisvgm + (org-check-external-command + "dvisvgm" "needed to convert LaTeX fragments to images") + #'org-create-formula-image-with-dvisvgm) (imagemagick (org-check-external-command "convert" "you need to install imagemagick") @@ -19429,6 +19442,64 @@ horizontal and vertical directions." (delete-file (concat texfilebase e)))) pngfile)))) +(defun org-create-formula-image-with-dvisvgm (string tofile options buffer) + "This calls dvisvgm." + (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")) + (xdvfile (concat texfilebase ".xdv")) + (svgfile (concat texfilebase ".svg")) + (scale (number-to-string (or (plist-get options (if buffer :scale :html-scale)) 2.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-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 '(:name dvisvgm :need dvi)) + (if (not (or (file-exists-p dvifile) + (file-exists-p xdvfile))) + (progn (message "Failed to create dvi or xdv file from %s" texfile) nil) + (ignore-errors + (call-process "dvisvgm" nil nil nil + (if (file-exists-p dvifile) + dvifile + xdvfile) + "-n" + "-b" "min" + "-c" scale + "-o" svgfile)) + (if (not (file-exists-p svgfile)) + (if org-format-latex-signal-error + (error "Failed to create svg file from %s" texfile) + (message "Failed to create svg file from %s" texfile) + nil) + ;; Use the requested file name and clean up + (copy-file svgfile tofile 'replace) + (dolist (e '(".dvi" ".xdv" ".tex" ".aux" ".log" ".svg" ".out")) + (when (file-exists-p (concat texfilebase e)) + (delete-file (concat texfilebase e)))) + svgfile)))) + (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." diff --git a/lisp/ox-html.el b/lisp/ox-html.el index b188c38..2c1fa4a 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 "ltximg/" (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) @@ -2801,7 +2804,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (let ((formula-link (org-html-format-latex latex-frag processing-type info))) (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) @@ -2822,7 +2825,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (case processing-type ((t mathjax) (org-html-format-latex latex-frag 'mathjax info)) - ((dvipng imagemagick) + ((dvipng dvisvgm imagemagick) (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..ccbd348 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -3515,7 +3540,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 caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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 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 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))) + ;; 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. + pdffile))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4 [-- Attachment #3: Type: text/plain, Size: 6 bytes --] -- ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-14 14:56 ` Feng Shu @ 2016-05-15 2:27 ` Feng Shu 2016-05-15 6:02 ` (version 3) " Feng Shu 1 sibling, 0 replies; 25+ messages in thread From: Feng Shu @ 2016-05-15 2:27 UTC (permalink / raw) To: emacs-orgmode "Feng Shu" <tumashu@163.com> writes: I will refactor the latex previewing code, this patch should be delay reviewd. > "Feng Shu" <tumashu@163.com> writes: > > This is version 2, make diff more easy read. > > From 66804cf5642256a38beb0b84ad8194562f34bfce Mon Sep 17 00:00:00 2001 > From: Feng Shu <tumashu@163.com> > Date: Sat, 14 May 2016 22:42:53 +0800 > Subject: [PATCH] New feature: Use dvisvgm to preview latex formular > > Tester should set like below: > > (setq org-latex-create-formula-image-program 'dvisvgm) > (setq org-latex-pdf-process > '(:fetcher my-org-latex-pdf-process-format)) > (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) > (cond > (snippet '("latex -interaction nonstopmode -output-directory %o %f")) > (t '("%latex -interaction nonstopmode -output-directory %o %f" > "%latex -interaction nonstopmode -output-directory %o %f" > "%latex -interaction nonstopmode -output-directory %o %f")))) > > * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. > (org-latex-compile): Add a new optional argument: caller-info, > which used to record the caller's 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): Add dvisvgm case. > (org-create-formula-image-with-dvisvgm): New function, deal with latex formula with dvisvgm command. > > * 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 | 101 ++++++++++++++++++++++++++++------ > lisp/ox-html.el | 19 ++++--- > lisp/ox-latex.el | 161 +++++++++++++++++++++++++++++++++++-------------------- > 4 files changed, 225 insertions(+), 95 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 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 > @@ -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 > -@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 > +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-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 @pxref{@LaTeX{} fragments}), > @@ -11713,6 +11713,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 > @@ -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 > +@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 > @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. > @end table > > @cindex dvipng > +@cindex 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 > > +@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 > diff --git a/lisp/org.el b/lisp/org.el > index f45d5d0..d86042c 100644 > --- a/lisp/org.el > +++ b/lisp/org.el > @@ -3985,15 +3985,22 @@ 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/" > +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) > +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory > + "Org mode version 9.0") > +(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 +19003,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 +19016,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 +19100,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 +19131,7 @@ 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 '(dvipng dvisvgm imagemagick))) > (overlay-recenter (point-max))) > (while (re-search-forward math-regexp nil t) > (unless (and overlays > @@ -19148,7 +19156,7 @@ 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) > + ((dvipng dvisvgm imagemagick) > ;; Process to an image. > (cl-incf cnt) > (goto-char beg) > @@ -19172,9 +19180,10 @@ Some of the options can be changed using the variable > org-latex-packages-alist > org-format-latex-options > forbuffer value fg bg)))) > + (imagetype (if (eq processing-type 'dvisvgm) 'svg '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 +19205,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 > @@ -19315,10 +19324,10 @@ inspection." > > (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. > +This function calls `org-create-formula-image-with-dvipng' > +`org-create-formula-image-with-dvisvgm' 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." > @@ -19330,6 +19339,10 @@ share a good deal of logic." > (org-check-external-command > "dvipng" "needed to convert LaTeX fragments to images") > #'org-create-formula-image-with-dvipng) > + (dvisvgm > + (org-check-external-command > + "dvisvgm" "needed to convert LaTeX fragments to images") > + #'org-create-formula-image-with-dvisvgm) > (imagemagick > (org-check-external-command > "convert" "you need to install imagemagick") > @@ -19429,6 +19442,64 @@ horizontal and vertical directions." > (delete-file (concat texfilebase e)))) > pngfile)))) > > +(defun org-create-formula-image-with-dvisvgm (string tofile options buffer) > + "This calls dvisvgm." > + (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")) > + (xdvfile (concat texfilebase ".xdv")) > + (svgfile (concat texfilebase ".svg")) > + (scale (number-to-string (or (plist-get options (if buffer :scale :html-scale)) 2.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-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 '(:name dvisvgm :need dvi)) > + (if (not (or (file-exists-p dvifile) > + (file-exists-p xdvfile))) > + (progn (message "Failed to create dvi or xdv file from %s" texfile) nil) > + (ignore-errors > + (call-process "dvisvgm" nil nil nil > + (if (file-exists-p dvifile) > + dvifile > + xdvfile) > + "-n" > + "-b" "min" > + "-c" scale > + "-o" svgfile)) > + (if (not (file-exists-p svgfile)) > + (if org-format-latex-signal-error > + (error "Failed to create svg file from %s" texfile) > + (message "Failed to create svg file from %s" texfile) > + nil) > + ;; Use the requested file name and clean up > + (copy-file svgfile tofile 'replace) > + (dolist (e '(".dvi" ".xdv" ".tex" ".aux" ".log" ".svg" ".out")) > + (when (file-exists-p (concat texfilebase e)) > + (delete-file (concat texfilebase e)))) > + svgfile)))) > + > (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." > diff --git a/lisp/ox-html.el b/lisp/ox-html.el > index b188c38..2c1fa4a 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 "ltximg/" > (file-name-sans-extension > (file-name-nondirectory bfn))) > cache-dir (file-name-directory bfn)) > @@ -2801,7 +2804,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." > (case processing-type > ((t mathjax) > (org-html-format-latex latex-frag 'mathjax info)) > - ((dvipng imagemagick) > + ((dvipng dvisvgm imagemagick) > (let ((formula-link > (org-html-format-latex latex-frag processing-type info))) > (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) > @@ -2822,7 +2825,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." > (case processing-type > ((t mathjax) > (org-html-format-latex latex-frag 'mathjax info)) > - ((dvipng imagemagick) > + ((dvipng dvisvgm imagemagick) > (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..ccbd348 100644 > --- a/lisp/ox-latex.el > +++ b/lisp/ox-latex.el > @@ -1143,7 +1143,32 @@ 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 plist, the first element of the > +plist is :fetcher and the second is a function, for example: > + > + (setq org-latex-pdf-process > + '(:fetcher my-org-latex-pdf-process-format)) > + > + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) > + (cond > + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) > + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" > + \"%latex -interaction nonstopmode -output-directory %o %f\" > + \"%latex -interaction nonstopmode -output-directory %o %f\")))) > + > +`org-latex-compile' will call the second function, then use the > +returned command list. > + > +the function has three optional arguments: texfile, snippet and > +caller-info, when `org-latex-compile' compile a tex snippet for > +previewing, snippet will set to t and client-info argument will > +record the infomation of org-latex-compile's caller, for example: > + > + (:name dvisvgm :need dvi) > + > +This information can be used to select tex command." > :group 'org-export-pdf > :type '(choice > (repeat :tag "Shell command sequence" > @@ -3515,7 +3540,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 caller-info) > "Compile a TeX file. > > TEXFILE is the name of the file being compiled. Processing is > @@ -3525,6 +3550,16 @@ 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. > > +By default, `org-latex-compile' will compile `texfile' to a pdf > +file, but when we compile a tex snippet, the desired output may > +dvi or xdv file instead of pdf file, snippet-generate-function > +can tell `org-latex-compile' the infomation with the argument > +CALLER-INFO, then org-latex-compile can find proper commands > +with this infomation, this argument is a property list, for > +example: > + > + (:caller dvisvgm :need dvi) > + > 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) > + (latex-pdf-process > + (if fetcher-function > + (if (functionp fetcher-function) > + (funcall fetcher-function > + (shell-quote-argument texfile) snippet caller-info) > + (error "`org-latex-pdf-process' set an invalid fetcher function.")) > + org-latex-pdf-process))) > + (save-window-excursion > + (cond > + ;; A function is provided: Apply it. > + ((functionp latex-pdf-process) > + (funcall 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 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 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))) > + ;; 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. > + pdffile))))) > > (defun org-latex--collect-warnings (buffer) > "Collect some warnings from \"pdflatex\" command output. > -- > 2.1.4 -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-14 14:56 ` Feng Shu 2016-05-15 2:27 ` Feng Shu @ 2016-05-15 6:02 ` Feng Shu 2016-05-15 12:14 ` Feng Shu 2016-05-15 12:16 ` (version 4) " Feng Shu 1 sibling, 2 replies; 25+ messages in thread From: Feng Shu @ 2016-05-15 6:02 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 162 bytes --] This is version 3 patch, the latex-previewing code is refacter org-create-formula-image-with-dvipng and org-create-formula-image-with-imagemagick are removed. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 38721 bytes --] From 164c5f4bd41ba29d65fc2c5454b5c4b596c6eb7c Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Sat, 14 May 2016 22:42:53 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (princ (format "The caller's info: %s" caller-info)) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's 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 | 357 +++++++++++++++++++++++++++++++------------------------ lisp/ox-html.el | 28 +++-- lisp/ox-latex.el | 161 ++++++++++++++++--------- 4 files changed, 344 insertions(+), 241 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..10dcf40 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3985,15 +3985,89 @@ 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 + :scale-adjust 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 + :scal-adjust 1.0 + :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 + :scale-adjust 1.0 + :post-clean (".pdf" ".tex" ".aux" ".log" ".png" ".out") + :commands (("convert" "-density" "%dpi%" "-trim" "-antialias" "%input-file%" "-quality" "100" "%output-file%")))) + "Org mode can use some external commands to generate TeX snippet's image for +proviewing or inserting to html file, for example: dvipng, dvisvgm or imagemagick +this variable tell `org-create-formula-image' how to use the above command. + + :class symbol, this setting may useful in future. + :name string, the backend's name. + :programs string-list, 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 it set to 'latex, latex xcolor macro will be used + to deal with background and fontground color of image, 'divpng + is only useful to dvipng backend. + :scale-adjust number, adjust image's size, only useful for backend developers. + :need-clean string-list, the files matched its elements will be cleaned up + after image generated. + :commands list, the commands setting, the following special strings, + will be replaced to according value before command called. + + 1. %fg% fontground + 2. %bg% background + 3. %dpi% dpi, used to adjust image size by some backend. + 4. %scale% scale, used to adjust image size by some backend. + 5. %input-file% input file name. + 6. %output-file% output file name. + 7. %file-base% input file name's base name. + 8. %tmpdir% temporary dir used by `org-create-formula-image'. + + For example, %tmpdir% may be replaced to /tmp in linux." + :group 'org-latex + :version "24.1" + :type 'alist) + +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(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 +19070,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 +19083,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 +19167,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 +19198,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 +19215,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 +19224,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 (assoc 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 +19251,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 +19276,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 +19285,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 +19295,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 +19393,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 +19423,121 @@ 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." +(declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) +(defun org-create-formula-image (string tofile options buffer &optional type) + "Create an image from LaTeX source using program." (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) + (let* ((type (or type 'dvipng)) + (backend-info + (cdr (assoc 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)) + (scale-adjust (or (plist-get backend-info :scale-adjust) 1.0)) + (post-clean + (delete-dups `(,@(plist-get backend-info :post-clean) + ".dvi" ".xdv" ".tex" ".aux" ".log" + ".svg" ".png" ".jpg" ".jpeg" ".out"))) + (commands (plist-get backend-info :commands)) + (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 + (input-file (format "%s.%s" texfilebase input-type)) + (output-file (format "%s.%s" texfilebase output-type)) + (scale (* scale-adjust + (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." - (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)))) + "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" scale)) + ("%input-file%" . ,input-file) + ("%output-file%" . ,output-file) + ("%file-base%" . ,texfilebase) + ("%tmpdir" . ,tmpdir))) + ;; Compile latex snippet file with `org-latex-compile'. + (org-latex-compile texfile t backend-info) + ;; Use latex command as a fallback. + (when (not (file-exists-p input-file)) + (message "`org-latex-complie' fail to compile %s, try latex command instead." texfile) + (let ((dir default-directory)) + (ignore-errors + (cd tmpdir) + (call-process "latex" nil nil nil texfile)) + (cd dir))) + (if (not (file-exists-p input-file)) + (progn (message "Failed to create %s file from %s" input-file 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))) + ;; (princ args-alist) + ;; (princ command) + (ignore-errors + (apply 'call-process + `(,(car command) nil nil nil ,@(cdr command))))))) + (if (not (file-exists-p output-file)) + (if org-format-latex-signal-error + (error "Failed to create %s file from %s" output-file texfile) + (message "Failed to create %s file from %s" output-file texfile) + 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..6a84a35 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 "ltximg/" (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..ccbd348 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -3515,7 +3540,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 caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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 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 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))) + ;; 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. + pdffile))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 6:02 ` (version 3) " Feng Shu @ 2016-05-15 12:14 ` Feng Shu 2016-05-15 22:32 ` Nicolas Goaziou 2016-05-15 12:16 ` (version 4) " Feng Shu 1 sibling, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-15 12:14 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 78 bytes --] "Feng Shu" <tumashu@163.com> writes: Version 4 patch, minor change based v3 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 39465 bytes --] From 010baf028bb6dbb706f5abb9f99de0552235f2af Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Sat, 14 May 2016 22:42:53 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (princ (format "The caller's info: %s" caller-info)) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's 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 | 366 +++++++++++++++++++++++++++++++------------------------ lisp/ox-html.el | 28 +++-- lisp/ox-latex.el | 161 +++++++++++++++--------- 4 files changed, 354 insertions(+), 240 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..86d9c95 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3985,15 +3985,97 @@ 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 + :scale-adjust 2.0 + :org-latex-compile nil + :need-clean (".dvi" ".tex" ".aux" ".log" ".png" ".out") + :commands (("latex" "-interaction" "nonstopmode" "-output-directory" "%temp-dir%" "%tex-file%") + ("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 + :scal-adjust 2.0 + :org-latex-compile t + :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 + :scale-adjust 2.0 + :org-latex-compile t + :post-clean (".pdf" ".tex" ".aux" ".log" ".png" ".out") + :commands (("convert" "-density" "%dpi%" "-trim" "-antialias" "%input-file%" "-quality" "100" "%output-file%")))) + "Org mode can use some external commands to generate TeX snippet's image for +proviewing or inserting to html file, for example: dvipng, dvisvgm or imagemagick +this variable tell `org-create-formula-image' how to use the above command. + + :class symbol, this setting may useful in future. + :name string, the backend's name. + :programs string-list, 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 it set to 'latex, latex xcolor macro will be used + to deal with background and fontground color of image, 'divpng + is only useful to dvipng backend. + :scale-adjust number, adjust image's size, only useful for backend developers. + :org-latex-compile boolean, if set it to t, `org-create-formula-image' will use + `org-latex-compile' to compile tex file, when set it to nil, + user need to set latex command in `:commands'. + :need-clean string-list, the files matched its elements will be cleaned up + after image generated. + :commands list, the commands setting, the following special strings, + will be replaced to according value before command called. + + 1. %fg% fontground + 2. %bg% background + 3. %dpi% dpi, used to adjust image size by some backend. + 4. %scale% scale, used to adjust image size by some backend. + 5. %tex-file% tex file name. + 6. %input-file% input file name. + 7. %output-file% output file name. + 8. %file-base% input file name's base name. + 9. %temp-dir% temporary dir used by `org-create-formula-image'. + + For example, %tmpdir% may be replaced to /tmp in linux." + :group 'org-latex + :version "24.1" + :type 'alist) + +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(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 +19078,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 +19091,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 +19175,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 +19206,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 +19223,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 +19232,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 (assoc 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 +19259,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 +19284,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 +19293,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 +19303,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 +19401,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 +19431,124 @@ 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." +(declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) +(defun org-create-formula-image (string tofile options buffer &optional type) + "Create an image from LaTeX source using program." (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) + (let* ((type (or type 'dvipng)) + (backend-info + (cdr (assoc 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)) + (scale-adjust (or (plist-get backend-info :scale-adjust) 1.0)) + (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 (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 + (input-file (format "%s.%s" texfilebase input-type)) + (output-file (format "%s.%s" texfilebase output-type)) + (scale (* scale-adjust + (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." - (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)) + "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" scale)) + ("%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-pdf-process'." texfile) + (message "`org-latex-compile' can't compile %s, please adjust `org-latex-pdf-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))) + ;; (princ args-alist) + ;; (princ 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..6a84a35 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 "ltximg/" (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..ccbd348 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -3515,7 +3540,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 caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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 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 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))) + ;; 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. + pdffile))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 12:14 ` Feng Shu @ 2016-05-15 22:32 ` Nicolas Goaziou 2016-05-16 5:32 ` Feng Shu ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-15 22:32 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel Hello, "Feng Shu" <tumashu@163.com> writes: Thank you for this work. This looks interesting. Some comments follow. > * ox-latex.el (org-latex-pdf-process): Add a new config > method, :fetcher. At this point, I think we should instead separate compiler for LaTeX preview from compiler for full LaTeX export. It probably makes sense to have a full fledged compile process for the export back-end possibly with multiple passes to get cross-references right, and a quick process for previews. In any case, I suggest to create a new variable `org-latex-preview-process' for that. > (org-latex-compile): Add a new optional argument: caller-info, > which used to record the caller's info In the same vein, I suggest to extract it out from ox-latex and use a dedicated command for that. WDYT? > (org-create-formula-image): Big refactor, merge dvipng and imagemagick backend's feature. > Add dvisvgm feature. Good news. This part was begging for a refactor. A couple (or more) of tests would be nice too. > -(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 > + :scale-adjust 2.0 > + :org-latex-compile nil > + :need-clean (".dvi" ".tex" ".aux" ".log" ".png" ".out") > + :commands (("latex" "-interaction" "nonstopmode" "-output-directory" "%temp-dir%" "%tex-file%") > + ("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 > + :scal-adjust 2.0 Typo. :scale-adjust > + :org-latex-compile t > + :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 > + :scale-adjust 2.0 > + :org-latex-compile t > + :post-clean (".pdf" ".tex" ".aux" ".log" ".png" ".out") > + :commands (("convert" "-density" "%dpi%" "-trim" "-antialias" "%input-file%" "-quality" "100" "%output-file%")))) > + "Org mode can use some external commands to generate TeX snippet's image for The first line needs to be a sentence on its own. Perhaps: "List definitions of external processes for LaTeX previewing. Org can use some external commands to generate LaTeX snippet' images for ..." > +proviewing or inserting to html file, for example: dvipng, dvisvgm or imagemagick previewing or inserting into HTML files, e.g., > +this variable tell `org-create-formula-image' how to use the above command. tells > + :class symbol, this setting may useful in future. may be useful > + :name string, the backend's name. > + :programs string-list, required programs. list of strings > + :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 it set to 'latex, latex xcolor macro will be used if set to `latex', LaTeX "xcolor" macro is used > + to deal with background and fontground color of image, 'divpng if set to `dvipng' > + is only useful to dvipng backend. > + :scale-adjust number, adjust image's size, only useful for backend developers. > + :org-latex-compile boolean, if set it to t, `org-create-formula-image' will use when non-nil `org-create-formula-image' uses... > + `org-latex-compile' to compile tex file, when set it to nil, otherwise, you need to > + user need to set latex command in `:commands'. > + :need-clean string-list, the files matched its elements will be cleaned up > + after image generated. 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 command called. > + > + 1. %fg% fontground foreground > + For example, %tmpdir% may be replaced to /tmp in linux." may be replaced with "/tmp". > + :group 'org-latex > + :version "24.1" :version "25.1" > + :type 'alist) The type should reflect the complexity of the value. > + > +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) > +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory > + "Org mode version 9.0") See `make-obsolete-variable'. > + (let* ((backend-info > + (cdr (assoc processing-type org-latex-to-image-backends))) `assoc' -> `assq' > + (let* ((type (or type 'dvipng)) > + (backend-info > + (cdr (assoc type org-latex-to-image-backends))) `assq' > + (tmpdir (if (featurep 'xemacs) > (temp-directory) > temporary-file-directory)) You can drop this, Org 9 doesn't support XEmacs anyway. > + (dolist (command commands) > + (let ((command > + (mapcar #'(lambda (c) No need to use #' for lambda. > + (dolist (arg args-alist) > + (setq c (replace-regexp-in-string > + (car arg) (cdr arg) c))) > + c) command))) > + ;; (princ args-alist) > + ;; (princ command) Please remove debugging comments. > + (ignore-errors > + (apply 'call-process Nitpick: #'call-process Regards, -- Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 22:32 ` Nicolas Goaziou @ 2016-05-16 5:32 ` Feng Shu 2016-05-16 13:18 ` Nicolas Goaziou 2016-05-16 5:33 ` Feng Shu 2016-05-16 12:05 ` (v6) " Feng Shu 2 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-16 5:32 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu Nicolas Goaziou <mail@nicolasgoaziou.fr> writes: > In any case, I suggest to create a new variable > `org-latex-preview-process' for that. `org-latex-preview-process' is a good idea, which make org-latex beginner easily, i will add it. > >> (org-latex-compile): Add a new optional argument: caller-info, >> which used to record the caller's info > > In the same vein, I suggest to extract it out from ox-latex and use > a dedicated command for that. > > WDYT? I suggest to add (:generator my-generator-function) style configure to `org-latex-pdf-process', it is simple and powerful feature, we can use this feature to switch latex commands dynamicially, for example: (defun my-latex-pdf-process-generator (texfile snippet extra-info) (cond ((<a>) (<org-latex-pdf-process-style-command1>) ((<b>) (<org-latex-pdf-process-style-command2>))))) although we can set org-latex-pdf-process to a function to do the same work, but this function is hard to write as org-latex-compile, it may only useful for developer instead of user.... caller-info argument is for the above feature. > >> (org-create-formula-image): Big refactor, merge dvipng and imagemagick backend's feature. >> Add dvisvgm feature. > > Good news. This part was begging for a refactor. A couple (or more) of > tests would be nice too. yes >> + >> +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) >> +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory >> + "Org mode version 9.0") > > See `make-obsolete-variable'. Remove the above two and only use the below *one* ? (make-obsolete-variable 'org-latex-preview-ltxpng-directory "Set `org-latex-preview-ltximg-directory' instead." "25.1") ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 5:32 ` Feng Shu @ 2016-05-16 13:18 ` Nicolas Goaziou 2016-05-16 15:06 ` tumashu 0 siblings, 1 reply; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-16 13:18 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel Hello, "Feng Shu" <tumashu@163.com> writes: > I suggest to add (:generator my-generator-function) style configure > to `org-latex-pdf-process', it is simple and powerful feature, we > can use this feature to switch latex commands dynamicially, for example: > > (defun my-latex-pdf-process-generator (texfile snippet extra-info) > (cond > ((<a>) (<org-latex-pdf-process-style-command1>) > ((<b>) (<org-latex-pdf-process-style-command2>))))) > > although we can set org-latex-pdf-process to a function to do the same work, > but this function is hard to write as org-latex-compile, it may only > useful for developer instead of user.... > > caller-info argument is for the above feature. I understand the need to extend `org-latex-pdf-process'. However this isn't a good way to look at it. In fact, it makes little sense to load the whole export framework when you're only after displaying a LaTeX snippet in the current buffer. I think a better approach would be to create a generic tool to compile a file to another format, e.g. `org-compile-file'. It would take a command (as a list of strings or a function) and apply it to the source file name. Then it would check if the output file was produced. Optionally, it would allow to create a buffer so as to retrieve error messages. Then, e.g., `org-latex-compile' or `org-preview-generate-image', could extend this function, i.e., handle specific variables (e.g., `org-latex-pdf-process') and call it with appropriate arguments. As example, here's a proof of concept for `org-compile-file' and `org-latex-compile'. (defun org-compile-file (source process extension &optional spec log-buffer) "Compile a SOURCE file using PROCESS. PROCESS is either a function or a list of shell commands, as strings. If PROCESS is a function, it is called with a single argument: SOURCE file. It must create a file with the same base name and directory as SOURCE, but using extension. If it is a list of commands, each of them is called using `shell-command'. By default, in each command, %b, %f and %o are replaced, respectively, with SOURCE base name, SOURCE full name and SOURCE directory. It is possible, however, to use different place-holders by specifying them in optional argument SPEC. In this case, SPEC should be an alist (CHARACTER REPLACEMENT-STRING). When PROCESS is a list of commands, optional argument LOG-BUFFER can be set to a buffer or a buffer name. `shell-command' then uses it as an output buffer, which may be used for collecting errors. `default-directory' is set to SOURCE directory during the whole process. Return output file or raise an error if it wasn't generated upon executing PROCESS." (let* ((base-name (file-name-sans-extension (file-name-nondirectory source))) (full-name (file-truename source)) (out-dir (file-name-directory source)) ;; Properly set working directory for compilation. (default-directory (if (file-name-absolute-p source) (file-name-directory full-name) default-directory)) (time (current-time))) (save-window-excursion (pcase process ((pred functionp) (funcall process (shell-quote-argument source))) ((pred consp) (let ((log (and log-buffer (get-buffer-create log-buffer))) (spec (or spec `((?b ,(shell-quote-argument base-name)) (?f ,(shell-quote-argument full-name)) (?o ,(shell-quote-argument out-dir)))))) (dolist (command process) (shell-command (format-spec command spec) log)))) (t (error "No valid command to process %S" source))) ;; Check for process failure. (let ((output (concat out-dire base-name extension))) (when (or (not (file-exists-p output)) ;; Only compare times up to whole seconds as some ;; file-systems (e.g. HFS+) do not retain any finer ;; granularity. (time-less-p (cl-subseq (nth 5 (file-attributes output)) 0 2) (cl-subseq time 0 2))) (error (format "File %S wasn't produced" output))) output)))) (defun org-latex-compile (texfile) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is done through the command specified in `org-latex-pdf-process'. Return PDF file name or an error if it couldn't be produced." (message "Processing LaTeX file %s..." texfile) (let* ((base-name (file-name-sans-extension (file-name-nondirectory texfile))) (full-name (file-truename texfile)) (compiler (or (with-temp-buffer (save-excursion (insert-file-contents full-name)) (when (and (search-forward-regexp (regexp-opt org-latex-compilers) (line-end-position 2) t) (progn (beginning-of-line) (looking-at-p "%"))) (match-string 0))) "pdflatex")) (out-dir (file-name-directory texfile)) (spec `((?B ,(shell-quote-argument org-latex-bib-compiler)) (?L ,(shell-quote-argument compiler)) (?b ,(shell-quote-argument base-name)) (?f ,(shell-quote-argument full-name)) (?o ,(shell-quote-argument out-dir)))) (log-buffer (get-buffer-create "*Org PDF LaTeX Output*")) (outfile (org-compile-file texfile (let ((process org-latex-pdf-process)) ;; A function is provided: Apply it. (if (functionp org-latex-pdf-process) org-latex-pdf-process ;; 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. (mapcar (lambda (command) (replace-regexp-in-string "%\\(latex\\|bibtex\\)\\>" (lambda (str) (upcase (substring str 0 2))) command)) org-latex-pdf-process))) ".pdf" log-buffer))) (when org-latex-remove-logfiles (mapc #'delete-file (directory-files out-dir t (concat (regexp-quote base-name) "\\(?:\\.[0-9]+\\)?" "\\." (regexp-opt org-latex-logfiles-extensions))))) (let ((warnings (get-buffer-create(org-latex--collect-warnings outbuf)))) (message (concat "PDF file produced" (cond ((eq warnings 'error) " with errors.") (warnings (concat " with warnings: " warnings)) (t "."))))) ;; Return output file name. outfile)) > Remove the above two and only use the below *one* ? > > (make-obsolete-variable > 'org-latex-preview-ltxpng-directory > "Set `org-latex-preview-ltximg-directory' instead." "25.1") I think (make-obsolete-variable 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory "25.1") is sufficient. The code you wrote is not wrong either, tho. Regards, -- Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 13:18 ` Nicolas Goaziou @ 2016-05-16 15:06 ` tumashu 0 siblings, 0 replies; 25+ messages in thread From: tumashu @ 2016-05-16 15:06 UTC (permalink / raw) To: Nicolas Goaziou; +Cc: orgmode-devel -- 发自我的网易邮箱手机智能版 在 2016-05-16 21:18:20,"Nicolas Goaziou" <mail@nicolasgoaziou.fr> 写道: >Hello, > >"Feng Shu" <tumashu@163.com> writes: > >> I suggest to add (:generator my-generator-function) style configure >> to `org-latex-pdf-process', it is simple and powerful feature, we >> can use this feature to switch latex commands dynamicially, for example: >> >> (defun my-latex-pdf-process-generator (texfile snippet extra-info) >> (cond >> ((<a>) (<org-latex-pdf-process-style-command1>) >> ((<b>) (<org-latex-pdf-process-style-command2>))))) >> >> although we can set org-latex-pdf-process to a function to do the same work, >> but this function is hard to write as org-latex-compile, it may only >> useful for developer instead of user.... >> >> caller-info argument is for the above feature. > >I understand the need to extend `org-latex-pdf-process'. However this >isn't a good way to look at it. In fact, it makes little sense to load >the whole export framework when you're only after displaying a LaTeX >snippet in the current buffer. > >I think a better approach would be to create a generic tool to compile >a file to another format, e.g. `org-compile-file'. It would take a command >(as a list of strings or a function) and apply it to the source file >name. Then it would check if the output file was produced. Optionally, >it would allow to create a buffer so as to retrieve error messages. > >Then, e.g., `org-latex-compile' or `org-preview-generate-image', could >extend this function, i.e., handle specific variables (e.g., >`org-latex-pdf-process') and call it with appropriate arguments. > >As example, here's a proof of concept for `org-compile-file' and >`org-latex-compile'. > > (defun org-compile-file (source process extension &optional spec log-buffer) > "Compile a SOURCE file using PROCESS. > > PROCESS is either a function or a list of shell commands, as > strings. > > If PROCESS is a function, it is called with a single argument: > SOURCE file. It must create a file with the same base name and > directory as SOURCE, but using extension. > > If it is a list of commands, each of them is called using > `shell-command'. By default, in each command, %b, %f and %o are > replaced, respectively, with SOURCE base name, SOURCE full name > and SOURCE directory. It is possible, however, to use different > place-holders by specifying them in optional argument SPEC. In > this case, SPEC should be an alist (CHARACTER REPLACEMENT-STRING). > > When PROCESS is a list of commands, optional argument LOG-BUFFER > can be set to a buffer or a buffer name. `shell-command' then > uses it as an output buffer, which may be used for collecting > errors. > > `default-directory' is set to SOURCE directory during the whole > process. > > Return output file or raise an error if it wasn't generated upon > executing PROCESS." > (let* ((base-name (file-name-sans-extension (file-name-nondirectory source))) > (full-name (file-truename source)) > (out-dir (file-name-directory source)) > ;; Properly set working directory for compilation. > (default-directory (if (file-name-absolute-p source) > (file-name-directory full-name) > default-directory)) > (time (current-time))) > (save-window-excursion > (pcase process > ((pred functionp) (funcall process (shell-quote-argument source))) > ((pred consp) > (let ((log (and log-buffer (get-buffer-create log-buffer))) > (spec (or spec > `((?b ,(shell-quote-argument base-name)) > (?f ,(shell-quote-argument full-name)) > (?o ,(shell-quote-argument out-dir)))))) > (dolist (command process) > (shell-command (format-spec command spec) log)))) > (t (error "No valid command to process %S" source))) > ;; Check for process failure. > (let ((output (concat out-dire base-name extension))) > (when (or (not (file-exists-p output)) > ;; Only compare times up to whole seconds as some > ;; file-systems (e.g. HFS+) do not retain any finer > ;; granularity. > (time-less-p (cl-subseq (nth 5 (file-attributes output)) 0 2) > (cl-subseq time 0 2))) > (error (format "File %S wasn't produced" output))) > output)))) > > (defun org-latex-compile (texfile) > "Compile a TeX file. > > TEXFILE is the name of the file being compiled. Processing is > done through the command specified in `org-latex-pdf-process'. > > Return PDF file name or an error if it couldn't be produced." > (message "Processing LaTeX file %s..." texfile) > (let* ((base-name (file-name-sans-extension (file-name-nondirectory texfile))) > (full-name (file-truename texfile)) > (compiler (or (with-temp-buffer > (save-excursion (insert-file-contents full-name)) > (when (and (search-forward-regexp > (regexp-opt org-latex-compilers) (line-end-position 2) t) > (progn (beginning-of-line) > (looking-at-p "%"))) > (match-string 0))) > "pdflatex")) > (out-dir (file-name-directory texfile)) > (spec `((?B ,(shell-quote-argument org-latex-bib-compiler)) > (?L ,(shell-quote-argument compiler)) > (?b ,(shell-quote-argument base-name)) > (?f ,(shell-quote-argument full-name)) > (?o ,(shell-quote-argument out-dir)))) > (log-buffer (get-buffer-create "*Org PDF LaTeX Output*")) > (outfile > (org-compile-file > texfile > (let ((process org-latex-pdf-process)) > ;; A function is provided: Apply it. > (if (functionp org-latex-pdf-process) > org-latex-pdf-process > ;; 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. > (mapcar (lambda (command) > (replace-regexp-in-string > "%\\(latex\\|bibtex\\)\\>" > (lambda (str) (upcase (substring str 0 2))) > command)) > org-latex-pdf-process))) > ".pdf" > log-buffer))) > (when org-latex-remove-logfiles > (mapc #'delete-file > (directory-files > out-dir t > (concat (regexp-quote base-name) > "\\(?:\\.[0-9]+\\)?" > "\\." > (regexp-opt org-latex-logfiles-extensions))))) > (let ((warnings (get-buffer-create(org-latex--collect-warnings outbuf)))) > (message (concat "PDF file produced" > (cond > ((eq warnings 'error) " with errors.") > (warnings (concat " with warnings: " warnings)) > (t "."))))) > ;; Return output file name. > outfile)) > i do not understand you mean, we may say different things. org-latex-compile is enough, do you want split org-latex-compile to two function? i suggest discuss base my v6 patch. >> Remove the above two and only use the below *one* ? >> >> (make-obsolete-variable >> 'org-latex-preview-ltxpng-directory >> "Set `org-latex-preview-ltximg-directory' instead." "25.1") > >I think > > (make-obsolete-variable > 'org-latex-preview-ltxpng-directory > 'org-latex-preview-ltximg-directory "25.1") > >is sufficient. The code you wrote is not wrong either, tho. > >Regards, > >-- >Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 22:32 ` Nicolas Goaziou 2016-05-16 5:32 ` Feng Shu @ 2016-05-16 5:33 ` Feng Shu 2016-05-16 13:19 ` Nicolas Goaziou 2016-05-16 12:05 ` (v6) " Feng Shu 2 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-16 5:33 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu Nicolas Goaziou <mail@nicolasgoaziou.fr> writes: >> + :group 'org-latex >> + :version "24.1" > > :version "25.1" > >> + :type 'alist) I need to help to deal with it, what about just remove :type? > ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 3) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 5:33 ` Feng Shu @ 2016-05-16 13:19 ` Nicolas Goaziou 0 siblings, 0 replies; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-16 13:19 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel "Feng Shu" <tumashu@163.com> writes: > Nicolas Goaziou <mail@nicolasgoaziou.fr> writes: >>> + :type 'alist) > > I need to help to deal with it, what about just remove :type? You cannot remove :type as it would make the defcustom invalid. However, I wouldn't bother much at the moment since the design is not yet finalized. Regards, ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (v6) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 22:32 ` Nicolas Goaziou 2016-05-16 5:32 ` Feng Shu 2016-05-16 5:33 ` Feng Shu @ 2016-05-16 12:05 ` Feng Shu 2016-05-16 21:17 ` Nicolas Goaziou 2 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-16 12:05 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 140 bytes --] Nicolas Goaziou <mail@nicolasgoaziou.fr> writes: This is my modified patch (v6), fix the problems you stated. please review again, thank! [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 40382 bytes --] From 29760e5c5876fb6b772f7a6004b7160bc06efba8 Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 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 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: (v6) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 12:05 ` (v6) " Feng Shu @ 2016-05-16 21:17 ` Nicolas Goaziou 2016-05-16 22:17 ` tumashu ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-16 21:17 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel Hello, "Feng Shu" <tumashu@163.com> writes: > This is my modified patch (v6), fix the problems you stated. please review > again, thank! Thank you. Comments follow. > From 29760e5c5876fb6b772f7a6004b7160bc06efba8 Mon Sep 17 00:00:00 2001 > From: Feng Shu <tumashu@163.com> > 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. As discussed in another message, I don't think we should mess with `org-latex-compile'. Instead, we could factor out the needed part in `org-latex-compile' and make it a generic function. Then we can introduce a new function to specifically handle previewing related compilation. Note that I'm not asking you to implement the factoring out part in your patch, but to tell me if the following would fulfill your needs for `org-create-formula-image'. I'm sending its docstring again. (defun org-compile-file (source process extension &optional spec log-buffer) "Compile a SOURCE file using PROCESS. PROCESS is either a function or a list of shell commands, as strings. If PROCESS is a function, it is called with a single argument: SOURCE file. It must create a file with the same base name and directory as SOURCE, but using extension. If it is a list of commands, each of them is called using `shell-command'. By default, in each command, %b, %f and %o are replaced, respectively, with SOURCE base name, SOURCE full name and SOURCE directory. It is possible, however, to use different place-holders by specifying them in optional argument SPEC. In this case, SPEC should be an alist (STRING REPLACEMENT-STRING). When PROCESS is a list of commands, optional argument LOG-BUFFER can be set to a buffer or a buffer name. `shell-command' then uses it as an output buffer, which may be used for collecting errors. `default-directory' is set to SOURCE directory during the whole process. Generated file is expected to use the same directory and base name as SOURCE, and end with EXTENSION. Return its filename or raise an error if it wasn't generated upon executing 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 You need to use two spaces to separate sentences. > +(defcustom org-latex-to-image-backends You could remove it `org-preview-latex-backends' since it doesn't belong to the "org-latex" namespace. > +dvisvgm Process the LaTeX fragments to dvi/xdv file, then convert > + dvi/xdv files to svg files using dvipng. You probably mean "using dvisvgm". > +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. or imagemagick. This variable tells... > + :class symbol, this setting may be useful in future. Meanwhile, I suggest to remove it, unless you have a clear plan in mind. > + :name string, the backend's name. > + :programs list of strings, required programs. > + :message string, message it when required program can't be found. required programs > + :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%\". are generated; you should used them in ... with special strings: ... > + :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. This option... users... > + :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. Is it :need-clean or :post-clean? A back-end uses the former, the others the latter. > + :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. which is used > + 4. %scale% the image size scale ratio, which used to > + adjust image size by some backend's command. which is used > + For example, \"%temp-dir%/test\" may be replaced to \"/tmp/test\" > + in linux." Again, please drop "in linux". > + :group 'org-latex > + :version "25.1" > + :type '(alist :tag "LaTeX to image backends" > + :value-type (plist))) This can work, but will need to be refined for a nice Customize interface. > (org-in-regexp > "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*"))) > > + (when (and overlays (memq processing-type > + (mapcar #'car org-latex-to-image-backends))) (memq processing-type ...) => (assq processing-type org-latex-to-image-backends) > @@ -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)) Ditto. > + (let* ((type (or type 'dvipng)) > + (backend-info > + (cdr (assq type org-latex-to-image-backends))) > + (programs (plist-get backend-info :programs)) (cons "latex" (plist-get backend-info :programs)) so you can avoid duplicating checks later. Up to you. > + (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) Isn't it :need-clean? > + ".dvi" ".xdv" ".tex" ".aux" ".log" > + ".svg" ".png" ".jpg" ".jpeg" ".out"))) Why do you force other types since they are already provided by preview image back-ends. You could do instead (or (plist-get backend-info :need-clean) '(".dvi" ...)) > - (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)) See above. > (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)) Ditto. > (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 I suggest to rename it `org-preview-latex-process' and move it to "org.el". > + '("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. The first line should be a sentence on its own. Maybe Commands to process a LaTeX snippet to dvi, xdv, or pdf. The produced file can be converted to an image and previewed in the buffer or inserted in an HTML file. > + :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))) Note that there is no requirement for this variable to mimic `org-latex-pdf-process'. In particular, the function could accept three arguments (texfile, snippet and extra info) bypassing the need for the :generator trick altogether. Regards, -- Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (v6) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 21:17 ` Nicolas Goaziou @ 2016-05-16 22:17 ` tumashu 2016-05-17 1:15 ` tumashu 2016-05-18 6:30 ` (V8) " Feng Shu 2 siblings, 0 replies; 25+ messages in thread From: tumashu @ 2016-05-16 22:17 UTC (permalink / raw) To: Nicolas Goaziou; +Cc: orgmode-devel i see your mean, i think org-compile-file can do more thing, for example: handle dvipng or dvisvgm, what i need to know is the different of call-process and run shell command. can we use run shell command instead of call-process in converting dvi to png? special string need to do more work, i think. -- 发自我的网易邮箱手机智能版 在 2016-05-17 05:17:45,"Nicolas Goaziou" <mail@nicolasgoaziou.fr> 写道: >Hello, > >"Feng Shu" <tumashu@163.com> writes: > >> This is my modified patch (v6), fix the problems you stated. please review >> again, thank! > >Thank you. Comments follow. > >> From 29760e5c5876fb6b772f7a6004b7160bc06efba8 Mon Sep 17 00:00:00 2001 >> From: Feng Shu <tumashu@163.com> >> 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. > >As discussed in another message, I don't think we should mess with >`org-latex-compile'. Instead, we could factor out the needed part in >`org-latex-compile' and make it a generic function. Then we can >introduce a new function to specifically handle previewing related >compilation. > >Note that I'm not asking you to implement the factoring out part in your >patch, but to tell me if the following would fulfill your needs for >`org-create-formula-image'. I'm sending its docstring again. > > (defun org-compile-file (source process extension &optional spec log-buffer) > "Compile a SOURCE file using PROCESS. > > PROCESS is either a function or a list of shell commands, as > strings. > > If PROCESS is a function, it is called with a single argument: > SOURCE file. It must create a file with the same base name and > directory as SOURCE, but using extension. > > If it is a list of commands, each of them is called using > `shell-command'. By default, in each command, %b, %f and %o are > replaced, respectively, with SOURCE base name, SOURCE full name > and SOURCE directory. It is possible, however, to use different > place-holders by specifying them in optional argument SPEC. In > this case, SPEC should be an alist (STRING REPLACEMENT-STRING). > > When PROCESS is a list of commands, optional argument LOG-BUFFER > can be set to a buffer or a buffer name. `shell-command' then > uses it as an output buffer, which may be used for collecting > errors. > > `default-directory' is set to SOURCE directory during the whole > process. > > Generated file is expected to use the same directory and base > name as SOURCE, and end with EXTENSION. Return its filename or > raise an error if it wasn't generated upon executing 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 > >You need to use two spaces to separate sentences. > >> +(defcustom org-latex-to-image-backends > >You could remove it `org-preview-latex-backends' since it doesn't belong >to the "org-latex" namespace. > >> +dvisvgm Process the LaTeX fragments to dvi/xdv file, then convert >> + dvi/xdv files to svg files using dvipng. > >You probably mean "using dvisvgm". > >> +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. > >or imagemagick. This variable tells... > >> + :class symbol, this setting may be useful in future. > >Meanwhile, I suggest to remove it, unless you have a clear plan in mind. > >> + :name string, the backend's name. >> + :programs list of strings, required programs. >> + :message string, message it when required program can't be found. > >required programs > >> + :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%\". > >are generated; you should used them in ... with special strings: ... > >> + :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. > >This option... users... > >> + :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. > >Is it :need-clean or :post-clean? A back-end uses the former, the others >the latter. > >> + :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. > >which is used > >> + 4. %scale% the image size scale ratio, which used to >> + adjust image size by some backend's command. > >which is used > >> + For example, \"%temp-dir%/test\" may be replaced to \"/tmp/test\" >> + in linux." > >Again, please drop "in linux". > >> + :group 'org-latex >> + :version "25.1" >> + :type '(alist :tag "LaTeX to image backends" >> + :value-type (plist))) > >This can work, but will need to be refined for a nice Customize >interface. > >> (org-in-regexp >> "\\\\[a-zA-Z]+\\*?\\(\\(\\[[^][\n{}]*\\]\\)\\|\\({[^{}\n]*}\\)\\)*"))) >> >> + (when (and overlays (memq processing-type >> + (mapcar #'car org-latex-to-image-backends))) > >(memq processing-type ...) => (assq processing-type org-latex-to-image-backends) > >> @@ -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)) > >Ditto. > >> + (let* ((type (or type 'dvipng)) >> + (backend-info >> + (cdr (assq type org-latex-to-image-backends))) >> + (programs (plist-get backend-info :programs)) > >(cons "latex" (plist-get backend-info :programs)) > >so you can avoid duplicating checks later. Up to you. > >> + (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) > >Isn't it :need-clean? > >> + ".dvi" ".xdv" ".tex" ".aux" ".log" >> + ".svg" ".png" ".jpg" ".jpeg" ".out"))) > >Why do you force other types since they are already provided by preview >image back-ends. You could do instead > >(or (plist-get backend-info :need-clean) > '(".dvi" ...)) > >> - (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)) > >See above. > >> (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)) > >Ditto. > >> (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 > >I suggest to rename it `org-preview-latex-process' and move it to >"org.el". > >> + '("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. > >The first line should be a sentence on its own. Maybe > >Commands to process a LaTeX snippet to dvi, xdv, or pdf. >The produced file can be converted to an image and previewed in the >buffer or inserted in an HTML file. > >> + :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))) > >Note that there is no requirement for this variable to mimic >`org-latex-pdf-process'. In particular, the function could accept three >arguments (texfile, snippet and extra info) bypassing the need for >the :generator trick altogether. > > >Regards, > >-- >Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (v6) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 21:17 ` Nicolas Goaziou 2016-05-16 22:17 ` tumashu @ 2016-05-17 1:15 ` tumashu 2016-05-18 6:30 ` (V8) " Feng Shu 2 siblings, 0 replies; 25+ messages in thread From: tumashu @ 2016-05-17 1:15 UTC (permalink / raw) To: Nicolas Goaziou; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 359 bytes --] If we need 4 cmmand to convert test.dvi to test.png 1. cmd1 test.dvi test.a 2. cmd2 test.a test.b 3. cmd4 test.b test.png does it work correctly? can %b.a convert to text.a ? ("cmd1 %b.dvi %b.a" "cmd2 %b.a %b.b" "cmd3 %b.b %b.png") if it works properly, i suggest merge org-compile-file feature first, i will rebase my patch to it before merge. [-- Attachment #2: Type: text/html, Size: 615 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V8) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-16 21:17 ` Nicolas Goaziou 2016-05-16 22:17 ` tumashu 2016-05-17 1:15 ` tumashu @ 2016-05-18 6:30 ` Feng Shu 2016-05-19 8:22 ` Nicolas Goaziou 2 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-18 6:30 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 692 bytes --] > As discussed in another message, I don't think we should mess with > `org-latex-compile'. Instead, we could factor out the needed part in > `org-latex-compile' and make it a generic function. Then we can > introduce a new function to specifically handle previewing related > compilation. > > Note that I'm not asking you to implement the factoring out part in your > patch, but to tell me if the following would fulfill your needs for > `org-create-formula-image'. I'm sending its docstring again. > I have rebase my patch to new function org-compile-file, the v8 patch is very different with the earlier version, it is more simpler i think, please comment again, thanks for your help! [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 34672 bytes --] From 61885684f4826b06de4bb72b6ef1f369960f268a Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Tue, 17 May 2016 21:24:35 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular * 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-preview-latex-image-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-preview-latex-process-alist): Add new variable, which used to set latex preview processes. (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 | 41 +++-- lisp/org.el | 462 +++++++++++++++++++++++++++++++++++++------------------- lisp/ox-html.el | 27 ++-- 3 files changed, 346 insertions(+), 184 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 17b01c2..ad75b5d 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 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 @@ -10444,11 +10444,11 @@ lines: @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{} +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-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 @pxref{@LaTeX{} fragments}), or for inline previewing within Org mode. @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..d752cac 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3985,15 +3985,103 @@ 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 dvisvgm. + 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-preview-latex-process-alist + '((dvipng + :programs ("latex" "dvipng" "gs") + :message "you need to install latex, dvipng and ghostscript." + :image-input dvi + :image-output png + :image-size-adjust (1.0 . 1.0) + :latex-compiler ("latex -interaction nonstopmode -output-directory %o %t") + :image-converter ("dvipng -fg %F -bg %B -D %d -T tight -o %p %i")) + (dvisvgm + :programs ("latex" "dvisvgm" "gs") + :message "you needed to install latex, dvisvgm and ghostscript." + :use-xcolor t + :image-input (dvi xdv) + :image-output svg + :image-size-adjust (1.7 . 1.5) + :latex-compiler ("latex -interaction nonstopmode -output-directory %o %t") + :image-converter ("dvisvgm %i -n -b min -c %s -o %p")) + (imagemagick + :programs ("latex" "convert" "gs") + :message "you need to install latex, imagemagick and ghostscript." + :use-xcolor t + :image-input pdf + :image-output png + :image-size-adjust (1.0 . 1.0) + :latex-compiler ("latex -interaction nonstopmode -output-directory %o %t") + :image-converter ("convert -density %d -trim -antialias %i -quality 100 %p"))) + "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. + + :name symbol, the process setting name. + :inherit symbol, inhert options from an exist process setting. + :programs list of strings, required programs. + :message string, message it when required programs can't be found. + :image-input symbol, input file type, for example: dvi. + :image-output symbol, output file type, for example: png. + :use-xcolor boolean, if set to `t', LaTeX \"xcolor\" macro is used + to deal with background and foreground color of image, + if set to `nil', dvipng style background and foregroud color + format are generated; you should used them in command options + with special string: \"%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 backend 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. If set to `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 string, latex snippet file's header, if set to `nil', + the return value of `org-create-formula--latex-header' will be + used, which is controled `org-format-latex-header', + `org-latex-default-packages-alist' and `org-latex-packages-alist'. + :latex-compiler list of latex commands, each of them will be given to the shell + as a command. the special strings, %t, %b and %o, will be replaced + to according value before commands called. + :image-converter list of image converter command strings, each of them will be + given to the shell as a command. the following special strings, + will be replaced to according value before commands called. + +Special strings used by `:image-converter' and `:latex-compiler': + +1. %F foreground +2. %B background +3. %d dpi, which is used to adjust image size by + some backend's command. +4. %s the image size scale ratio, which is used to + adjust image size by some backend's command. +5. %t tex file name. +6. %i input file name of image converter. +7. %p output file name of image converter. +8. %b base name of input file +9. %o the base directory of input file." + :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-preview-latex-image-directory "25.1") + +(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 @@ -18996,9 +19084,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 +19097,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 +19181,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-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)) @@ -19139,8 +19228,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 +19237,21 @@ 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))) + (inherit-processing-info + (cdr (assq (plist-get processing-info :inherit) + org-preview-latex-process-alist))) + (inherit-processing-info + (if (or (plist-get inherit-processing-info :inherit) + (eq (plist-get processing-info :inherit) type)) + (progn (error "'%s' inherit an invalid process setting." processing-type) nil) + inherit-processing-info)) + (face (face-at-point)) ;; Get the colors from the face at point. (fg (let ((color (plist-get org-format-latex-options @@ -19172,9 +19271,12 @@ 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) + (plist-get inherit-processing-info :image-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 +19298,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 +19307,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 +19317,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 +19415,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 +19445,204 @@ 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." +(defun org-create-formula-image (string tofile options buffer &optional type) + "Create an image from LaTeX source using external processes. + +The external processes are defined in `org-preview-latex-process-alist'." (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) - (temp-directory) - temporary-file-directory)) + (let* ((type (or type 'dvipng)) + (processing-info + (cdr (assq type org-preview-latex-process-alist))) + (inherit-processing-info + (cdr (assq (plist-get processing-info :inherit) + org-preview-latex-process-alist))) + (inherit-processing-info + (if (or (plist-get inherit-processing-info :inherit) + (eq (plist-get processing-info :inherit) type)) + (progn (error "'%s' inherit an invalid process setting." type) nil) + inherit-processing-info)) + (programs + (or (plist-get processing-info :programs) + (plist-get inherit-processing-info :programs))) + (error-message + (or (plist-get processing-info :message) + (plist-get inherit-processing-info :message))) + (use-xcolor + (or (plist-get processing-info :use-xcolor) + (plist-get inherit-processing-info :use-xcolor))) + (image-input-types + (or (plist-get processing-info :image-input) + (plist-get inherit-processing-info :image-input))) + (image-output-type + (or (plist-get processing-info :image-output) + (plist-get inherit-processing-info :image-output))) + (post-clean (or (plist-get processing-info :post-clean) + (plist-get inherit-processing-info :post-clean) + '(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log" + ".svg" ".png" ".jpg" ".jpeg" ".out"))) + (latex-header (or (plist-get processing-info :latex-header) + (plist-get inherit-processing-info :latex-header) + (org-create-formula--latex-header))) + (latex-compiler + (or (plist-get processing-info :latex-compiler) + (plist-get inherit-processing-info :latex-compiler))) + (image-converter + (or (plist-get processing-info :image-converter) + (plist-get inherit-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)))) + (image-output-file + (format "%s.%s" texfilebase image-output-type)) + (font-height (face-attribute 'default :height nil)) + (image-size-adjust (or (plist-get processing-info :image-size-adjust) + (plist-get inherit-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*")) + image-input-file) + (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)))) + + (setq image-input-file + (org-compile-file + texfile image-input-types latex-compiler log-buf + (format "Please adjust '%s' part in `org-preview-latex-process-alist'." type) + `((?t . ,(shell-quote-argument texfile)) + (?b . ,(shell-quote-argument texfilebase)) + (?o . ,(shell-quote-argument tmpdir))))) + + (setq image-output-file + (org-compile-file + image-input-file image-output-type image-converter log-buf + (format "Please adjust '%S' part in `org-preview-latex-process-alist'." type) + `((?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)))) + (?t . ,(shell-quote-argument texfile)) + (?i . ,(shell-quote-argument image-input-file)) + (?p . ,(shell-quote-argument image-output-file)) + (?b . ,(shell-quote-argument texfilebase)) + (?o . ,(shell-quote-argument tmpdir))))) + + (when (file-exists-p image-output-file) + (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-compile-file (source extensions process + &optional log-buffer message spec) + "Compile a SOURCE file using PROCESS. + +PROCESS is either a function or a list of shell commands, as +strings. + +If PROCESS is a function, it is called with a single argument: +SOURCE file. It must create a file with the same base name and +directory as SOURCE, but using an extension belong EXTENSIONS. + +If it is a list of commands, each of them is called using +`shell-command'. By default, in each command, %b, %f and %o are +replaced, respectively, with SOURCE base name, SOURCE full name +and SOURCE directory. It is possible, however, to use different +place-holders by specifying them in optional argument SPEC. In +this case, SPEC should be an alist (CHARACTER REPLACEMENT-STRING). + +When PROCESS is a list of commands, optional argument LOG-BUFFER +can be set to a buffer or a buffer name. `shell-command' then +uses it as an output buffer, which may be used for collecting +errors. + +`default-directory' is set to SOURCE directory during the whole +process. + +Return output file or raise suggest MESSAGE if it wasn't generated +upon executing PROCESS." + (let* ((base-name (file-name-sans-extension (file-name-nondirectory source))) + (full-name (file-truename source)) + (output-dir (file-name-directory source)) + ;; Properly set working directory for compilation. + (default-directory (if (file-name-absolute-p source) + (file-name-directory full-name) + default-directory)) + (extensions (if (consp extensions) + extensions + (list extensions))) + (time (current-time))) + (save-window-excursion + (pcase process + ((pred functionp) + (funcall process (shell-quote-argument source))) + ((pred consp) + (let ((resize-mini-windows nil) + (log-buffer (and log-buffer (get-buffer-create log-buffer))) + (spec (or spec `((?b ,(shell-quote-argument base-name)) + (?f ,(shell-quote-argument full-name)) + (?o ,(shell-quote-argument output-dir)))))) + (dolist (command process) + (shell-command (format-spec command spec) log-buffer)))) + (_ (error (format "No valid command to process %S. %s" source message)))) + + ;; Check for process failure. + (let* ((output-files + (mapcar (lambda (ext) + (format "%s%s.%s" output-dir base-name ext)) + extensions)) + (files-string + (format "%s%s.%s" output-dir base-name + (mapconcat #'symbol-name extensions "|"))) + output-file) + (dolist (file output-files) + (when (file-exists-p file) + (setq output-file file) + (setq output-files nil))) + (when (or (not output-file) + ;; Only compare times up to whole seconds as some + ;; file-systems (e.g. HFS+) do not retain any finer + ;; granularity. + (time-less-p (cl-subseq (nth 5 (file-attributes output-file)) 0 2) + (cl-subseq time 0 2))) + (error (format "File %S wasn't produced. %s" files-string message))) + 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..0e3d266 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-preview-latex-image-directory) (file-name-sans-extension (file-name-nondirectory bfn))) cache-dir (file-name-directory bfn)) @@ -2798,10 +2801,10 @@ 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) + ((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)) @@ -2819,10 +2822,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) + ((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)) -- 2.1.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: (V8) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-18 6:30 ` (V8) " Feng Shu @ 2016-05-19 8:22 ` Nicolas Goaziou 2016-05-19 9:18 ` tumashu 0 siblings, 1 reply; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-19 8:22 UTC (permalink / raw) To: Feng Shu; +Cc: orgmode-devel Hello, "Feng Shu" <tumashu@163.com> writes: > I have rebase my patch to new function org-compile-file, the v8 patch is > very different with the earlier version, it is more simpler i think, > please comment again, thanks for your help! Thank you. I added `org-compile-file' to master branch and incorporated some of you suggestions. Beware, however, that there are some differences with the version you're using here. In particular, 1. the order of arguments is different; 2. %b, %f, and %o are always replaced in commands, no need to specify them again when using argument SPEC; 3. extension argument is a string, not a symbol or a list of symbols. By the way, I don't understand why you do need to provide a list of extensions. The extension argument is used to check if the process actually succeeded, but the process itself can create as many files as it sees fit. Some additional comments follow. > + (dvisvgm > + :programs ("latex" "dvisvgm" "gs") > + :message "you needed to install latex, dvisvgm and ghostscript." > + :use-xcolor t > + :image-input (dvi xdv) Per above, it is either dvi or xdv > + "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. > + > + :name symbol, the process setting name. > + :inherit symbol, inhert options from an exist process setting. I suggest to drop the property above. It is only partially implemented (e.g., you cannot inherit from an inherited process), it complicates code, and I don't think it is terribly useful overall. > + :image-input symbol, input file type, for example: dvi. > + :image-output symbol, output file type, for example: png. symbol -> string > + :use-xcolor boolean, if set to `t', LaTeX \"xcolor\" macro is used > + to deal with background and foreground color of image, > + if set to `nil', dvipng style background and foregroud color > + format are generated; you should used them in command options > + with special string: \"%F\" and \"%B\". when non-nil, `LaTeX' \"xcolor\"... color of image. Otherwise, dvipng style... 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 latex -> LaTeX > + size showed in buffer and the cdr element is for html file. html -> HTML > + This option is only useful for backend 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. If set to `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 string, latex snippet file's header, if set to `nil', latex -> `LaTeX' > + the return value of `org-create-formula--latex-header' will be > + used, which is controled `org-format-latex-header', > + `org-latex-default-packages-alist' and `org-latex-packages-alist'. No need to reference an internal function: the return value 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, each of them will be given to the shell > + as a command. the special strings, %t, %b and %o, will be replaced > + to according value before commands called. as a command. Place-holders "%t", "%b" and "%o" are replaced with values defined below. > + :image-converter list of image converter command strings, each of them will be > + given to the shell as a command. the following special strings, > + will be replaced to according value before commands called. each of them is given to the shell as a command and support any of the following place-holders defined below. > +Special strings used by `:image-converter' and `:latex-compiler': Place-holders used by... > +5. %t tex file name. Couldn't you use %f so as to be compatible with default place-holders? > -(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." You need to explain IMAGETYPE in docstring, e.g., Argument IMAGETYPE is the extension of the displayed image, as a symbol. It defaults to "png". > + (let* ((processing-info > + (cdr (assq processing-type org-preview-latex-process-alist))) > + (inherit-processing-info > + (cdr (assq (plist-get processing-info :inherit) > + org-preview-latex-process-alist))) > + (inherit-processing-info > + (if (or (plist-get inherit-processing-info :inherit) > + (eq (plist-get processing-info :inherit) type)) > + (progn (error "'%s' inherit an invalid process setting." processing-type) nil) > + inherit-processing-info)) Again, I suggest to drop the part about inheriting process info. If you think it is a must-have, then it should be factored out of this function and from `org-create-formula-image', as there is too much code duplication. It should also support inheriting from inherited processes. > + (face (face-at-point)) > ;; Get the colors from the face at point. > (fg > (let ((color (plist-get org-format-latex-options > @@ -19172,9 +19271,12 @@ 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) > + (plist-get inherit-processing-info :image-output) > + 'png)) Ditto. > +(defun org-create-formula-image (string tofile options buffer &optional type) > + "Create an image from LaTeX source using external processes. > + > +The external processes are defined in `org-preview-latex-process-alist'." Ideally, each argument need to be explained in the docstring. I know the previous function didn't do that, but, if you can improve it, that's better. > (require 'ox-latex) > - (let* ((tmpdir (if (featurep 'xemacs) > - (temp-directory) > - temporary-file-directory)) > + (let* ((type (or type 'dvipng)) > + (processing-info > + (cdr (assq type org-preview-latex-process-alist))) > + (inherit-processing-info > + (cdr (assq (plist-get processing-info :inherit) > + org-preview-latex-process-alist))) > + (inherit-processing-info > + (if (or (plist-get inherit-processing-info :inherit) > + (eq (plist-get processing-info :inherit) type)) > + (progn (error "'%s' inherit an invalid process setting." type) nil) > + inherit-processing-info)) > + (programs > + (or (plist-get processing-info :programs) > + (plist-get inherit-processing-info :programs))) > + (error-message > + (or (plist-get processing-info :message) > + (plist-get inherit-processing-info :message))) > + (use-xcolor > + (or (plist-get processing-info :use-xcolor) > + (plist-get inherit-processing-info :use-xcolor))) > + (image-input-types > + (or (plist-get processing-info :image-input) > + (plist-get inherit-processing-info :image-input))) > + (image-output-type > + (or (plist-get processing-info :image-output) > + (plist-get inherit-processing-info :image-output))) > + (post-clean (or (plist-get processing-info :post-clean) > + (plist-get inherit-processing-info :post-clean) > + '(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log" > + ".svg" ".png" ".jpg" ".jpeg" ".out"))) > + (latex-header (or (plist-get processing-info :latex-header) > + (plist-get inherit-processing-info :latex-header) > + (org-create-formula--latex-header))) > + (latex-compiler > + (or (plist-get processing-info :latex-compiler) > + (plist-get inherit-processing-info :latex-compiler))) > + (image-converter > + (or (plist-get processing-info :image-converter) > + (plist-get inherit-processing-info :image-converter))) This is the repetitive pattern I was talking about. > + (setq image-input-file > + (org-compile-file > + texfile image-input-types latex-compiler log-buf > + (format "Please adjust '%s' part in `org-preview-latex-process-alist'." type) > + `((?t . ,(shell-quote-argument texfile)) > + (?b . ,(shell-quote-argument texfilebase)) > + (?o . ,(shell-quote-argument tmpdir))))) As explained above, beware the order of arguments and the type of IMAGE-OUTPUT-TYPE. Also, I don't think you need to provide SPEC, as it is the default, with a slight change ?t is actually ?f. > + (setq image-output-file > + (org-compile-file > + image-input-file image-output-type image-converter log-buf > + (format "Please adjust '%S' part in `org-preview-latex-process-alist'." type) > + `((?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)))) > + (?t . ,(shell-quote-argument texfile)) > + (?i . ,(shell-quote-argument image-input-file)) > + (?p . ,(shell-quote-argument image-output-file)) > + (?b . ,(shell-quote-argument texfilebase)) > + (?o . ,(shell-quote-argument tmpdir))))) As explained above, beware the order of arguments and the type of IMAGE-OUTPUT-TYPE. Also, you don't need to provide ?o, ?b and probably ?t in SPEC. > + (when (file-exists-p image-output-file) IMAGE-OUTPUT-FILE is guaranteed to exist. Otherwise, `org-compile-file' returns an error. > +(defun org-compile-file (source extensions process > + &optional log-buffer message spec) You can remove this, as it is integrated in master. > -`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. Process types are mostly hard-coded, this is a reason why I don't think inheritance is terribly useful: you almost always want to modify existing processes, not create new ones. I think we're getting close to the merge. Regards, -- Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V8) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-19 8:22 ` Nicolas Goaziou @ 2016-05-19 9:18 ` tumashu 2016-05-19 10:32 ` Nicolas Goaziou 0 siblings, 1 reply; 25+ messages in thread From: tumashu @ 2016-05-19 9:18 UTC (permalink / raw) To: Nicolas Goaziou; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 298 bytes --] `((?b . ,(shell-quote-argument base-name)) (?f . ,(shell-quote-argument full-name)) (?o . ,(shell-quote-argument out-dir)))))) What about add a spec to output-file, some commands need this information. I will edit my diff tonight and sent to org-mode mailling list as far as possible. [-- Attachment #2: Type: text/html, Size: 616 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V8) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-19 9:18 ` tumashu @ 2016-05-19 10:32 ` Nicolas Goaziou 2016-05-19 14:01 ` (V9) " Feng Shu 0 siblings, 1 reply; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-19 10:32 UTC (permalink / raw) To: tumashu; +Cc: emacs-orgmode tumashu <tumashu@163.com> writes: > `((?b . ,(shell-quote-argument base-name)) > (?f . ,(shell-quote-argument full-name)) > (?o . ,(shell-quote-argument out-dir)))))) > > > What about add a spec to output-file, some commands need this > information. I'm not sure to understand. What information do you need? Regards, ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V9) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-19 10:32 ` Nicolas Goaziou @ 2016-05-19 14:01 ` Feng Shu 2016-05-21 9:38 ` Nicolas Goaziou 0 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-19 14:01 UTC (permalink / raw) To: emacs-orgmode; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 193 bytes --] Thank you for patiently help, this is v9 patch, inhert feature is removed from this patch, I need to think it over, maybe submit patch in the future. please comment again, thanks again :-) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 31697 bytes --] From e18b7a4430ff90d6bcb828e3898ef25c61aba4bd Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Tue, 17 May 2016 21:24:35 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular * 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): 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 | 43 ++++--- lisp/org.el | 383 +++++++++++++++++++++++++++++++------------------------- lisp/ox-html.el | 43 +++---- 3 files changed, 259 insertions(+), 210 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 025baaa..54f3c5a 100644 --- a/doc/org.texi +++ b/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 diff --git a/lisp/org.el b/lisp/org.el index 93d66ad..9b1fa69 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3980,21 +3980,110 @@ 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'." :group 'org-latex :version "24.1" - :type '(choice - (const :tag "dvipng" dvipng) - (const :tag "imagemagick" imagemagick))) + :type '(symbol :tag "LaTeX preview process" :value dvipng)) + +(defcustom org-preview-latex-process-alist + '((dvipng + :programs ("latex" "dvipng" "gs") + :document "Compile a LaTeX fragment file to dvi file, + then convert the dvi file to png file using dvipng." + :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") + :document "Compile a LaTeX fragment file to a dvi file, then convert + the dvi file to svg file using dvisvgm program." + :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") + :document "Compile a LaTeX fragment file to pdf file, then use imagemagick + to convert the pdf file to png file." + :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"))) + "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. + + :name symbol, the process name. + :programs list of strings, required programs. + :document string, the process document. + :message string, message it when required programs can't be found. + :image-input-type string, input file type of image converter, for example: \"dvi\". + :image-output-type string, output file type of image converter, for example: \"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 string, the `LaTeX' header of 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, each of them will be given to the shell + as a command. Place-holders \"%t\", \"%b\" and \"%o\" are replaced + with values defined below. + :image-converter list of image converter command strings, each of them is given to + the shell as a command and support any of the following place-holders + defined below. + +Place-holders used by `:image-converter' and `:latex-compiler': + +1. %i input file name. +2. %b base name of input file. +3. %o base directory of input file. + +Place-holders only used by `:image-converter': + +1. %F foreground of image +2. %B background of image +3. %D dpi, which is used to adjust image size by some + processing commands. +4. %S the image size scale ratio, which is used to + adjust image size by some processing commands." + :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-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 @@ -18997,9 +19086,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 @@ -19009,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. @@ -19093,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-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)) @@ -19140,8 +19232,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) @@ -19149,11 +19241,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 @@ -19173,9 +19267,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 @@ -19197,7 +19292,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 @@ -19206,7 +19301,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")) @@ -19216,8 +19311,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) @@ -19314,31 +19409,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)) @@ -19369,133 +19439,104 @@ 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 will be saved to a temporary `LaTeX' file, +then converted to a image file by process PROCESSING-TYPE defined +in `org-preview-latex-process-alist', the image file generated will +eventually be moved to TOFILE. + +The OPTIONS control the size, foreground color and background color +of image generated. + +When BUFFER non-nil, this function is used to `LaTeX' previewing, +otherwise, used to deal with LaTeX snippts showed in HTML file." + (let* ((processing-type (or processing-type 'dvipng)) + (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 generate image. + image-input-file image-output-file) + (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)))) + + (setq image-input-file + (org-compile-file + texfile latex-compiler image-input-type + (format "Please adjust '%s' part of `org-preview-latex-process-alist'." processing-type) + log-buf)) + + (setq image-output-file + (org-compile-file + image-input-file image-converter image-output-type + (format "Please adjust '%S' part of `org-preview-latex-process-alist'." processing-type) + 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. diff --git a/lisp/ox-html.el b/lisp/ox-html.el index b188c38..530109e 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -816,24 +816,21 @@ 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'." +1. t Synonym for `mathjax'. +2. nil Ignore math snippets. +3. `verbatim' Keep everything in verbatim +4. `mathjax' Do MathJax preprocessing and arrange for MathJax.js to + be loaded. +5. other symbol Any symbol of process 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 +2756,10 @@ 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'. +for example: `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,10 +2795,10 @@ 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) + ((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)) @@ -2819,10 +2816,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) + ((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)) -- 2.1.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: (V9) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-19 14:01 ` (V9) " Feng Shu @ 2016-05-21 9:38 ` Nicolas Goaziou 2016-05-21 12:22 ` Feng Shu 0 siblings, 1 reply; 25+ messages in thread From: Nicolas Goaziou @ 2016-05-21 9:38 UTC (permalink / raw) To: Feng Shu; +Cc: emacs-orgmode Hello, "Feng Shu" <tumashu@163.com> writes: > From e18b7a4430ff90d6bcb828e3898ef25c61aba4bd Mon Sep 17 00:00:00 2001 > From: Feng Shu <tumashu@163.com> > Date: Tue, 17 May 2016 21:24:35 +0800 > Subject: [PATCH] New feature: Use dvisvgm to preview latex formular It looks good. I applied it with minor tweak to docstrings. I also made use of `org-preview-latex-default-process', which was defined but not used in the patch. Thank you for all this work. BTW, could you provide an entry for ORG-NEWS about it? User visible changes are variables being renamed an, obviously, the new feature. Regards, -- Nicolas Goaziou ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V9) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-21 9:38 ` Nicolas Goaziou @ 2016-05-21 12:22 ` Feng Shu 2016-05-21 13:35 ` Rasmus 0 siblings, 1 reply; 25+ messages in thread From: Feng Shu @ 2016-05-21 12:22 UTC (permalink / raw) To: emacs-orgmode; +Cc: Feng Shu Nicolas Goaziou <mail@nicolasgoaziou.fr> writes: > Hello, > > "Feng Shu" <tumashu@163.com> writes: > >> From e18b7a4430ff90d6bcb828e3898ef25c61aba4bd Mon Sep 17 00:00:00 2001 >> From: Feng Shu <tumashu@163.com> >> Date: Tue, 17 May 2016 21:24:35 +0800 >> Subject: [PATCH] New feature: Use dvisvgm to preview latex formular > > It looks good. I applied it with minor tweak to docstrings. I also made > use of `org-preview-latex-default-process', which was defined but not > used in the patch. > > Thank you for all this work. Thank you for you help too :-) The next work i want to do is: 1. org-latex-pdf-process -> org-latex-pdf-default-process 2. Add new variable org-latex-pdf-process-alist 3. Add #+LATEX_PDF_PROCESS setting I am a member of emacs community in chinese, many org-mode latex beginners will ask me: "How to export org to pdf by latex?", this problem is annoying, so i deside to write a package: ox-latex-chinese and tell them: "Install org-latex-chinese package!" But, it is a diffcult work to convert my own org latex configure to a well organized emacs package, setq nightmare!. The above suggestion is a try to solve this problem. Any suggestion? if you agree, i will code the patch. > > BTW, could you provide an entry for ORG-NEWS about it? User visible > changes are variables being renamed an, obviously, the new feature. I can write an entry, but for my poor English, reviewing it may need more time than writing a new, :-) > > Regards, -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (V9) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-21 12:22 ` Feng Shu @ 2016-05-21 13:35 ` Rasmus 0 siblings, 0 replies; 25+ messages in thread From: Rasmus @ 2016-05-21 13:35 UTC (permalink / raw) To: emacs-orgmode Hi Feng, Thanks for the patches. "Feng Shu" <tumashu@163.com> writes: > 1. org-latex-pdf-process -> org-latex-pdf-default-process > 2. Add new variable org-latex-pdf-process-alist What do you have in mind? I assume it’s something more than just ripping out the :type part of org-latex-pdf-process. > 3. Add #+LATEX_PDF_PROCESS setting Is this the same as #+latex_compiler, which is used for setting the process to pdflatex, xelatex or lualatex? > I am a member of emacs community in chinese, many org-mode latex > beginners will ask me: "How to export org to pdf by latex?", > this problem is annoying, so i deside to write a package: > ox-latex-chinese and tell them: "Install org-latex-chinese package!" It sounds like #+language support should be extended. A basic Chinese document with org doesn’t seem that hard. With ttf-hannom, all I need is this: #+latex_compiler: xelatex #+latex_header: \usepackage{xeCJK} #+latex_header: \setCJKmainfont{HAN NOM A} 文章内容 Rasmus -- Don't slow down Johnny, leave the Cadillac runnin' ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: (version 4) [PATCH] New feature: Use dvisvgm to preview latex formular 2016-05-15 6:02 ` (version 3) " Feng Shu 2016-05-15 12:14 ` Feng Shu @ 2016-05-15 12:16 ` Feng Shu 1 sibling, 0 replies; 25+ messages in thread From: Feng Shu @ 2016-05-15 12:16 UTC (permalink / raw) To: orgmode-devel; +Cc: Feng Shu [-- Attachment #1: Type: text/plain, Size: 80 bytes --] "Feng Shu" <tumashu@163.com> writes: v4 patch, add some minor change based v3 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-New-feature-Use-dvisvgm-to-preview-latex-formular.patch --] [-- Type: text/x-diff, Size: 39465 bytes --] From 010baf028bb6dbb706f5abb9f99de0552235f2af Mon Sep 17 00:00:00 2001 From: Feng Shu <tumashu@163.com> Date: Sat, 14 May 2016 22:42:53 +0800 Subject: [PATCH] New feature: Use dvisvgm to preview latex formular Tester should set like below: (setq org-latex-create-formula-image-program 'dvisvgm) (setq org-latex-pdf-process '(:fetcher my-org-latex-pdf-process-format)) (defun my-org-latex-pdf-process-format (&optional texfile snippet caller-info) (princ (format "The caller's info: %s" caller-info)) (cond (snippet '("latex -interaction nonstopmode -output-directory %o %f")) (t '("%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f" "%latex -interaction nonstopmode -output-directory %o %f")))) * ox-latex.el (org-latex-pdf-process): Add a new config method, :fetcher. (org-latex-compile): Add a new optional argument: caller-info, which used to record the caller's 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 | 366 +++++++++++++++++++++++++++++++------------------------ lisp/ox-html.el | 28 +++-- lisp/ox-latex.el | 161 +++++++++++++++--------- 4 files changed, 354 insertions(+), 240 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 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 @@ -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 -@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 +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-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 @pxref{@LaTeX{} fragments}), @@ -11713,6 +11713,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 @@ -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 +@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 @@ -12908,6 +12914,7 @@ and open the formula file with the system-registered application. @end table @cindex dvipng +@cindex 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 +@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 diff --git a/lisp/org.el b/lisp/org.el index f45d5d0..86d9c95 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -3985,15 +3985,97 @@ 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 + :scale-adjust 2.0 + :org-latex-compile nil + :need-clean (".dvi" ".tex" ".aux" ".log" ".png" ".out") + :commands (("latex" "-interaction" "nonstopmode" "-output-directory" "%temp-dir%" "%tex-file%") + ("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 + :scal-adjust 2.0 + :org-latex-compile t + :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 + :scale-adjust 2.0 + :org-latex-compile t + :post-clean (".pdf" ".tex" ".aux" ".log" ".png" ".out") + :commands (("convert" "-density" "%dpi%" "-trim" "-antialias" "%input-file%" "-quality" "100" "%output-file%")))) + "Org mode can use some external commands to generate TeX snippet's image for +proviewing or inserting to html file, for example: dvipng, dvisvgm or imagemagick +this variable tell `org-create-formula-image' how to use the above command. + + :class symbol, this setting may useful in future. + :name string, the backend's name. + :programs string-list, 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 it set to 'latex, latex xcolor macro will be used + to deal with background and fontground color of image, 'divpng + is only useful to dvipng backend. + :scale-adjust number, adjust image's size, only useful for backend developers. + :org-latex-compile boolean, if set it to t, `org-create-formula-image' will use + `org-latex-compile' to compile tex file, when set it to nil, + user need to set latex command in `:commands'. + :need-clean string-list, the files matched its elements will be cleaned up + after image generated. + :commands list, the commands setting, the following special strings, + will be replaced to according value before command called. + + 1. %fg% fontground + 2. %bg% background + 3. %dpi% dpi, used to adjust image size by some backend. + 4. %scale% scale, used to adjust image size by some backend. + 5. %tex-file% tex file name. + 6. %input-file% input file name. + 7. %output-file% output file name. + 8. %file-base% input file name's base name. + 9. %temp-dir% temporary dir used by `org-create-formula-image'. + + For example, %tmpdir% may be replaced to /tmp in linux." + :group 'org-latex + :version "24.1" + :type 'alist) + +(defalias 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory) +(make-obsolete 'org-latex-preview-ltxpng-directory 'org-latex-preview-ltximg-directory + "Org mode version 9.0") +(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 +19078,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 +19091,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 +19175,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 +19206,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 +19223,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 +19232,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 (assoc 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 +19259,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 +19284,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 +19293,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 +19303,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 +19401,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 +19431,124 @@ 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." +(declare-function org-latex-compile "ox-latex" (texfile &optional snippet)) +(defun org-create-formula-image (string tofile options buffer &optional type) + "Create an image from LaTeX source using program." (require 'ox-latex) - (let* ((tmpdir (if (featurep 'xemacs) + (let* ((type (or type 'dvipng)) + (backend-info + (cdr (assoc 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)) + (scale-adjust (or (plist-get backend-info :scale-adjust) 1.0)) + (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 (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 + (input-file (format "%s.%s" texfilebase input-type)) + (output-file (format "%s.%s" texfilebase output-type)) + (scale (* scale-adjust + (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." - (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)) + "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" scale)) + ("%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-pdf-process'." texfile) + (message "`org-latex-compile' can't compile %s, please adjust `org-latex-pdf-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))) + ;; (princ args-alist) + ;; (princ 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..6a84a35 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 "ltximg/" (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..ccbd348 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1143,7 +1143,32 @@ 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 plist, the first element of the +plist is :fetcher and the second is a function, for example: + + (setq org-latex-pdf-process + '(:fetcher my-org-latex-pdf-process-format)) + + (defun my-org-late-pdf-process-formt (&optional texfile snippet caller-info) + (cond + (snippet '(\"latex -interaction nonstopmode -output-directory %o %f\")) + (t '(\"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\" + \"%latex -interaction nonstopmode -output-directory %o %f\")))) + +`org-latex-compile' will call the second function, then use the +returned command list. + +the function has three optional arguments: texfile, snippet and +caller-info, when `org-latex-compile' compile a tex snippet for +previewing, snippet will set to t and client-info argument will +record the infomation of org-latex-compile's caller, for example: + + (:name dvisvgm :need dvi) + +This information can be used to select tex command." :group 'org-export-pdf :type '(choice (repeat :tag "Shell command sequence" @@ -3515,7 +3540,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 caller-info) "Compile a TeX file. TEXFILE is the name of the file being compiled. Processing is @@ -3525,6 +3550,16 @@ 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. +By default, `org-latex-compile' will compile `texfile' to a pdf +file, but when we compile a tex snippet, the desired output may +dvi or xdv file instead of pdf file, snippet-generate-function +can tell `org-latex-compile' the infomation with the argument +CALLER-INFO, then org-latex-compile can find proper commands +with this infomation, this argument is a property list, for +example: + + (:caller dvisvgm :need dvi) + 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 +3579,72 @@ 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* ((fetcher-function (plist-get org-latex-pdf-process :fetcher)) + (latex-pdf-process + (if fetcher-function + (if (functionp fetcher-function) + (funcall fetcher-function + (shell-quote-argument texfile) snippet caller-info) + (error "`org-latex-pdf-process' set an invalid fetcher function.")) + org-latex-pdf-process))) + (save-window-excursion + (cond + ;; A function is provided: Apply it. + ((functionp latex-pdf-process) + (funcall 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 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 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))) + ;; 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. + pdffile))))) (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. -- 2.1.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
end of thread, other threads:[~2016-05-21 13:35 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-05-14 6:30 [PATCH] New feature: Use dvisvgm to preview latex formular Feng Shu 2016-05-14 8:47 ` numbchild 2016-05-14 14:56 ` Feng Shu 2016-05-15 2:27 ` Feng Shu 2016-05-15 6:02 ` (version 3) " Feng Shu 2016-05-15 12:14 ` Feng Shu 2016-05-15 22:32 ` Nicolas Goaziou 2016-05-16 5:32 ` Feng Shu 2016-05-16 13:18 ` Nicolas Goaziou 2016-05-16 15:06 ` tumashu 2016-05-16 5:33 ` Feng Shu 2016-05-16 13:19 ` Nicolas Goaziou 2016-05-16 12:05 ` (v6) " Feng Shu 2016-05-16 21:17 ` Nicolas Goaziou 2016-05-16 22:17 ` tumashu 2016-05-17 1:15 ` tumashu 2016-05-18 6:30 ` (V8) " Feng Shu 2016-05-19 8:22 ` Nicolas Goaziou 2016-05-19 9:18 ` tumashu 2016-05-19 10:32 ` Nicolas Goaziou 2016-05-19 14:01 ` (V9) " Feng Shu 2016-05-21 9:38 ` Nicolas Goaziou 2016-05-21 12:22 ` Feng Shu 2016-05-21 13:35 ` Rasmus 2016-05-15 12:16 ` (version 4) " Feng Shu
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.