Release Emacs Muse 3.03!
[muse-el.git] / lisp / muse-latex2png.el
blob227036f9847411bebe5f13c1549f7685a9f69326
1 ;; muse-latex2png.el --- generate PNG images from inline LaTeX code
3 ;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
5 ;; Author: Michael Olson <mwolson@gnu.org>
6 ;; Created: 12-Oct-2005
8 ;; This file is part of Emacs Muse. It is not part of GNU Emacs.
10 ;; Emacs Muse is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; Emacs Muse is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with Emacs Muse; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;;; Commentary:
27 ;; This was taken from latex2png.el, by Ganesh Swami <ganesh AT
28 ;; iamganesh DOT com>, which was made for emacs-wiki. It has since
29 ;; been extensively rewritten for Muse.
31 ;;; To do
33 ;; Remove stale image files. This could be done by making a function
34 ;; for `muse-before-publish-hook' that deletes according to
35 ;; (muse-page-name).
37 ;;; Code
39 (require 'muse-publish)
41 (defgroup muse-latex2png nil
42 "Publishing LaTeX formulas as PNG files."
43 :group 'muse-publish)
45 (defcustom muse-latex2png-img-dest "./latex"
46 "The folder where the generated images will be placed.
47 This is relative to the current publishing directory."
48 :type 'string
49 :group 'muse-latex2png)
51 (defcustom muse-latex2png-scale-factor 2.5
52 "The scale factor to be used for sizing the resulting LaTeX output."
53 :type 'number
54 :group 'muse-latex2png)
56 (defcustom muse-latex2png-fg "Black"
57 "The foreground color."
58 :type 'string
59 :group 'muse-latex2png)
61 (defcustom muse-latex2png-bg "Transparent"
62 "The background color."
63 :type 'string
64 :group 'muse-latex2png)
66 (defcustom muse-latex2png-template
67 "\\documentclass{article}
68 \\usepackage{fullpage}
69 \\usepackage{amssymb}
70 \\usepackage[usenames]{color}
71 \\usepackage{amsmath}
72 \\usepackage{latexsym}
73 \\usepackage[mathscr]{eucal}
74 %preamble%
75 \\pagestyle{empty}
76 \\begin{document}
77 {%code%}
78 \\end{document}\n"
79 "The LaTeX template to use."
80 :type 'string
81 :group 'muse-latex2png)
83 (defun muse-latex2png-move2pubdir (file prefix pubdir)
84 "Move FILE to the PUBDIR folder.
86 This is done so that the resulting images do not clutter your
87 main publishing directory.
89 Old files with PREFIX in the name are deleted."
90 (when file
91 (if (file-exists-p file)
92 (progn
93 (unless (file-directory-p pubdir)
94 (message "Creating latex directory %s" pubdir)
95 (make-directory pubdir))
96 (copy-file file (expand-file-name (file-name-nondirectory file)
97 pubdir)
99 (delete-file file)
100 (concat muse-latex2png-img-dest "/" (file-name-nondirectory file)))
101 (message "Cannot find %s!" file))))
103 (defun muse-latex2png (code prefix preamble)
104 "Convert the LaTeX CODE into a png file beginning with PREFIX.
105 PREAMBLE indicates extra packages and definitions to include."
106 (unless preamble
107 (setq preamble ""))
108 (unless prefix
109 (setq prefix "muse-latex2png"))
110 (let* ((tmpdir (cond ((boundp 'temporary-file-directory)
111 temporary-file-directory)
112 ((fboundp 'temp-directory)
113 (temp-directory))
114 (t "/tmp")))
115 (texfile (expand-file-name
116 (concat prefix "__" (format "%d" (abs (sxhash code))))
117 tmpdir))
118 (defalt-directory default-directory))
119 (with-temp-file (concat texfile ".tex")
120 (insert muse-latex2png-template)
121 (goto-char (point-min))
122 (while (search-forward "%preamble%" nil t)
123 (replace-match preamble nil t))
124 (goto-char (point-min))
125 (while (search-forward "%code%" nil t)
126 (replace-match code nil t)))
127 (setq default-directory tmpdir)
128 (call-process "latex" nil nil nil texfile)
129 (if (file-exists-p (concat texfile ".dvi"))
130 (progn
131 (shell-command-to-string
132 (concat "dvipng " texfile ".dvi -E"
133 " -fg " muse-latex2png-fg
134 " -bg " muse-latex2png-bg " -T tight"
135 " -x " (format "%s" (* muse-latex2png-scale-factor 1000))
136 " -y " (format "%s" (* muse-latex2png-scale-factor 1000))
137 " -o " texfile ".png"))
138 (if (file-exists-p (concat texfile ".png"))
139 (progn
140 (delete-file (concat texfile ".dvi"))
141 (delete-file (concat texfile ".tex"))
142 (delete-file (concat texfile ".aux"))
143 (delete-file (concat texfile ".log"))
144 (concat texfile ".png"))
145 (message "Failed to create png file")
146 nil))
147 (message (concat "Failed to create dvi file " texfile))
148 nil)))
150 (defun muse-latex2png-region (beg end attrs)
151 "Generate an image for the Latex code between BEG and END.
152 If a Muse page is currently being published, replace the given
153 region with the appropriate markup that displays the image.
154 Otherwise, just return the path of the generated image.
156 Valid keys for the ATTRS alist are as follows.
158 prefix: The prefix given to the image file.
159 preamble: Extra text to add to the Latex preamble.
160 inline: Display image as inline, instead of a block."
161 (let ((end-marker (set-marker (make-marker) (1+ end)))
162 (pubdir (expand-file-name
163 muse-latex2png-img-dest
164 (file-name-directory muse-publishing-current-output-path))))
165 (save-restriction
166 (narrow-to-region beg end)
167 (let* ((text (buffer-substring-no-properties beg end))
168 ;; the prefix given to the image file.
169 (prefix (cdr (assoc "prefix" attrs)))
170 ;; preamble (for extra options)
171 (preamble (cdr (assoc "preamble" attrs)))
172 ;; display inline or as a block
173 (display (car (assoc "inline" attrs))))
174 (when muse-publishing-p
175 (delete-region beg end)
176 (goto-char (point-min)))
177 (unless (file-directory-p pubdir)
178 (make-directory pubdir))
179 (let ((path (muse-latex2png-move2pubdir
180 (muse-latex2png text prefix preamble)
181 prefix pubdir)))
182 (when path
183 (when muse-publishing-p
184 (muse-insert-markup
185 (if (muse-style-derived-p "html")
186 (concat "<img src=\"" path
187 "\" alt=\"latex2png equation\" "
188 (if display (concat "class=\"latex-inline\"")
189 (concat "class=\"latex-display\""))
190 (if (muse-style-derived-p "xhtml")
191 " />"
192 ">")
193 (muse-insert-markup "<!-- " text "-->"))
194 (let ((ext (or (file-name-extension path) ""))
195 (path (muse-path-sans-extension path)))
196 (muse-markup-text 'image path ext))))
197 (goto-char (point-max)))
198 path))))))
200 (defun muse-publish-latex-tag (beg end attrs)
201 "If the current style is not Latex-based, generate an image for the
202 given Latex code. Otherwise, don't do anything to the region.
203 See `muse-latex2png-region' for valid keys for ATTRS."
204 (unless (assoc "prefix" attrs)
205 (setq attrs (cons (cons "prefix"
206 (concat "latex2png-" (muse-page-name)))
207 attrs)))
208 (if (muse-style-derived-p "latex")
209 (muse-publish-mark-read-only beg end)
210 (muse-latex2png-region beg end attrs)))
212 (defun muse-publish-math-tag (beg end)
213 "Surround the given region with \"$\" characters. Then, if the
214 current style is not Latex-based, generate an image for the given
215 Latex math code.
217 If 6 or more spaces come before the tag, surrouund the region
218 with the equivalent of \"$$\" instead, which causes the region to
219 be centered in the published output (among other things)."
220 (let* ((centered (and (re-search-backward
221 (concat "^[" muse-regexp-blank "]\\{6,\\}\\=")
222 nil t)
223 (prog1 t
224 (replace-match "")
225 (when (and (muse-style-derived-p "latex")
226 (not (bobp)))
227 (backward-char 1)
228 (if (bolp)
229 (delete-char 1)
230 (forward-char 1)))
231 (setq beg (point)))))
232 (tag-beg (if centered
233 (if (muse-style-derived-p "contex")
234 "$$" "\\[ ")
235 "$"))
236 (tag-end (if centered
237 (if (muse-style-derived-p "contex")
238 "$$" " \\]")
239 "$"))
240 (attrs (nconc (list (cons "prefix"
241 (concat "latex2png-" (muse-page-name))))
242 (if centered nil
243 '(("inline" . t))))))
244 (muse-insert-markup tag-beg)
245 (goto-char end)
246 (muse-insert-markup tag-end)
247 (if (muse-style-derived-p "latex")
248 (muse-publish-mark-read-only beg (point))
249 (muse-latex2png-region beg (point) attrs))))
251 ;;; Insinuate with muse-publish
253 (add-to-list 'muse-publish-markup-tags
254 '("latex" t t nil muse-publish-latex-tag)
257 (add-to-list 'muse-publish-markup-tags
258 '("math" t nil nil muse-publish-math-tag)
261 (provide 'muse-latex2png)
262 ;;; muse-latex2png.el ends here