##// END OF EJS Templates
make lib.latextools accept unicode...
Min RK -
Show More
@@ -1,23 +1,10 b''
1 1 # -*- coding: utf-8 -*-
2 """Tools for handling LaTeX.
2 """Tools for handling LaTeX."""
3 3
4 Authors:
5
6 * Brian Granger
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2010 IPython Development Team.
10 #
4 # Copyright (c) IPython Development Team.
11 5 # Distributed under the terms of the Modified BSD License.
12 #
13 # The full license is in the file COPYING.txt, distributed with this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19 6
20 from io import BytesIO
7 from io import BytesIO, open
21 8 from base64 import encodestring
22 9 import os
23 10 import tempfile
@@ -25,20 +12,17 b' import shutil'
25 12 import subprocess
26 13
27 14 from IPython.utils.process import find_cmd, FindCmdError
15 from IPython.config.application import Application
28 16 from IPython.config.configurable import SingletonConfigurable
29 from IPython.utils.traitlets import List, CBool, CUnicode
30 from IPython.utils.py3compat import bytes_to_str
31
32 #-----------------------------------------------------------------------------
33 # Tools
34 #-----------------------------------------------------------------------------
17 from IPython.utils.traitlets import List, Bool, Unicode
18 from IPython.utils.py3compat import cast_unicode, cast_unicode_py2 as u
35 19
36 20
37 21 class LaTeXTool(SingletonConfigurable):
38 22 """An object to store configuration of the LaTeX tool."""
39 23
40 24 backends = List(
41 CUnicode, ["matplotlib", "dvipng"],
25 Unicode, ["matplotlib", "dvipng"],
42 26 help="Preferred backend to draw LaTeX math equations. "
43 27 "Backends in the list are checked one by one and the first "
44 28 "usable one is used. Note that `matplotlib` backend "
@@ -51,7 +35,7 b' class LaTeXTool(SingletonConfigurable):'
51 35 # unicode pretty printing is used, you can use ["matplotlib"].
52 36 config=True)
53 37
54 use_breqn = CBool(
38 use_breqn = Bool(
55 39 True,
56 40 help="Use breqn.sty to automatically break long equations. "
57 41 "This configuration takes effect only for dvipng backend.",
@@ -63,7 +47,7 b' class LaTeXTool(SingletonConfigurable):'
63 47 "'breqn' will be automatically appended when use_breqn=True.",
64 48 config=True)
65 49
66 preamble = CUnicode(
50 preamble = Unicode(
67 51 help="Additional preamble to use when generating LaTeX source "
68 52 "for dvipng backend.",
69 53 config=True)
@@ -74,10 +58,10 b' def latex_to_png(s, encode=False, backend=None, wrap=False):'
74 58
75 59 Parameters
76 60 ----------
77 s : str
61 s : text
78 62 The raw string containing valid inline LaTeX.
79 63 encode : bool, optional
80 Should the PNG data bebase64 encoded to make it JSON'able.
64 Should the PNG data base64 encoded to make it JSON'able.
81 65 backend : {matplotlib, dvipng}
82 66 Backend for producing PNG data.
83 67 wrap : bool
@@ -86,6 +70,7 b' def latex_to_png(s, encode=False, backend=None, wrap=False):'
86 70 None is returned when the backend cannot be used.
87 71
88 72 """
73 s = cast_unicode(s)
89 74 allowed_backends = LaTeXTool.instance().backends
90 75 if backend is None:
91 76 backend = allowed_backends[0]
@@ -110,7 +95,7 b' def latex_to_png_mpl(s, wrap):'
110 95 return None
111 96
112 97 if wrap:
113 s = '${0}$'.format(s)
98 s = u'${0}$'.format(s)
114 99 mt = mathtext.MathTextParser('bitmap')
115 100 f = BytesIO()
116 101 mt.to_png(f, s, fontsize=12)
@@ -129,10 +114,10 b' def latex_to_png_dvipng(s, wrap):'
129 114 dvifile = os.path.join(workdir, "tmp.dvi")
130 115 outfile = os.path.join(workdir, "tmp.png")
131 116
132 with open(tmpfile, "w") as f:
117 with open(tmpfile, "w", encoding='utf8') as f:
133 118 f.writelines(genelatex(s, wrap))
134 119
135 with open(os.devnull, 'w') as devnull:
120 with open(os.devnull, 'wb') as devnull:
136 121 subprocess.check_call(
137 122 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
138 123 cwd=workdir, stdout=devnull, stderr=devnull)
@@ -156,7 +141,7 b' def kpsewhich(filename):'
156 141 ["kpsewhich", filename],
157 142 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
158 143 (stdout, stderr) = proc.communicate()
159 return stdout.strip()
144 return stdout.strip().decode('utf8', 'replace')
160 145 except FindCmdError:
161 146 pass
162 147
@@ -165,28 +150,28 b' def genelatex(body, wrap):'
165 150 """Generate LaTeX document for dvipng backend."""
166 151 lt = LaTeXTool.instance()
167 152 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
168 yield r'\documentclass{article}'
153 yield u(r'\documentclass{article}')
169 154 packages = lt.packages
170 155 if breqn:
171 156 packages = packages + ['breqn']
172 157 for pack in packages:
173 yield r'\usepackage{{{0}}}'.format(pack)
174 yield r'\pagestyle{empty}'
158 yield u(r'\usepackage{{{0}}}'.format(pack))
159 yield u(r'\pagestyle{empty}')
175 160 if lt.preamble:
176 161 yield lt.preamble
177 yield r'\begin{document}'
162 yield u(r'\begin{document}')
178 163 if breqn:
179 yield r'\begin{dmath*}'
164 yield u(r'\begin{dmath*}')
180 165 yield body
181 yield r'\end{dmath*}'
166 yield u(r'\end{dmath*}')
182 167 elif wrap:
183 yield '$${0}$$'.format(body)
168 yield u'$${0}$$'.format(body)
184 169 else:
185 170 yield body
186 yield r'\end{document}'
171 yield u'\end{document}'
187 172
188 173
189 _data_uri_template_png = """<img src="data:image/png;base64,%s" alt=%s />"""
174 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
190 175
191 176 def latex_to_html(s, alt='image'):
192 177 """Render LaTeX to HTML with embedded PNG data using data URIs.
@@ -198,54 +183,8 b" def latex_to_html(s, alt='image'):"
198 183 alt : str
199 184 The alt text to use for the HTML.
200 185 """
201 base64_data = bytes_to_str(latex_to_png(s, encode=True), 'ascii')
186 base64_data = latex_to_png(s, encode=True).decode('ascii')
202 187 if base64_data:
203 188 return _data_uri_template_png % (base64_data, alt)
204 189
205 190
206 # From matplotlib, thanks to mdboom. Once this is in matplotlib releases, we
207 # will remove.
208 def math_to_image(s, filename_or_obj, prop=None, dpi=None, format=None):
209 """
210 Given a math expression, renders it in a closely-clipped bounding
211 box to an image file.
212
213 *s*
214 A math expression. The math portion should be enclosed in
215 dollar signs.
216
217 *filename_or_obj*
218 A filepath or writable file-like object to write the image data
219 to.
220
221 *prop*
222 If provided, a FontProperties() object describing the size and
223 style of the text.
224
225 *dpi*
226 Override the output dpi, otherwise use the default associated
227 with the output format.
228
229 *format*
230 The output format, eg. 'svg', 'pdf', 'ps' or 'png'. If not
231 provided, will be deduced from the filename.
232 """
233 from matplotlib import figure
234 # backend_agg supports all of the core output formats
235 from matplotlib.backends import backend_agg
236 from matplotlib.font_manager import FontProperties
237 from matplotlib.mathtext import MathTextParser
238
239 if prop is None:
240 prop = FontProperties()
241
242 parser = MathTextParser('path')
243 width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop)
244
245 fig = figure.Figure(figsize=(width / 72.0, height / 72.0))
246 fig.text(0, depth/height, s, fontproperties=prop)
247 backend_agg.FigureCanvasAgg(fig)
248 fig.savefig(filename_or_obj, dpi=dpi, format=format)
249
250 return depth
251
@@ -129,7 +129,6 b' class RichIPythonWidget(IPythonWidget):'
129 129 self._append_html(self.output_sep2, True)
130 130 elif 'text/latex' in data:
131 131 self._pre_image_append(msg, prompt_number)
132 latex = data['text/latex'].encode('ascii')
133 132 # latex_to_png takes care of handling $
134 133 latex = latex.strip('$')
135 134 png = latex_to_png(latex, wrap=True)
General Comments 0
You need to be logged in to leave comments. Login now