##// END OF EJS Templates
Merge pull request #11840 from oscargus/enablelatexfontcolor...
Matthias Bussonnier -
r25163:fe0b87c2 merge
parent child Browse files
Show More
@@ -1,201 +1,220 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for handling LaTeX."""
2 """Tools for handling LaTeX."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from io import BytesIO, open
7 from io import BytesIO, open
8 import os
8 import os
9 import tempfile
9 import tempfile
10 import shutil
10 import shutil
11 import subprocess
11 import subprocess
12 from base64 import encodebytes
12 from base64 import encodebytes
13 import textwrap
13
14
14 from IPython.utils.process import find_cmd, FindCmdError
15 from IPython.utils.process import find_cmd, FindCmdError
15 from traitlets.config import get_config
16 from traitlets.config import get_config
16 from traitlets.config.configurable import SingletonConfigurable
17 from traitlets.config.configurable import SingletonConfigurable
17 from traitlets import List, Bool, Unicode
18 from traitlets import List, Bool, Unicode
18 from IPython.utils.py3compat import cast_unicode
19 from IPython.utils.py3compat import cast_unicode
19
20
20
21
21 class LaTeXTool(SingletonConfigurable):
22 class LaTeXTool(SingletonConfigurable):
22 """An object to store configuration of the LaTeX tool."""
23 """An object to store configuration of the LaTeX tool."""
23 def _config_default(self):
24 def _config_default(self):
24 return get_config()
25 return get_config()
25
26
26 backends = List(
27 backends = List(
27 Unicode(), ["matplotlib", "dvipng"],
28 Unicode(), ["matplotlib", "dvipng"],
28 help="Preferred backend to draw LaTeX math equations. "
29 help="Preferred backend to draw LaTeX math equations. "
29 "Backends in the list are checked one by one and the first "
30 "Backends in the list are checked one by one and the first "
30 "usable one is used. Note that `matplotlib` backend "
31 "usable one is used. Note that `matplotlib` backend "
31 "is usable only for inline style equations. To draw "
32 "is usable only for inline style equations. To draw "
32 "display style equations, `dvipng` backend must be specified. ",
33 "display style equations, `dvipng` backend must be specified. ",
33 # It is a List instead of Enum, to make configuration more
34 # It is a List instead of Enum, to make configuration more
34 # flexible. For example, to use matplotlib mainly but dvipng
35 # flexible. For example, to use matplotlib mainly but dvipng
35 # for display style, the default ["matplotlib", "dvipng"] can
36 # for display style, the default ["matplotlib", "dvipng"] can
36 # be used. To NOT use dvipng so that other repr such as
37 # be used. To NOT use dvipng so that other repr such as
37 # unicode pretty printing is used, you can use ["matplotlib"].
38 # unicode pretty printing is used, you can use ["matplotlib"].
38 ).tag(config=True)
39 ).tag(config=True)
39
40
40 use_breqn = Bool(
41 use_breqn = Bool(
41 True,
42 True,
42 help="Use breqn.sty to automatically break long equations. "
43 help="Use breqn.sty to automatically break long equations. "
43 "This configuration takes effect only for dvipng backend.",
44 "This configuration takes effect only for dvipng backend.",
44 ).tag(config=True)
45 ).tag(config=True)
45
46
46 packages = List(
47 packages = List(
47 ['amsmath', 'amsthm', 'amssymb', 'bm'],
48 ['amsmath', 'amsthm', 'amssymb', 'bm'],
48 help="A list of packages to use for dvipng backend. "
49 help="A list of packages to use for dvipng backend. "
49 "'breqn' will be automatically appended when use_breqn=True.",
50 "'breqn' will be automatically appended when use_breqn=True.",
50 ).tag(config=True)
51 ).tag(config=True)
51
52
52 preamble = Unicode(
53 preamble = Unicode(
53 help="Additional preamble to use when generating LaTeX source "
54 help="Additional preamble to use when generating LaTeX source "
54 "for dvipng backend.",
55 "for dvipng backend.",
55 ).tag(config=True)
56 ).tag(config=True)
56
57
57
58
58 def latex_to_png(s, encode=False, backend=None, wrap=False):
59 def latex_to_png(s, encode=False, backend=None, wrap=False, color='Black',
60 scale=1.0):
59 """Render a LaTeX string to PNG.
61 """Render a LaTeX string to PNG.
60
62
61 Parameters
63 Parameters
62 ----------
64 ----------
63 s : str
65 s : str
64 The raw string containing valid inline LaTeX.
66 The raw string containing valid inline LaTeX.
65 encode : bool, optional
67 encode : bool, optional
66 Should the PNG data base64 encoded to make it JSON'able.
68 Should the PNG data base64 encoded to make it JSON'able.
67 backend : {matplotlib, dvipng}
69 backend : {matplotlib, dvipng}
68 Backend for producing PNG data.
70 Backend for producing PNG data.
69 wrap : bool
71 wrap : bool
70 If true, Automatically wrap `s` as a LaTeX equation.
72 If true, Automatically wrap `s` as a LaTeX equation.
73 color : string
74 Foreground color name among dvipsnames, e.g. 'Maroon' or on hex RGB
75 format, e.g. '#AA20FA'.
76 scale : float
77 Scale factor for the resulting PNG.
71
78
72 None is returned when the backend cannot be used.
79 None is returned when the backend cannot be used.
73
80
74 """
81 """
75 s = cast_unicode(s)
82 s = cast_unicode(s)
76 allowed_backends = LaTeXTool.instance().backends
83 allowed_backends = LaTeXTool.instance().backends
77 if backend is None:
84 if backend is None:
78 backend = allowed_backends[0]
85 backend = allowed_backends[0]
79 if backend not in allowed_backends:
86 if backend not in allowed_backends:
80 return None
87 return None
81 if backend == 'matplotlib':
88 if backend == 'matplotlib':
82 f = latex_to_png_mpl
89 f = latex_to_png_mpl
83 elif backend == 'dvipng':
90 elif backend == 'dvipng':
84 f = latex_to_png_dvipng
91 f = latex_to_png_dvipng
92 if color.startswith('#'):
93 # Convert hex RGB color to LaTeX RGB color.
94 if len(color) == 7:
95 try:
96 color = "RGB {}".format(" ".join([str(int(x, 16)) for x in
97 textwrap.wrap(color[1:], 2)]))
98 except ValueError:
99 raise ValueError('Invalid color specification {}.'.format(color))
100 else:
101 raise ValueError('Invalid color specification {}.'.format(color))
85 else:
102 else:
86 raise ValueError('No such backend {0}'.format(backend))
103 raise ValueError('No such backend {0}'.format(backend))
87 bin_data = f(s, wrap)
104 bin_data = f(s, wrap, color, scale)
88 if encode and bin_data:
105 if encode and bin_data:
89 bin_data = encodebytes(bin_data)
106 bin_data = encodebytes(bin_data)
90 return bin_data
107 return bin_data
91
108
92
109
93 def latex_to_png_mpl(s, wrap):
110 def latex_to_png_mpl(s, wrap, color='Black', scale=1.0):
94 try:
111 try:
95 from matplotlib import mathtext
112 from matplotlib import mathtext
96 from pyparsing import ParseFatalException
113 from pyparsing import ParseFatalException
97 except ImportError:
114 except ImportError:
98 return None
115 return None
99
116
100 # mpl mathtext doesn't support display math, force inline
117 # mpl mathtext doesn't support display math, force inline
101 s = s.replace('$$', '$')
118 s = s.replace('$$', '$')
102 if wrap:
119 if wrap:
103 s = u'${0}$'.format(s)
120 s = u'${0}$'.format(s)
104
121
105 try:
122 try:
106 mt = mathtext.MathTextParser('bitmap')
123 mt = mathtext.MathTextParser('bitmap')
107 f = BytesIO()
124 f = BytesIO()
108 mt.to_png(f, s, fontsize=12)
125 dpi = 120*scale
126 mt.to_png(f, s, fontsize=12, dpi=dpi, color=color)
109 return f.getvalue()
127 return f.getvalue()
110 except (ValueError, RuntimeError, ParseFatalException):
128 except (ValueError, RuntimeError, ParseFatalException):
111 return None
129 return None
112
130
113
131
114 def latex_to_png_dvipng(s, wrap):
132 def latex_to_png_dvipng(s, wrap, color='Black', scale=1.0):
115 try:
133 try:
116 find_cmd('latex')
134 find_cmd('latex')
117 find_cmd('dvipng')
135 find_cmd('dvipng')
118 except FindCmdError:
136 except FindCmdError:
119 return None
137 return None
120 try:
138 try:
121 workdir = tempfile.mkdtemp()
139 workdir = tempfile.mkdtemp()
122 tmpfile = os.path.join(workdir, "tmp.tex")
140 tmpfile = os.path.join(workdir, "tmp.tex")
123 dvifile = os.path.join(workdir, "tmp.dvi")
141 dvifile = os.path.join(workdir, "tmp.dvi")
124 outfile = os.path.join(workdir, "tmp.png")
142 outfile = os.path.join(workdir, "tmp.png")
125
143
126 with open(tmpfile, "w", encoding='utf8') as f:
144 with open(tmpfile, "w", encoding='utf8') as f:
127 f.writelines(genelatex(s, wrap))
145 f.writelines(genelatex(s, wrap))
128
146
129 with open(os.devnull, 'wb') as devnull:
147 with open(os.devnull, 'wb') as devnull:
130 subprocess.check_call(
148 subprocess.check_call(
131 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
149 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
132 cwd=workdir, stdout=devnull, stderr=devnull)
150 cwd=workdir, stdout=devnull, stderr=devnull)
133
151
152 resolution = round(150*scale)
134 subprocess.check_call(
153 subprocess.check_call(
135 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
154 ["dvipng", "-T", "tight", "-D", str(resolution), "-z", "9",
136 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir,
155 "-bg", "transparent", "-o", outfile, dvifile, "-fg", color],
137 stdout=devnull, stderr=devnull)
156 cwd=workdir, stdout=devnull, stderr=devnull)
138
157
139 with open(outfile, "rb") as f:
158 with open(outfile, "rb") as f:
140 return f.read()
159 return f.read()
141 except subprocess.CalledProcessError:
160 except subprocess.CalledProcessError:
142 return None
161 return None
143 finally:
162 finally:
144 shutil.rmtree(workdir)
163 shutil.rmtree(workdir)
145
164
146
165
147 def kpsewhich(filename):
166 def kpsewhich(filename):
148 """Invoke kpsewhich command with an argument `filename`."""
167 """Invoke kpsewhich command with an argument `filename`."""
149 try:
168 try:
150 find_cmd("kpsewhich")
169 find_cmd("kpsewhich")
151 proc = subprocess.Popen(
170 proc = subprocess.Popen(
152 ["kpsewhich", filename],
171 ["kpsewhich", filename],
153 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
172 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
154 (stdout, stderr) = proc.communicate()
173 (stdout, stderr) = proc.communicate()
155 return stdout.strip().decode('utf8', 'replace')
174 return stdout.strip().decode('utf8', 'replace')
156 except FindCmdError:
175 except FindCmdError:
157 pass
176 pass
158
177
159
178
160 def genelatex(body, wrap):
179 def genelatex(body, wrap):
161 """Generate LaTeX document for dvipng backend."""
180 """Generate LaTeX document for dvipng backend."""
162 lt = LaTeXTool.instance()
181 lt = LaTeXTool.instance()
163 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
182 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
164 yield r'\documentclass{article}'
183 yield r'\documentclass{article}'
165 packages = lt.packages
184 packages = lt.packages
166 if breqn:
185 if breqn:
167 packages = packages + ['breqn']
186 packages = packages + ['breqn']
168 for pack in packages:
187 for pack in packages:
169 yield r'\usepackage{{{0}}}'.format(pack)
188 yield r'\usepackage{{{0}}}'.format(pack)
170 yield r'\pagestyle{empty}'
189 yield r'\pagestyle{empty}'
171 if lt.preamble:
190 if lt.preamble:
172 yield lt.preamble
191 yield lt.preamble
173 yield r'\begin{document}'
192 yield r'\begin{document}'
174 if breqn:
193 if breqn:
175 yield r'\begin{dmath*}'
194 yield r'\begin{dmath*}'
176 yield body
195 yield body
177 yield r'\end{dmath*}'
196 yield r'\end{dmath*}'
178 elif wrap:
197 elif wrap:
179 yield u'$${0}$$'.format(body)
198 yield u'$${0}$$'.format(body)
180 else:
199 else:
181 yield body
200 yield body
182 yield u'\\end{document}'
201 yield u'\\end{document}'
183
202
184
203
185 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
204 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
186
205
187 def latex_to_html(s, alt='image'):
206 def latex_to_html(s, alt='image'):
188 """Render LaTeX to HTML with embedded PNG data using data URIs.
207 """Render LaTeX to HTML with embedded PNG data using data URIs.
189
208
190 Parameters
209 Parameters
191 ----------
210 ----------
192 s : str
211 s : str
193 The raw string containing valid inline LateX.
212 The raw string containing valid inline LateX.
194 alt : str
213 alt : str
195 The alt text to use for the HTML.
214 The alt text to use for the HTML.
196 """
215 """
197 base64_data = latex_to_png(s, encode=True).decode('ascii')
216 base64_data = latex_to_png(s, encode=True).decode('ascii')
198 if base64_data:
217 if base64_data:
199 return _data_uri_template_png % (base64_data, alt)
218 return _data_uri_template_png % (base64_data, alt)
200
219
201
220
@@ -1,134 +1,181 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6 from unittest.mock import patch
6 from unittest.mock import patch
7 import nose.tools as nt
7 import nose.tools as nt
8
8
9 from IPython.lib import latextools
9 from IPython.lib import latextools
10 from IPython.testing.decorators import onlyif_cmds_exist, skipif_not_matplotlib
10 from IPython.testing.decorators import onlyif_cmds_exist, skipif_not_matplotlib
11 from IPython.utils.process import FindCmdError
11 from IPython.utils.process import FindCmdError
12
12
13
13
14 def test_latex_to_png_dvipng_fails_when_no_cmd():
14 def test_latex_to_png_dvipng_fails_when_no_cmd():
15 """
15 """
16 `latex_to_png_dvipng` should return None when there is no required command
16 `latex_to_png_dvipng` should return None when there is no required command
17 """
17 """
18 for command in ['latex', 'dvipng']:
18 for command in ['latex', 'dvipng']:
19 yield (check_latex_to_png_dvipng_fails_when_no_cmd, command)
19 yield (check_latex_to_png_dvipng_fails_when_no_cmd, command)
20
20
21
21
22 def check_latex_to_png_dvipng_fails_when_no_cmd(command):
22 def check_latex_to_png_dvipng_fails_when_no_cmd(command):
23 def mock_find_cmd(arg):
23 def mock_find_cmd(arg):
24 if arg == command:
24 if arg == command:
25 raise FindCmdError
25 raise FindCmdError
26
26
27 with patch.object(latextools, "find_cmd", mock_find_cmd):
27 with patch.object(latextools, "find_cmd", mock_find_cmd):
28 nt.assert_equal(latextools.latex_to_png_dvipng("whatever", True),
28 nt.assert_equal(latextools.latex_to_png_dvipng("whatever", True),
29 None)
29 None)
30
30
31
31
32 @onlyif_cmds_exist('latex', 'dvipng')
32 @onlyif_cmds_exist('latex', 'dvipng')
33 def test_latex_to_png_dvipng_runs():
33 def test_latex_to_png_dvipng_runs():
34 """
34 """
35 Test that latex_to_png_dvipng just runs without error.
35 Test that latex_to_png_dvipng just runs without error.
36 """
36 """
37 def mock_kpsewhich(filename):
37 def mock_kpsewhich(filename):
38 nt.assert_equal(filename, "breqn.sty")
38 nt.assert_equal(filename, "breqn.sty")
39 return None
39 return None
40
40
41 for (s, wrap) in [(u"$$x^2$$", False), (u"x^2", True)]:
41 for (s, wrap) in [(u"$$x^2$$", False), (u"x^2", True)]:
42 yield (latextools.latex_to_png_dvipng, s, wrap)
42 yield (latextools.latex_to_png_dvipng, s, wrap)
43
43
44 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
44 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
45 yield (latextools.latex_to_png_dvipng, s, wrap)
45 yield (latextools.latex_to_png_dvipng, s, wrap)
46
46
47 @skipif_not_matplotlib
47 @skipif_not_matplotlib
48 def test_latex_to_png_mpl_runs():
48 def test_latex_to_png_mpl_runs():
49 """
49 """
50 Test that latex_to_png_mpl just runs without error.
50 Test that latex_to_png_mpl just runs without error.
51 """
51 """
52 def mock_kpsewhich(filename):
52 def mock_kpsewhich(filename):
53 nt.assert_equal(filename, "breqn.sty")
53 nt.assert_equal(filename, "breqn.sty")
54 return None
54 return None
55
55
56 for (s, wrap) in [("$x^2$", False), ("x^2", True)]:
56 for (s, wrap) in [("$x^2$", False), ("x^2", True)]:
57 yield (latextools.latex_to_png_mpl, s, wrap)
57 yield (latextools.latex_to_png_mpl, s, wrap)
58
58
59 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
59 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
60 yield (latextools.latex_to_png_mpl, s, wrap)
60 yield (latextools.latex_to_png_mpl, s, wrap)
61
61
62 @skipif_not_matplotlib
62 @skipif_not_matplotlib
63 def test_latex_to_html():
63 def test_latex_to_html():
64 img = latextools.latex_to_html("$x^2$")
64 img = latextools.latex_to_html("$x^2$")
65 nt.assert_in("data:image/png;base64,iVBOR", img)
65 nt.assert_in("data:image/png;base64,iVBOR", img)
66
66
67
67
68 def test_genelatex_no_wrap():
68 def test_genelatex_no_wrap():
69 """
69 """
70 Test genelatex with wrap=False.
70 Test genelatex with wrap=False.
71 """
71 """
72 def mock_kpsewhich(filename):
72 def mock_kpsewhich(filename):
73 assert False, ("kpsewhich should not be called "
73 assert False, ("kpsewhich should not be called "
74 "(called with {0})".format(filename))
74 "(called with {0})".format(filename))
75
75
76 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
76 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
77 nt.assert_equal(
77 nt.assert_equal(
78 '\n'.join(latextools.genelatex("body text", False)),
78 '\n'.join(latextools.genelatex("body text", False)),
79 r'''\documentclass{article}
79 r'''\documentclass{article}
80 \usepackage{amsmath}
80 \usepackage{amsmath}
81 \usepackage{amsthm}
81 \usepackage{amsthm}
82 \usepackage{amssymb}
82 \usepackage{amssymb}
83 \usepackage{bm}
83 \usepackage{bm}
84 \pagestyle{empty}
84 \pagestyle{empty}
85 \begin{document}
85 \begin{document}
86 body text
86 body text
87 \end{document}''')
87 \end{document}''')
88
88
89
89
90 def test_genelatex_wrap_with_breqn():
90 def test_genelatex_wrap_with_breqn():
91 """
91 """
92 Test genelatex with wrap=True for the case breqn.sty is installed.
92 Test genelatex with wrap=True for the case breqn.sty is installed.
93 """
93 """
94 def mock_kpsewhich(filename):
94 def mock_kpsewhich(filename):
95 nt.assert_equal(filename, "breqn.sty")
95 nt.assert_equal(filename, "breqn.sty")
96 return "path/to/breqn.sty"
96 return "path/to/breqn.sty"
97
97
98 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
98 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
99 nt.assert_equal(
99 nt.assert_equal(
100 '\n'.join(latextools.genelatex("x^2", True)),
100 '\n'.join(latextools.genelatex("x^2", True)),
101 r'''\documentclass{article}
101 r'''\documentclass{article}
102 \usepackage{amsmath}
102 \usepackage{amsmath}
103 \usepackage{amsthm}
103 \usepackage{amsthm}
104 \usepackage{amssymb}
104 \usepackage{amssymb}
105 \usepackage{bm}
105 \usepackage{bm}
106 \usepackage{breqn}
106 \usepackage{breqn}
107 \pagestyle{empty}
107 \pagestyle{empty}
108 \begin{document}
108 \begin{document}
109 \begin{dmath*}
109 \begin{dmath*}
110 x^2
110 x^2
111 \end{dmath*}
111 \end{dmath*}
112 \end{document}''')
112 \end{document}''')
113
113
114
114
115 def test_genelatex_wrap_without_breqn():
115 def test_genelatex_wrap_without_breqn():
116 """
116 """
117 Test genelatex with wrap=True for the case breqn.sty is not installed.
117 Test genelatex with wrap=True for the case breqn.sty is not installed.
118 """
118 """
119 def mock_kpsewhich(filename):
119 def mock_kpsewhich(filename):
120 nt.assert_equal(filename, "breqn.sty")
120 nt.assert_equal(filename, "breqn.sty")
121 return None
121 return None
122
122
123 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
123 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
124 nt.assert_equal(
124 nt.assert_equal(
125 '\n'.join(latextools.genelatex("x^2", True)),
125 '\n'.join(latextools.genelatex("x^2", True)),
126 r'''\documentclass{article}
126 r'''\documentclass{article}
127 \usepackage{amsmath}
127 \usepackage{amsmath}
128 \usepackage{amsthm}
128 \usepackage{amsthm}
129 \usepackage{amssymb}
129 \usepackage{amssymb}
130 \usepackage{bm}
130 \usepackage{bm}
131 \pagestyle{empty}
131 \pagestyle{empty}
132 \begin{document}
132 \begin{document}
133 $$x^2$$
133 $$x^2$$
134 \end{document}''')
134 \end{document}''')
135
136
137 @skipif_not_matplotlib
138 @onlyif_cmds_exist('latex', 'dvipng')
139 def test_latex_to_png_color():
140 """
141 Test color settings for latex_to_png.
142 """
143 latex_string = "$x^2$"
144 default_value = latextools.latex_to_png(latex_string, wrap=False)
145 default_hexblack = latextools.latex_to_png(latex_string, wrap=False,
146 color='#000000')
147 dvipng_default = latextools.latex_to_png_dvipng(latex_string, False)
148 dvipng_black = latextools.latex_to_png_dvipng(latex_string, False, 'Black')
149 nt.assert_equal(dvipng_default, dvipng_black)
150 mpl_default = latextools.latex_to_png_mpl(latex_string, False)
151 mpl_black = latextools.latex_to_png_mpl(latex_string, False, 'Black')
152 nt.assert_equal(mpl_default, mpl_black)
153 nt.assert_in(default_value, [dvipng_black, mpl_black])
154 nt.assert_in(default_hexblack, [dvipng_black, mpl_black])
155
156 # Test that dvips name colors can be used without error
157 dvipng_maroon = latextools.latex_to_png_dvipng(latex_string, False,
158 'Maroon')
159 # And that it doesn't return the black one
160 nt.assert_not_equal(dvipng_black, dvipng_maroon)
161
162 mpl_maroon = latextools.latex_to_png_mpl(latex_string, False, 'Maroon')
163 nt.assert_not_equal(mpl_black, mpl_maroon)
164 mpl_white = latextools.latex_to_png_mpl(latex_string, False, 'White')
165 mpl_hexwhite = latextools.latex_to_png_mpl(latex_string, False, '#FFFFFF')
166 nt.assert_equal(mpl_white, mpl_hexwhite)
167
168 mpl_white_scale = latextools.latex_to_png_mpl(latex_string, False,
169 'White', 1.2)
170 nt.assert_not_equal(mpl_white, mpl_white_scale)
171
172
173 def test_latex_to_png_invalid_hex_colors():
174 """
175 Test that invalid hex colors provided to dvipng gives an exception.
176 """
177 latex_string = "$x^2$"
178 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
179 backend='dvipng', color="#f00bar"))
180 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
181 backend='dvipng', color="#f00"))
General Comments 0
You need to be logged in to leave comments. Login now