def latex_image_length(self, width_str, figure=False):
"""Convert `width_str` with rst length to LaTeX length.
This function is copied from docutils' latex writer
The last parameter, ``figure`` is only for compatibility with 1.4.4.
It will be removed at Sphinx-1.5.
"""
match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
if not match:
# fallback
return width_str
res = width_str
amount, unit = match.groups()[:2]
if figure and unit in ('', 'pt'):
res = '%sbp' % amount # convert to 'bp'
elif not unit or unit == "px":
# pixels: let LaTeX alone
return None
elif unit == "%":
res = "%.3f\\linewidth" % (float(amount) / 100.0)
return res
python类figure()的实例源码
def visit_footnote(self, node):
try:
backref = node['backrefs'][0]
except IndexError:
backref = node['ids'][0] # no backref, use self-ref instead
if self.settings.figure_footnotes:
self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
self.out.append('\\begin{figure}[b]')
self.append_hypertargets(node)
if node.get('id') == node.get('name'): # explicite label
self.out += self.ids_to_labels(node)
elif self.docutils_footnotes:
self.fallbacks['footnotes'] = PreambleCmds.footnotes
num,text = node.astext().split(None,1)
if self.settings.footnote_references == 'brackets':
num = '[%s]' % num
self.out.append('%%\n\\DUfootnotetext{%s}{%s}{%s}{' %
(node['ids'][0], backref, self.encode(num)))
if node['ids'] == node['names']:
self.out += self.ids_to_labels(node)
# mask newline to prevent spurious whitespace:
self.out.append('%')
## else: # TODO: "real" LaTeX \footnote{}s
def apply(self):
def has_child(node, cls):
return any(isinstance(child, cls) for child in node)
for node in self.document.traverse(nodes.Element):
if isinstance(node, nodes.figure):
if has_child(node, nodes.caption):
self.document.note_implicit_target(node)
elif isinstance(node, nodes.image):
if node.parent and has_child(node.parent, nodes.caption):
self.document.note_implicit_target(node.parent)
elif isinstance(node, nodes.table):
if has_child(node, nodes.title):
self.document.note_implicit_target(node)
elif isinstance(node, nodes.literal_block):
if node.parent and has_child(node.parent, nodes.caption):
self.document.note_implicit_target(node.parent)
def depart_caption(self, node):
self.body.append('</span>')
# append permalink if available
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.add_permalink_ref(node.parent, _('Permalink to this code'))
elif isinstance(node.parent, nodes.figure):
image_nodes = node.parent.traverse(nodes.image)
target_node = image_nodes and image_nodes[0] or node.parent
self.add_permalink_ref(target_node, _('Permalink to this image'))
elif node.parent.get('toctree'):
self.add_permalink_ref(node.parent.parent, _('Permalink to this toctree'))
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.body.append('</div>\n')
else:
BaseTranslator.depart_caption(self, node)
def depart_image(self, node):
if type(node.parent) == nodes.figure:
self.visit_reference(node)
self.append('[' + node.attributes.get('alt', 'Image') + ']')
self.depart_reference(node)
self.newline()
else:
self.append('[' + node.attributes.get('alt', 'Image') + ']')
def visit_figure(self, node):
ids = ''
if node.get('refuri'):
ids += self.hypertarget(node['refuri'], withdoc=False, anchor=False)
for id in sorted(self.pop_hyperlink_ids('figure')):
ids += self.hypertarget(id, anchor=False)
if node['ids']:
ids += self.hypertarget(node['ids'][0], anchor=False)
if (len(node.children) and
isinstance(node.children[0], nodes.image) and
node.children[0]['ids']):
ids += self.hypertarget(node.children[0]['ids'][0], anchor=False)
for c in node.children:
if isinstance(c, nodes.caption):
caption = c.astext()
node.caption = caption
ids += self.hypertarget('figure:%s' % caption,
withdoc=False,
anchor=False)
break
self.restrict_footnote(node)
self.body.append('\\begin{figure}[tb]\\begin{center}')
# The context is added to the body in depart_figure()
if ids:
self.context.append(ids)
self.context.append('\\end{center}\\end{figure}\n')
def visit_caption(self, node):
self.in_caption += 1
if self.in_container_literal_block:
# Track the caption body separately
self.literal_block_caption = []
self.pushbody(self.literal_block_caption)
elif self.in_minipage and isinstance(node.parent, nodes.figure):
self.body.append('\\captionof{figure}{')
elif self.table and node.parent.tagname == 'figure':
self.body.append('\\sphinxfigcaption{')
else:
self.body.append('\\caption{')
def visit_citation(self, node):
# TODO maybe use cite bibitems
if self._use_latex_citations:
self.push_output_collector([])
else:
# TODO: do we need these?
## self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
self.out.append(r'\begin{figure}[b]')
self.append_hypertargets(node)
def depart_citation(self, node):
if self._use_latex_citations:
label = self.out[0]
text = ''.join(self.out[1:])
self._bibitems.append([label, text])
self.pop_output_collector()
else:
self.out.append('\\end{figure}\n')
def visit_figure(self, node):
self.requirements['float_settings'] = PreambleCmds.float_settings
# The 'align' attribute sets the "outer alignment",
# for "inner alignment" use LaTeX default alignment (similar to HTML)
alignment = node.attributes.get('align', 'center')
if alignment != 'center':
# The LaTeX "figure" environment always uses the full linewidth,
# so "outer alignment" is ignored. Just write a comment.
# TODO: use the wrapfigure environment?
self.out.append('\n\\begin{figure} %% align = "%s"\n' % alignment)
else:
self.out.append('\n\\begin{figure}\n')
if node.get('ids'):
self.out += self.ids_to_labels(node) + ['\n']
def depart_figure(self, node):
self.out.append('\\end{figure}\n')
def visit_citation(self, node):
# TODO maybe use cite bibitems
if self._use_latex_citations:
self.push_output_collector([])
else:
# TODO: do we need these?
## self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
self.out.append(r'\begin{figure}[b]')
self.append_hypertargets(node)
def depart_citation(self, node):
if self._use_latex_citations:
label = self.out[0]
text = ''.join(self.out[1:])
self._bibitems.append([label, text])
self.pop_output_collector()
else:
self.out.append('\\end{figure}\n')
def visit_figure(self, node):
self.requirements['float_settings'] = PreambleCmds.float_settings
self.duclass_open(node)
# The 'align' attribute sets the "outer alignment",
# for "inner alignment" use LaTeX default alignment (similar to HTML)
alignment = node.attributes.get('align', 'center')
if alignment != 'center':
# The LaTeX "figure" environment always uses the full linewidth,
# so "outer alignment" is ignored. Just write a comment.
# TODO: use the wrapfigure environment?
self.out.append('\\begin{figure} %% align = "%s"\n' % alignment)
else:
self.out.append('\\begin{figure}\n')
if node.get('ids'):
self.out += self.ids_to_labels(node) + ['\n']
def depart_figure(self, node):
self.out.append('\\end{figure}\n')
self.duclass_close(node)
def get_figtype(self, node):
"""Get figure type of nodes."""
def has_child(node, cls):
return any(isinstance(child, cls) for child in node)
if isinstance(node, nodes.container):
if node.get('literal_block') and has_child(node, nodes.literal_block):
return 'code-block'
else:
return None
else:
figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return figtype
def doctree_read(app, doctree):
# first generate figure numbers for each figure
env = app.builder.env
figid_docname_map = getattr(env, 'figid_docname_map', {})
for figure_info in doctree.traverse(figure):
for id in figure_info['ids']:
figid_docname_map[id] = env.docname
env.figid_docname_map = figid_docname_map
def doctree_resolved(app, doctree, docname):
i = 1
figids = {}
for figure_info in doctree.traverse(figure):
if app.builder.name != 'latex' and app.config.number_figures:
for cap in figure_info.traverse(caption):
cap[0] = Text("%s %d: %s" % (app.config.figure_caption_prefix, i, cap[0]))
for id in figure_info['ids']:
figids[id] = i
i += 1
# replace numfig nodes with links
if app.builder.name != 'latex':
for ref_info in doctree.traverse(num_ref):
if '#' in ref_info['reftarget']:
label, target = ref_info['reftarget'].split('#')
labelfmt = label + " %d"
else:
labelfmt = '%d'
target = ref_info['reftarget']
if target not in figids:
continue
if app.builder.name == 'html':
target_doc = app.builder.env.figid_docname_map[target]
link = "%s#%s" % (app.builder.get_relative_uri(docname, target_doc),
target)
html = '<a class="pageref" href="%s">Fig. %s</a>' % (link, labelfmt %(figids[target]))
ref_info.replace_self(raw(html, html, format='html'))
else:
ref_info.replace_self(Text(labelfmt % (figids[target])))
def visit_citation(self, node):
# TODO maybe use cite bibitems
if self._use_latex_citations:
self.push_output_collector([])
else:
# TODO: do we need these?
## self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
self.out.append(r'\begin{figure}[b]')
self.append_hypertargets(node)
def depart_citation(self, node):
if self._use_latex_citations:
label = self.out[0]
text = ''.join(self.out[1:])
self._bibitems.append([label, text])
self.pop_output_collector()
else:
self.out.append('\\end{figure}\n')
def visit_figure(self, node):
self.requirements['float_settings'] = PreambleCmds.float_settings
# The 'align' attribute sets the "outer alignment",
# for "inner alignment" use LaTeX default alignment (similar to HTML)
alignment = node.attributes.get('align', 'center')
if alignment != 'center':
# The LaTeX "figure" environment always uses the full textwidth,
# so "outer alignment" is ignored. Just write a comment.
# TODO: use the wrapfigure environment?
self.out.append('\n\\begin{figure} %% align = "%s"\n' % alignment)
else:
self.out.append('\n\\begin{figure}\n')
if node.get('ids'):
self.out += self.ids_to_labels(node) + ['\n']
def depart_figure(self, node):
self.out.append('\\end{figure}\n')
def figure_wrapper(directive, node, caption):
figure_node = nodes.figure('', node)
parsed = nodes.Element()
directive.state.nested_parse(ViewList([caption], source=''),
directive.content_offset, parsed)
caption_node = nodes.caption(parsed[0].rawsource, '',
*parsed[0].children)
caption_node.source = parsed[0].source
caption_node.line = parsed[0].line
figure_node += caption_node
return figure_node
def apply_source_workaround(node):
# workaround: nodes.term have wrong rawsource if classifier is specified.
# The behavior of docutils-0.11, 0.12 is:
# * when ``term text : classifier1 : classifier2`` is specified,
# * rawsource of term node will have: ``term text : classifier1 : classifier2``
# * rawsource of classifier node will be None
if isinstance(node, nodes.classifier) and not node.rawsource:
definition_list_item = node.parent
node.source = definition_list_item.source
node.line = definition_list_item.line - 1
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
if isinstance(node, nodes.term):
# strip classifier from rawsource of term
for classifier in reversed(node.parent.traverse(nodes.classifier)):
node.rawsource = re.sub(
'\s*:\s*%s' % re.escape(classifier.astext()), '', node.rawsource)
# workaround: recommonmark-0.2.0 doesn't set rawsource attribute
if not node.rawsource:
node.rawsource = node.astext()
if node.source and node.rawsource:
return
# workaround: docutils-0.10.0 or older's nodes.caption for nodes.figure
# and nodes.title for nodes.admonition doesn't have source, line.
# this issue was filed to Docutils tracker:
# sf.net/tracker/?func=detail&aid=3599485&group_id=38414&atid=422032
# sourceforge.net/p/docutils/patches/108/
if (isinstance(node, (
nodes.caption,
nodes.title,
nodes.rubric,
nodes.line,
))):
node.source = find_source_node(node)
node.line = 0 # need fix docutils to get `node.line`
return
def depart_caption(self, node):
if (isinstance(node.parent, nodes.figure) or
(isinstance(node.parent, nodes.container) and
node.parent.get('literal_block'))):
self.body.append('}\n')
def visit_figure(self, node):
ids = ''
for id in self.next_figure_ids:
ids += self.hypertarget(id, anchor=False)
self.next_figure_ids.clear()
self.restrict_footnote(node)
if (len(node.children) and
isinstance(node.children[0], nodes.image) and
node.children[0]['ids']):
ids += self.hypertarget(node.children[0]['ids'][0], anchor=False)
if 'width' in node and node.get('align', '') in ('left', 'right'):
self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
(node['align'] == 'right' and 'r' or 'l',
node['width']))
self.context.append(ids + '\\end{wrapfigure}\n')
else:
if ('align' not in node.attributes or
node.attributes['align'] == 'center'):
# centering does not add vertical space like center.
align = '\n\\centering'
align_end = ''
else:
# TODO non vertical space for other alignments.
align = '\\begin{flush%s}' % node.attributes['align']
align_end = '\\end{flush%s}' % node.attributes['align']
self.body.append('\\begin{figure}[%s]%s\n' % (
self.elements['figure_align'], align))
if any(isinstance(child, nodes.caption) for child in node):
self.body.append('\\capstart\n')
self.context.append(ids + align_end + '\\end{figure}\n')
def visit_citation(self, node):
# TODO maybe use cite bibitems
if self._use_latex_citations:
self.push_output_collector([])
else:
# TODO: do we need these?
## self.requirements['~fnt_floats'] = PreambleCmds.footnote_floats
self.out.append(r'\begin{figure}[b]')
self.append_hypertargets(node)
def depart_citation(self, node):
if self._use_latex_citations:
label = self.out[0]
text = ''.join(self.out[1:])
self._bibitems.append([label, text])
self.pop_output_collector()
else:
self.out.append('\\end{figure}\n')
def visit_figure(self, node):
self.requirements['float_settings'] = PreambleCmds.float_settings
self.duclass_open(node)
# The 'align' attribute sets the "outer alignment",
# for "inner alignment" use LaTeX default alignment (similar to HTML)
alignment = node.attributes.get('align', 'center')
if alignment != 'center':
# The LaTeX "figure" environment always uses the full linewidth,
# so "outer alignment" is ignored. Just write a comment.
# TODO: use the wrapfigure environment?
self.out.append('\\begin{figure} %% align = "%s"\n' % alignment)
else:
self.out.append('\\begin{figure}\n')
if node.get('ids'):
self.out += self.ids_to_labels(node) + ['\n']
def depart_figure(self, node):
self.out.append('\\end{figure}\n')
self.duclass_close(node)