]> git.llucax.com Git - z.facultad/75.00/informe.git/blob - ext/aafig.py
Mencionar problema de fragmentación
[z.facultad/75.00/informe.git] / ext / aafig.py
1 # -*- coding: utf-8 -*-
2 """
3     sphinxcontrib.aafig
4     ~~~~~~~~~~~~~~~~~~~
5
6     Allow embeded ASCII art to be rendered as nice looking images
7     using the aafigure reStructuredText extension.
8
9     See the README file for details.
10
11     :copyright: Copyright 2009 by Leandro Lucarella <llucax@gmail.com> \
12         (based on sphinxcontrib.mscgen).
13     :license: BSD, see LICENSE for details.
14 """
15
16 import posixpath
17 from os import path
18 try:
19     from hashlib import sha1 as sha
20 except ImportError:
21     from sha import sha
22
23 from docutils import nodes
24 from docutils.parsers.rst import directives
25
26 from sphinx.errors import SphinxError
27 from sphinx.util import ensuredir
28 from sphinx.util.compat import Directive
29
30 import aafigure
31
32 DEFAULT_PREFIX = 'aafig'
33
34 class AafigError(SphinxError):
35     category = 'aafig error'
36
37
38 class aafig(nodes.General, nodes.Element):
39     pass
40
41
42 class Aafig(Directive):
43     """
44     Directive to insert an ASCII art figure to be rendered by aafigure.
45     """
46     has_content = True
47     required_arguments = 0
48     optional_arguments = 0
49     final_argument_whitespace = False
50     option_spec = dict(
51         scale        = float,
52         line_width   = float,
53         background   = str,
54         foreground   = str,
55         fill         = str,
56         aspect       = float,
57         textual      = directives.flag,
58         proportional = directives.flag,
59     )
60
61     def run(self):
62         node = aafig()
63         node['text'] = '\n'.join(self.content)
64         if 'textual' in self.options: self.options['textual'] = True
65         if 'proportional' in self.options: self.options['proportional'] = True
66         node['options'] = self.options
67         return [node]
68
69
70 def render_aafigure(self, text, options, prefix):
71     """
72     Render an ASCII art figure into the requested format output file.
73     """
74     hashkey = text.encode('utf-8') + str(options)
75     id = sha(hashkey).hexdigest()
76     fname = '%s-%s.%s' % (prefix, id, options['format'])
77     metadata_fname = '%s.aafig' % fname
78     if hasattr(self.builder, 'imgpath'):
79         # HTML
80         relfn = posixpath.join(self.builder.imgpath, fname)
81         outfn = path.join(self.builder.outdir, '_images', fname)
82     else:
83         # LaTeX
84         relfn = fname
85         outfn = path.join(self.builder.outdir, fname)
86
87     if path.isfile(outfn):
88         extra = None
89         if options['format'].lower() == 'svg':
90             f = file(metadata_fname, 'r')
91             extra = f.read()
92             f.close()
93         return relfn, outfn, id, extra
94
95     ensuredir(path.dirname(outfn))
96
97     # merge default options
98     for (k, v) in self.builder.config.aafig_default_options.items():
99         if k not in options:
100             options[k] = v
101
102     try:
103         (visitor, output) = aafigure.render(text, outfn, options)
104         output.close()
105     except aafigure.UnsupportedFormatError, e:
106         raise MscgenError(str(e))
107
108     extra = None
109     if options['format'].lower() == 'svg':
110         extra = visitor.get_size_attrs()
111         f = file(metadata_fname, 'w')
112         f.write(extra)
113         f.close()
114
115     return relfn, outfn, id, extra
116
117
118 def render_html(self, node, text, options, prefix=DEFAULT_PREFIX, imgcls=None):
119     try:
120         options['format'] = self.builder.config.aafig_format['html']
121         fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
122     except AafigError, exc:
123         self.builder.warn('aafigure error: ' + str(exc))
124         raise nodes.SkipNode
125
126     self.body.append(self.starttag(node, 'p', CLASS='aafigure'))
127     if fname is None:
128         self.body.append(self.encode(text))
129     else:
130         imgcss = imgcls and 'class="%s"' % imgcls or ''
131         if options['format'].lower() == 'svg':
132             self.body.append('<object type="image/svg+xml" data="%s" %s %s />'
133                     (fname, extra, imgcss))
134         else:
135             self.body.append('<img src="%s" alt="%s" %s/>\n' %
136                     (fname, self.encode(text).strip(), imgcss))
137     self.body.append('</p>\n')
138     raise nodes.SkipNode
139
140
141 def html_visit(self, node):
142     render_html(self, node, node['text'], node['options'])
143
144
145 def render_latex(self, node, text, options, prefix=DEFAULT_PREFIX):
146     try:
147         options['format'] = self.builder.config.aafig_format['latex']
148         fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
149     except AafigError, exc:
150         self.builder.warn('aafigure error: ' + str(exc))
151         raise nodes.SkipNode
152
153     if fname is not None:
154         self.body.append('\\includegraphics[]{%s}' % fname)
155     raise nodes.SkipNode
156
157
158 def latex_visit(self, node):
159     render_latex(self, node, node['text'], node['options'])
160
161
162 def setup(app):
163     app.add_node(aafig, html=(html_visit, None), latex=(latex_visit, None))
164     app.add_directive('aafig', Aafig)
165     app.add_config_value('aafig_format', dict(html='svg', latex='pdf'), 'html')
166     app.add_config_value('aafig_default_options', dict(), 'html')
167