123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- import hashlib
- import os
- import sys
- from docutils import nodes
- from docutils.parsers.rst import Directive, directives
- import sphinx
- from matplotlib import rcParams
- from matplotlib import cbook
- from matplotlib.mathtext import MathTextParser
- rcParams['mathtext.fontset'] = 'cm'
- mathtext_parser = MathTextParser("Bitmap")
- # Define LaTeX math node:
- class latex_math(nodes.General, nodes.Element):
- pass
- def fontset_choice(arg):
- return directives.choice(arg, ['cm', 'stix', 'stixsans'])
- def math_role(role, rawtext, text, lineno, inliner,
- options={}, content=[]):
- i = rawtext.find('`')
- latex = rawtext[i+1:-1]
- node = latex_math(rawtext)
- node['latex'] = latex
- node['fontset'] = options.get('fontset', 'cm')
- return [node], []
- math_role.options = {'fontset': fontset_choice}
- @cbook.deprecated("3.1", alternative="MathDirective")
- def math_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- latex = ''.join(content)
- node = latex_math(block_text)
- node['latex'] = latex
- node['fontset'] = options.get('fontset', 'cm')
- return [node]
- class MathDirective(Directive):
- has_content = True
- required_arguments = 0
- optional_arguments = 0
- final_argument_whitespace = False
- option_spec = {'fontset': fontset_choice}
- def run(self):
- latex = ''.join(self.content)
- node = latex_math(self.block_text)
- node['latex'] = latex
- node['fontset'] = self.options.get('fontset', 'cm')
- return [node]
- # This uses mathtext to render the expression
- def latex2png(latex, filename, fontset='cm'):
- latex = "$%s$" % latex
- orig_fontset = rcParams['mathtext.fontset']
- rcParams['mathtext.fontset'] = fontset
- if os.path.exists(filename):
- depth = mathtext_parser.get_depth(latex, dpi=100)
- else:
- try:
- depth = mathtext_parser.to_png(filename, latex, dpi=100)
- except Exception:
- cbook._warn_external("Could not render math expression %s" % latex,
- Warning)
- depth = 0
- rcParams['mathtext.fontset'] = orig_fontset
- sys.stdout.write("#")
- sys.stdout.flush()
- return depth
- # LaTeX to HTML translation stuff:
- def latex2html(node, source):
- inline = isinstance(node.parent, nodes.TextElement)
- latex = node['latex']
- name = 'math-%s' % hashlib.md5(latex.encode()).hexdigest()[-10:]
- destdir = os.path.join(setup.app.builder.outdir, '_images', 'mathmpl')
- if not os.path.exists(destdir):
- os.makedirs(destdir)
- dest = os.path.join(destdir, '%s.png' % name)
- path = '/'.join((setup.app.builder.imgpath, 'mathmpl'))
- depth = latex2png(latex, dest, node['fontset'])
- if inline:
- cls = ''
- else:
- cls = 'class="center" '
- if inline and depth != 0:
- style = 'style="position: relative; bottom: -%dpx"' % (depth + 1)
- else:
- style = ''
- return '<img src="%s/%s.png" %s%s/>' % (path, name, cls, style)
- def setup(app):
- setup.app = app
- # Add visit/depart methods to HTML-Translator:
- def visit_latex_math_html(self, node):
- source = self.document.attributes['source']
- self.body.append(latex2html(node, source))
- def depart_latex_math_html(self, node):
- pass
- # Add visit/depart methods to LaTeX-Translator:
- def visit_latex_math_latex(self, node):
- inline = isinstance(node.parent, nodes.TextElement)
- if inline:
- self.body.append('$%s$' % node['latex'])
- else:
- self.body.extend(['\\begin{equation}',
- node['latex'],
- '\\end{equation}'])
- def depart_latex_math_latex(self, node):
- pass
- app.add_node(latex_math,
- html=(visit_latex_math_html, depart_latex_math_html),
- latex=(visit_latex_math_latex, depart_latex_math_latex))
- app.add_role('mathmpl', math_role)
- app.add_directive('mathmpl', MathDirective)
- if sphinx.version_info < (1, 8):
- app.add_role('math', math_role)
- app.add_directive('math', MathDirective)
- metadata = {'parallel_read_safe': True, 'parallel_write_safe': True}
- return metadata
|