]> git.llucax.com Git - z.facultad/75.00/informe.git/blobdiff - ext/aafig.py
Agregar índice de tablas (cuadros)
[z.facultad/75.00/informe.git] / ext / aafig.py
index 793977ec58f6f16c6d71e345d1f9fb29275b892d..87d2281f41d4be45a51086967ac686eeb503d69b 100644 (file)
@@ -8,9 +8,8 @@
 
     See the README file for details.
 
-    :copyright: Copyright 2009 by Leandro Lucarella <llucax@gmail.com> \
-        (based on sphinxcontrib.mscgen).
-    :license: BSD, see LICENSE for details.
+    :author: Leandro Lucarella <llucax@gmail.com>
+    :license: BOLA, see LICENSE for details
 """
 
 import posixpath
@@ -27,83 +26,159 @@ from sphinx.errors import SphinxError
 from sphinx.util import ensuredir
 from sphinx.util.compat import Directive
 
-import aafigure
+try:
+    import aafigure
+except ImportError:
+    aafigure = None
 
-DEFAULT_PREFIX = 'aafig'
 
-class AafigError(SphinxError):
-    category = 'aafig error'
+DEFAULT_FORMATS = dict(html='svg', latex='pdf', text=None)
 
 
-class aafig(nodes.General, nodes.Element):
-    pass
+def merge_dict(dst, src):
+    for (k, v) in src.items():
+        if k not in dst:
+            dst[k] = v
+    return dst
 
 
-class Aafig(Directive):
+def get_basename(text, options, prefix='aafig'):
+    options = options.copy()
+    if 'format' in options:
+        del options['format']
+    hashkey = text.encode('utf-8') + str(options)
+    id = sha(hashkey).hexdigest()
+    return '%s-%s' % (prefix, id)
+
+
+class AafigError(SphinxError):
+    category = 'aafig error'
+
+
+class AafigDirective(directives.images.Image):
     """
     Directive to insert an ASCII art figure to be rendered by aafigure.
     """
     has_content = True
     required_arguments = 0
-    optional_arguments = 0
-    final_argument_whitespace = False
-    option_spec = dict(
-        scale        = float,
+    own_option_spec = dict(
         line_width   = float,
         background   = str,
         foreground   = str,
         fill         = str,
-        aspect       = float,
+        aspect       = directives.nonnegative_int,
         textual      = directives.flag,
         proportional = directives.flag,
     )
+    option_spec = directives.images.Image.option_spec.copy()
+    option_spec.update(own_option_spec)
 
     def run(self):
-        node = aafig()
-        node['text'] = '\n'.join(self.content)
-       if 'textual' in self.options: self.options['textual'] = True
-       if 'proportional' in self.options: self.options['proportional'] = True
-        node['options'] = self.options
-        return [node]
-
-
-def render_aafigure(self, text, options, prefix):
+        aafig_options = dict()
+        image_attrs = dict()
+        own_options_keys = self.own_option_spec.keys() + ['scale']
+        for (k, v) in self.options.items():
+            if k in own_options_keys:
+                # convert flags to booleans
+                if v is None:
+                    v = True
+                # convert percentage to float
+                if k == 'scale' or k == 'aspect':
+                    v = float(v) / 100.0
+                aafig_options[k] = v
+                del self.options[k]
+        self.arguments = ['']
+        (image_node,) = directives.images.Image.run(self)
+        if isinstance(image_node, nodes.system_message):
+            return [image_node]
+        text = '\n'.join(self.content)
+       image_node.aafig = dict(options = aafig_options, text = text)
+        return [image_node]
+
+
+def render_aafig_images(app, doctree):
+    format_map = app.builder.config.aafig_format
+    merge_dict(format_map, DEFAULT_FORMATS)
+    for img in doctree.traverse(nodes.image):
+        if not hasattr(img, 'aafig'):
+            continue
+
+        options = img.aafig['options']
+        text = img.aafig['text']
+        format = app.builder.format
+        merge_dict(options, app.builder.config.aafig_default_options)
+        if format in format_map:
+            options['format'] = format_map[format]
+        else:
+            app.builder.warn('unsupported builder format "%s", please '
+                    'add a custom entry in aafig_format config option '
+                    'for this builder' % format)
+            img.replace_self(nodes.literal_block(text, text))
+            continue
+        if options['format'] is None:
+            img.replace_self(nodes.literal_block(text, text))
+            continue
+        try:
+            fname, outfn, id, extra = render_aafigure(app, text, options)
+        except AafigError, exc:
+            app.builder.warn('aafigure error: ' + str(exc))
+            img.replace_self(nodes.literal_block(text, text))
+            continue
+        img['uri'] = fname
+        # FIXME: find some way to avoid this hack in aafigure
+        if extra:
+            (width, height) = [x.split('"')[1] for x in extra.split()]
+            if not img.has_key('width'):
+                img['width'] = width
+            if not img.has_key('height'):
+                img['height'] = height
+
+
+def render_aafigure(app, text, options):
     """
     Render an ASCII art figure into the requested format output file.
     """
-    hashkey = text.encode('utf-8') + str(options)
-    id = sha(hashkey).hexdigest()
-    fname = '%s-%s.%s' % (prefix, id, options['format'])
-    metadata_fname = '%s.aafig' % fname
-    if hasattr(self.builder, 'imgpath'):
+
+    if aafigure is None:
+        raise AafigError('aafigure module not installed')
+
+    fname = get_basename(text, options)
+    fname = '%s.%s' % (get_basename(text, options), options['format'])
+    if hasattr(app.builder, 'imgpath'):
         # HTML
-        relfn = posixpath.join(self.builder.imgpath, fname)
-        outfn = path.join(self.builder.outdir, '_images', fname)
+        relfn = posixpath.join(app.builder.imgpath, fname)
+        outfn = path.join(app.builder.outdir, '_images', fname)
     else:
         # LaTeX
         relfn = fname
-        outfn = path.join(self.builder.outdir, fname)
+        outfn = path.join(app.builder.outdir, fname)
+    metadata_fname = '%s.aafig' % outfn
 
-    if path.isfile(outfn):
-        extra = None
-        if options['format'].lower() == 'svg':
-            f = file(metadata_fname, 'r')
-            extra = f.read()
-            f.close()
-        return relfn, outfn, id, extra
+    try:
+        if path.isfile(outfn):
+            extra = None
+            if options['format'].lower() == 'svg':
+                f = None
+                try:
+                    try:
+                        f = file(metadata_fname, 'r')
+                        extra = f.read()
+                    except:
+                        raise AafigError()
+                finally:
+                    if f is not None:
+                        f.close()
+            return relfn, outfn, id, extra
+    except AafigError:
+        pass
 
     ensuredir(path.dirname(outfn))
 
-    # merge default options
-    for (k, v) in self.builder.config.aafig_default_options.items():
-        if k not in options:
-            options[k] = v
-
     try:
         (visitor, output) = aafigure.render(text, outfn, options)
        output.close()
     except aafigure.UnsupportedFormatError, e:
-        raise MscgenError(str(e))
+        raise AafigError(str(e))
 
     extra = None
     if options['format'].lower() == 'svg':
@@ -115,53 +190,9 @@ def render_aafigure(self, text, options, prefix):
     return relfn, outfn, id, extra
 
 
-def render_html(self, node, text, options, prefix=DEFAULT_PREFIX, imgcls=None):
-    try:
-        options['format'] = self.builder.config.aafig_format['html']
-        fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
-    except AafigError, exc:
-        self.builder.warn('aafigure error: ' + str(exc))
-        raise nodes.SkipNode
-
-    self.body.append(self.starttag(node, 'p', CLASS='aafigure'))
-    if fname is None:
-        self.body.append(self.encode(text))
-    else:
-        imgcss = imgcls and 'class="%s"' % imgcls or ''
-        if options['format'].lower() == 'svg':
-            self.body.append('<object type="image/svg+xml" data="%s" %s %s />'
-                    (fname, extra, imgcss))
-        else:
-            self.body.append('<img src="%s" alt="%s" %s/>\n' %
-                    (fname, self.encode(text).strip(), imgcss))
-    self.body.append('</p>\n')
-    raise nodes.SkipNode
-
-
-def html_visit(self, node):
-    render_html(self, node, node['text'], node['options'])
-
-
-def render_latex(self, node, text, options, prefix=DEFAULT_PREFIX):
-    try:
-        options['format'] = self.builder.config.aafig_format['latex']
-        fname, outfn, id, extra = render_aafigure(self, text, options, prefix)
-    except AafigError, exc:
-        self.builder.warn('aafigure error: ' + str(exc))
-        raise nodes.SkipNode
-
-    if fname is not None:
-        self.body.append('\\includegraphics[]{%s}' % fname)
-    raise nodes.SkipNode
-
-
-def latex_visit(self, node):
-    render_latex(self, node, node['text'], node['options'])
-
-
 def setup(app):
-    app.add_node(aafig, html=(html_visit, None), latex=(latex_visit, None))
-    app.add_directive('aafig', Aafig)
-    app.add_config_value('aafig_format', dict(html='svg', latex='pdf'), 'html')
+    app.add_directive('aafig', AafigDirective)
+    app.connect('doctree-read', render_aafig_images)
+    app.add_config_value('aafig_format', DEFAULT_FORMATS, 'html')
     app.add_config_value('aafig_default_options', dict(), 'html')