summaryrefslogtreecommitdiff
path: root/sandbox/cliechti/aafigure
diff options
context:
space:
mode:
authorwiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2006-01-09 20:44:25 +0000
committerwiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2006-01-09 20:44:25 +0000
commitd77fdfef70e08114f57cbef5d91707df8717ea9f (patch)
tree49444e3486c0c333cb7b33dfa721296c08ee4ece /sandbox/cliechti/aafigure
parent53cd16ca6ca5f638cbe5956988e88f9339e355cf (diff)
parent3993c4097756e9885bcfbd07cb1cc1e4e95e50e4 (diff)
downloaddocutils-0.4.tar.gz
Release 0.4: tagging released revisiondocutils-0.4
git-svn-id: http://svn.code.sf.net/p/docutils/code/tags/docutils-0.4@4268 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'sandbox/cliechti/aafigure')
-rw-r--r--sandbox/cliechti/aafigure/README.txt177
-rw-r--r--sandbox/cliechti/aafigure/aa.py93
-rw-r--r--sandbox/cliechti/aafigure/aafigure.py308
-rw-r--r--sandbox/cliechti/aafigure/aafigure_directive.py49
-rw-r--r--sandbox/cliechti/aafigure/makefile5
-rw-r--r--sandbox/cliechti/aafigure/rst2html.py27
-rw-r--r--sandbox/cliechti/aafigure/svg.py145
7 files changed, 0 insertions, 804 deletions
diff --git a/sandbox/cliechti/aafigure/README.txt b/sandbox/cliechti/aafigure/README.txt
deleted file mode 100644
index 473fa0e70..000000000
--- a/sandbox/cliechti/aafigure/README.txt
+++ /dev/null
@@ -1,177 +0,0 @@
-aafigure README
-===============
-
-Overview
---------
-
-The idea is to parse ASCII art images, embedded in reST documents and output
-an image. This would mean that simple illustrations could be embedded as
-ASCII art in the reST source and still look nice when converted to e.g. HTML
-
-Implementation
---------------
-
-Files:
-
-aafigure.py
- ASCII art parser. This is the main module.
-
-aafigure_directive.py
- Implmements the ``aafigure`` Docutils directive that takes these
- ASCII art figures ang generates SVG.
-
-aa.py
- ASCII art output backend. Intended for tests, not for the end user.
-
-rst2html.py
- Patched version that adds the ``aafigure`` Docutils directive.
-
-svg.py
- SVG output backend.
-
-
-Usage
------
-::
-
- ./rst2html.py README.txt >README.html
-
-This results in the ``README.html`` file and a ``.svg`` file for each
-``aafigure``.
-
-Display the resulting ``README.html`` file in a SVG capable browser. It has
-been tested with Firefox 1.5.
-
-TODO
-----
-
-- symbol detection: scan for some predefined shapes in the ASCII image
- and output them as symbol form a library
-- symbol libraries for UML, flowchart, electronic schematics, ...
-- more arrow heads
-- the way the image is embedded is a hack (inserting an ``<embed ..>`` tag
- trough a raw node...
-- search for ways to bring in color
-- aafigure probably need arguments like ``font-family``, ...
-- punctuation not included in strings
-
-License
--------
-
-BSD
-
-Tests
------
-
-Simple tests
-~~~~~~~~~~~~
-.. aafigure::
-
- -->
-
-.. aafigure::
-
- +---------------+
- |A box with text|
- +---------------+
-
-.. aafigure::
-
- ---> | ^| |
- <--- | || --+--
- <--> | |V |
- __ __
- | |__ +---+ |__|
- |box| ..
- +---+ Xenophon
-
-A flow chart
-~~~~~~~~~~~~
-.. aafigure::
- :scale: 0.6
-
- +---------+
- | State 1 |
- +----+----+
- |
- +<------+
- | |
- V |
- +----+----+ |
- | State 2 | |
- +----+----+ |
- | |
- V |
- +----+----+ |
- | State 3 | |
- +----+----+ |
- | |
- +-------+
-
-UML
-~~~
-No not realy, yet. But you get the idea.
-
-.. aafigure::
-
- object 1 object 2
- ----+---- ----+----
- | |
- | |
- X |
- X--------->X
- X X
- X<---------X
- X |
- | |
- | |
-
-Electronics
-~~~~~~~~~~~
-It would be cool if it could display simple schematics.
-
-.. aafigure::
-
- R1
- o------XXXX----+-----o
- 100k |
- -+- C1
- -+- 100n
- |
- o--------------+-----o
-
-- Resistor should not be filled -> can be solved by symbol detection
-- Capacitor not good, would prefer --||-- -> symbol detection
-
-Timing diagrams
-~~~~~~~~~~~~~~~
-.. aafigure::
- :scale: 0.4
-
- ___ ___
- ___| |___| |_____________________
- ___ ___
- _____| |___| |___________________
-
-Or one with descriptions:
-
-.. aafigure::
- :scale: 0.8
-
- sda_edge
- start stop
- | | | |
- v v v v
- ___ __________ ___
- SDA | | | |
- |____| |_____..._________|
- ______ _____ _..._ _____
- SCL | | | | | |
- |____| |_____| |_____|
-
- ^ ^ ^ ^ ^ ^
- | | | | | |
- | sh_in | sh_in | sh_in
- sh_out sh_out sh_out
-
- scl_edge
diff --git a/sandbox/cliechti/aafigure/aa.py b/sandbox/cliechti/aafigure/aa.py
deleted file mode 100644
index 69d62b4fd..000000000
--- a/sandbox/cliechti/aafigure/aa.py
+++ /dev/null
@@ -1,93 +0,0 @@
-"""
-Simple ASCII output of the rendered image.
-Think of it as a low resolution black and white image.
-
-(C) 2006 Chris Liechti <cliechti@gmx.net>
-"""
-
-import sys
-
-class AsciiOutputVisitor:
- """Render a list of shapes as ASCII art.
- Scaled, think of it as a low resolution black and white image
- """
-
- def __init__(self, scale=3):
- self.image = {}
- self.scale = scale
-
- def visit(self, aa_image):
- for shape in aa_image.shapes:
- shape_name = shape.__class__.__name__.lower()
- visitor_name = 'visit_%s' % shape_name
- if hasattr(self, visitor_name):
- getattr(self, visitor_name)(shape)
- else:
- print "don't know how to handle shape %r" % shape
-
- def visit_point(self, point):
- self.image[point.x*self.scale, point.y*self.scale] = '#'
-
- def visit_line(self, line):
- x1, x2 = line.start.x*self.scale, line.end.x*self.scale
- y1, y2 = line.start.y*self.scale, line.end.y*self.scale
- if x1 > x2: x1, x2 = x2, x1
- if y1 > y2: y1, y2 = y2, y1
- dx = x2 - x1
- dy = y2 - y1
- if dx > dy:
- y = y1
- if dx:
- m = float(dy)/dx
- else:
- m = 0
- for x in range(x1, x2+1):
- self.image[x,int(y)] = '#'
- y += m
- else:
- x = x1
- if dy:
- m = float(dx)/dy
- else:
- m = 0
- for y in range(y1, y2+1):
- self.image[int(x),y] = '#'
- x += m
- if line.start_style:
- self.image[line.start.x*self.scale,line.start.y*self.scale] = 'O'
- if line.end_style:
- self.image[line.end.x*self.scale,line.end.y*self.scale] = 'O'
-
- def visit_rectangle(self, rectangle):
- x1, x2 = rectangle.p1.x*self.scale, rectangle.p2.x*self.scale
- y1, y2 = rectangle.p1.y*self.scale, rectangle.p2.y*self.scale
- if x1 > x2: x1, x2 = x2, x1
- if y1 > y2: y1, y2 = y2, y1
- for y in range(y1, y2):
- for x in range(x1, x2):
- self.image[x,y] = '#'
-
- def visit_label(self, label):
- x, y = label.position.x*self.scale, label.position.y*self.scale
- for character in label.text:
- self.image[x, y] = character
- x += 1
-
- def __str__(self):
- """return a cropped image"""
- #find out size
- min_x = min_y = sys.maxint
- max_x = max_y = -sys.maxint
- for x,y in self.image:
- min_x = min(min_x, x)
- max_x = max(max_x, x)
- min_y = min(min_y, y)
- max_y = max(max_y, y)
- #render image to lines of text, fill unused fields with a dot
- result = []
- for y in range(min_y, max_y+1):
- line = []
- for x in range(min_x, max_x+1):
- line.append(self.image.get((x,y), '.'))
- result.append(''.join(line))
- return '\n'.join(result)
diff --git a/sandbox/cliechti/aafigure/aafigure.py b/sandbox/cliechti/aafigure/aafigure.py
deleted file mode 100644
index 74a3900ff..000000000
--- a/sandbox/cliechti/aafigure/aafigure.py
+++ /dev/null
@@ -1,308 +0,0 @@
-"""
-ASCII art to image converter.
-
-This is the main modlue that contains the parser.
-See svg.py and aa.py for output modules, that can reder the parsed structure.
-
-(C) 2006 Chris Liechti <cliechti@gmx.net>
-"""
-
-import pprint
-import svg
-import aa
-
-NOMINAL_SIZE = 2
-LEFT = TOP = 0
-CENTER = NOMINAL_SIZE/2
-RIGHT = BOTTOM = NOMINAL_SIZE
-
-CLASS_LINE = 'line'
-CLASS_STRING = 'str'
-CLASS_RECTANGLE = 'rect'
-
-# - - - - - - - - - - - - - - Shapes - - - - - - - - - - - - - - -
-class Point:
- """A single point. This class is primary use is to represent coordinates
- for the other shapes.
- """
- def __init__(self, x, y):
- self.x = x
- self.y = y
-
- def __repr__(self):
- return 'Point(%r, %r)' % (self.x, self.y)
-
-class Line:
- """Line with starting and ending point. Both ends can have arrows"""
- def __init__(self, start, end, start_style=None, end_style=None):
- self.start = start
- self.end = end
- self.start_style = start_style
- self.end_style = end_style
-
- def __repr__(self):
- return 'Line(%r, %r, %r, %r)' % (
- self.start,
- self.end,
- self.start_style,
- self.end_style
- )
-
-class Rectangle:
- """Rectangle with to edge coordiantes."""
- def __init__(self, p1, p2):
- self.p1 = p1
- self.p2 = p2
- def __repr__(self):
- return 'Rectangle(%r, %r)' % (self.p1, self.p2)
-
-class Label:
- """A label at a position"""
- def __init__(self, position, text):
- self.position = position
- self.text = text
- def __repr__(self):
- return 'Label(%r, %r)' % (self.position, self.text)
-
-
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-class AsciiArtImage:
- """This class hold a ASCII art figure and has methods to parse it.
- The resaulting list of shapes is also stored here.
- """
- ARROW_HEADS = list('<>Vv^')
-
- def __init__(self, text):
- """Take a ASCII art figure and store it, prepare for ``recognize``"""
- #XXX TODO tab expansion
- #detect size of input image
- self.image = []
- max_x = 0
- for y, line in enumerate(text.splitlines()):
- max_x = max(max_x, len(line))
- self.image.append(line)
- self.width = max_x
- self.height = y+1
- #make sure it's rectangular
- for y, line in enumerate(self.image):
- if len(line) < max_x:
- self.image[y] = line + ' '*(max_x-len(line))
- #initialize other data structures
- self.classification = [[None]*self.width for y in range(self.height)]
- self.shapes = []
- self.nominal_size = NOMINAL_SIZE
-
- def __repr__(self):
- return '%s\n%s' % (
- '\n'.join([','.join([str(self.classification[y][x])
- for x in range(self.width)])
- for y in range(self.height)]),
- pprint.pformat(self.shapes)
- )
-
- def __str__(self):
- """Return the original image"""
- return '\n'.join([self.image[y] for y in range(self.height)])
-
- def get(self, x, y):
- """Get character from image. Gives no error for access out of
- bounds, just returns a space. This simplifies the scanner
- functions.
- """
- try:
- return self.image[y][x]
- except IndexError:
- return ' '
-
- def tag(self, coordinates, classification):
- """Tag coordinates as used, store classification"""
- for x, y in coordinates:
- self.classification[y][x] = classification
-
- def recognize(self):
- """Try to convert ASCII are to vector graphics."""
- #XXX search for symbols
- #search for standard shapes
- for y in range(self.height):
- for x in range(self.width):
- #if not yet classified, check for a line
- character = self.image[y][x]
- if self.classification[y][x] != CLASS_LINE:
- if character == '-':
- self.shapes.append(self._follow_horizontal_line(x, y))
- elif character == '|':
- self.shapes.append(self._follow_vertical_line(x, y))
- elif character == '_':
- self.shapes.append(self._follow_lower_horizontal_line(x, y))
- if self.classification[y][x] is None:
- if character == 'X' and (self.get(x+1,y) == 'X' or self.get(x,y+1) == 'X'):
- self.shapes.append(self._follow_filled_rectangle(x, y))
- elif character.isalnum():
- self.shapes.append(self._follow_horizontal_string(x, y))
- elif character == '.':
- self.shapes.append(Point(x*NOMINAL_SIZE+CENTER,y*NOMINAL_SIZE+CENTER)) #XXX
-
- def _follow_vertical_line(self, x, y):
- """find a vertical line with optional arrow heads"""
- #follow line to the bottom
- _, end_y, line_end_style = self._follow_line(x, y, dy=1, line_character='|')
- #follow line to the top
- _, start_y, line_start_style = self._follow_line(x, y, dy=-1, line_character='|')
- #if a '+' follows a line, then the line is streched to hit the '+' center
- start_y_fix = end_y_fix = 0
- if self.get(x, start_y-1) == '+':
- start_y_fix = -NOMINAL_SIZE+CENTER
- if self.get(x, end_y+1) == '+':
- end_y_fix = CENTER
- #tag characters as used
- self.tag([(x, y) for y in range(start_y, end_y+1)], CLASS_LINE)
- #return the new shape object
- return Line(
- Point(x*NOMINAL_SIZE+CENTER, start_y*NOMINAL_SIZE+TOP+start_y_fix),
- Point(x*NOMINAL_SIZE+CENTER, end_y*NOMINAL_SIZE+BOTTOM+end_y_fix),
- line_start_style,
- line_end_style
- )
-
- def _follow_horizontal_line(self, x, y):
- """find a horizontal line with optional arrow heads"""
- #follow line to the right
- end_x, _, line_end_style = self._follow_line(x, y, dx=1, line_character='-')
- #follow line to the left
- start_x, _, line_start_style = self._follow_line(x, y, dx=-1, line_character='-')
- start_x_fix = end_x_fix = 0
- if self.get(start_x-1, y) == '+':
- start_x_fix = -NOMINAL_SIZE+CENTER
- if self.get(end_x+1, y) == '+':
- end_x_fix = CENTER
- self.tag([(x, y) for x in range(start_x, end_x+1)], CLASS_LINE)
- return Line(
- Point(start_x*NOMINAL_SIZE+LEFT+start_x_fix, y*NOMINAL_SIZE+CENTER),
- Point(end_x*NOMINAL_SIZE+RIGHT+end_x_fix, y*NOMINAL_SIZE+CENTER),
- line_start_style,
- line_end_style
- )
-
- def _follow_lower_horizontal_line(self, x, y):
- """find a horizontal line, the line is aligned to the bottom and a bit
- wider, so that it can be used for shapes like this:
- ___
- __| |___
- """
- #follow line to the right
- end_x, _, line_end_style = self._follow_line(x, y, dx=1, line_character='_')
- #follow line to the left
- start_x, _, line_start_style = self._follow_line(x, y, dx=-1, line_character='_')
- self.tag([(x, y) for x in range(start_x, end_x+1)], CLASS_LINE)
- return Line(
- Point(start_x*NOMINAL_SIZE+LEFT-CENTER, y*NOMINAL_SIZE+BOTTOM),
- Point(end_x*NOMINAL_SIZE+RIGHT+CENTER, y*NOMINAL_SIZE+BOTTOM),
- line_start_style,
- line_end_style
- )
-
- def _follow_line(self, x, y, dx=0, dy=0, line_character=None):
- """helper function for all the line functions"""
- #follow line in the given direction
- while 0 <= x < self.width and 0<= y < self.height and self.get(x+dx, y+dy) == line_character:
- x += dx
- y += dy
- #check for arrow head
- if self.get(x+dx, y+dy) in self.ARROW_HEADS:
- line_end_style = 'arrow' #XXX
- x += dx
- y += dy
- else:
- line_end_style = None
- return x, y, line_end_style
-
- def _follow_filled_rectangle(self, start_x, start_y):
- """detect the size of a filled rectangle. width is scanned first.
- shapes like these:
-
- XXXX
- XX
-
- are detected as two rectangles.
- """
- x = start_x
- y = start_y
- #expand as fas as possible to the right
- while x < self.width and self.get(x+1, y) == 'X':
- x += 1
- #expand height as long as the width stays the same
- while y < self.height and False not in [self.get(i,y+1) == 'X' for i in range(start_x, x+1)]:
- y += 1
- for i in range(start_y, y+1):
- self.tag([(x, i) for x in range(start_x, x+1)], CLASS_RECTANGLE)
- return Rectangle(
- Point(start_x*NOMINAL_SIZE+LEFT, start_y*NOMINAL_SIZE+TOP),
- Point(x*NOMINAL_SIZE+RIGHT, y*NOMINAL_SIZE+BOTTOM),
- )
-
- def _follow_horizontal_string(self, start_x, y):
- """find a string. may contain single spaces, but the detection is
- aborted after more than one space.
-
- Text one Text two
- """
- #follow line in the given direction
- x = start_x
- text = []
- text.append(self.get(x, y))
- is_first_space = True
- while 0 <= x < self.width \
- and (self.get(x+1, y).isalnum() \
- or (self.get(x+1, y) == ' ' and is_first_space)) \
- :
- x += 1
- text.append(self.get(x, y))
- if self.get(x, y) == ' ':
- is_first_space = False
- else:
- is_first_space = True
- if text[-1] == ' ':
- del text[-1]
- x -= 1
- self.tag([(x, y) for x in range(start_x, x+1)], CLASS_STRING)
- return Label(
- Point(start_x*NOMINAL_SIZE+LEFT, y*NOMINAL_SIZE+BOTTOM),
- ''.join(text)
- )
-
-
-def render(text):
- """helper function for tests. scan the given image and create svg output"""
- aaimg = AsciiArtImage(text)
- print text
- aaimg.recognize()
- aav = aa.AsciiOutputVisitor()
- pprint.pprint(aaimg.shapes)
- aav.visit(aaimg)
- print aav
- svgout = svg.SVGOutputVisitor(
- file('aafigure_%x.svg' % (long(hash(text)) & 0xffffffffL,), 'w'),
- scale = 10
- )
- svgout.visit(aaimg)
-
-
-if __name__ == '__main__':
- aaimg = AsciiArtImage("""
- ---> | ^| |
- <--- | || --+--
- <--> | |V |
- __ __
- | |__ +---+ |__|
- |box| ..
- +---+ Xenophon
- """)
- print aaimg
- aaimg.recognize()
- print "%r" % aaimg
- aav = aa.AsciiOutputVisitor()
- aav.visit(aaimg)
- print aav
-
diff --git a/sandbox/cliechti/aafigure/aafigure_directive.py b/sandbox/cliechti/aafigure/aafigure_directive.py
deleted file mode 100644
index d13f98f11..000000000
--- a/sandbox/cliechti/aafigure/aafigure_directive.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-implement aafigure directive
-"""
-
-import os, sys, tempfile, popen2
-import aafigure, svg
-
-from docutils import nodes
-from docutils.parsers.rst.directives import register_directive
-
-aafigure_counter = 0
-
-def AAFigureDrective(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- text = '\n'.join(content)
-
- global aafigure_counter
- aafigure_counter += 1
- output_name = 'aafigure-%i.svg' % aafigure_counter
-
- aaimg = aafigure.AsciiArtImage(text)
- #~ print text
- aaimg.recognize()
- if not options.has_key('scale'):
- options['scale'] = 1
-
- svgout = svg.SVGOutputVisitor(
- file(output_name, 'w'),
- scale = options['scale']*10,
- debug = True
- )
- svgout.visit(aaimg)
-
- # Return an image directive.
- #~ options['uri'] = os.path.basename(output_name)
- #~ return [nodes.image(output_name, **options)]
-
- attributes = {'format': 'html'}
- return [nodes.raw('', '<embed src="%s" %s/>' % (
- output_name,
- svgout.get_size_attrs()
- ), **attributes)]
-
-AAFigureDrective.content = True
-#~ AAFigureDrective.arguments = (1, 1, 1)
-AAFigureDrective.options = {'scale': float}
-
-def register():
- register_directive('aafigure', AAFigureDrective)
diff --git a/sandbox/cliechti/aafigure/makefile b/sandbox/cliechti/aafigure/makefile
deleted file mode 100644
index 7ddb89b5e..000000000
--- a/sandbox/cliechti/aafigure/makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# this makefile is for my convenience beacuse my editor has a handy shortcut to
-# run make
-
-all:
- python rst2html.py --traceback README.txt >readme.html \ No newline at end of file
diff --git a/sandbox/cliechti/aafigure/rst2html.py b/sandbox/cliechti/aafigure/rst2html.py
deleted file mode 100644
index 5dec1df40..000000000
--- a/sandbox/cliechti/aafigure/rst2html.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-
-# Author: David Goodger
-# Contact: goodger@users.sourceforge.net
-# Revision: $Revision$
-# Date: $Date$
-# Copyright: This module has been placed in the public domain.
-
-"""
-A minimal front end to the Docutils Publisher, producing HTML.
-"""
-
-import locale
-try:
- locale.setlocale(locale.LC_ALL, '')
-except:
- pass
-
-from docutils.core import publish_cmdline, Publisher, default_description
-
-import aafigure_directive
-aafigure_directive.register() # Enable the ABC directive
-
-description = ('Generates (X)HTML documents from standalone reStructuredText '
- 'sources. ' + default_description)
-
-publish_cmdline(writer_name='html', description=description)
diff --git a/sandbox/cliechti/aafigure/svg.py b/sandbox/cliechti/aafigure/svg.py
deleted file mode 100644
index b10423654..000000000
--- a/sandbox/cliechti/aafigure/svg.py
+++ /dev/null
@@ -1,145 +0,0 @@
-"""
-SVG renderer.
-
-(C) 2006 Chris Liechti <cliechti@gmx.net>
-"""
-
-from xml.sax.saxutils import escape
-
-class SVGOutputVisitor:
- """Render a list of shapes as ASCII art.
- """
-
- def __init__(self, file_like, scale = 1, unit='px', debug=False):
- self.file_like = file_like
- self.scale = scale
- self.unit = unit
- self.debug = debug
-
- def _num(self, number):
- """helper number to format numers for svg output"""
- return "%d%s" % (int(number*self.scale), self.unit)
-
- def get_size_attrs(self):
- """get image size as svg text"""
- #this function is here beacuse of a hack. the rst2html converter
- #has to know the size of the figure it inserts
- return 'width="%s" height="%s"' % (
- self._num(self.width),
- self._num(self.height)
- )
-
- def visit(self, aa_image):
- """Process the gived ASCIIArtFigure and output the shapes in
- the SVG file
- """
- self.aa_image = aa_image #save fore later XXX not optimal to do it here
- self.width = (aa_image.width+1)*aa_image.nominal_size
- self.height = (aa_image.height+1)*aa_image.nominal_size
- self.file_like.write("""\
-<?xml version="1.0" standalone="no" ?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
- "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg width="%s" height="%s" xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink">
-""" % (
- self._num(self.width),
- self._num(self.height)
- ))
-
- #~ if self.debug:
- #~ #draw a rectangle around entire image
- #~ self._rectangle(
- #~ 0,0,
- #~ aa_image.width, aa_image.height,
- #~ style = 'fill:none;',
- #~ )
-
- for shape in aa_image.shapes:
- shape_name = shape.__class__.__name__.lower()
- visitor_name = 'visit_%s' % shape_name
- if hasattr(self, visitor_name):
- getattr(self, visitor_name)(shape)
- else:
- print "don't know how to handle shape %r" % shape
-
- self.file_like.write("""</svg>""")
-
- # - - - - - - SVG drawing helpers - - - - - - -
- def _line_c(self, p1, p2):
- """Draw a line, coordinates given as complex number"""
- self._line(p1.real, p1.imag, p2.real, p2.imag)
-
- def _line(self, x1, y1, x2, y2):
- """Draw a line, coordinates given as four decimal numbers"""
- self.file_like.write("""\
-<line x1="%s" y1="%s" x2="%s" y2="%s"
- style="stroke:black; stroke-width:2px;" />
-""" % (self._num(x1), self._num(y1), self._num(x2), self._num(y2)))
-
- def _rectangle(self, x1, y1, x2, y2, style=''):
- """Draw a rectange, coordinates given as four decimal numbers.
- ``style`` is inserted in the SVG. It could be e.g. "fill:yellow"
- """
- self.file_like.write("""\
-<rect x="%s" y="%s"
- width="%s"
- height="%s"
- style="stroke:black; stroke-width:2px; %s"
-/>
-""" % (
- self._num(x1), self._num(y1),
- self._num(x2-x1), self._num(y2-y1),
- style
- ))
-
- # - - - - - - visitor function for the different shape types - - - - - - -
-
- def visit_point(self, point):
- self.file_like.write("""\
-<cirlce cx="%s" cy="%s" r="%s"
- style="fill:black; stroke:black; stroke-width:2px;" />
-""" % (self._num(point.x), self._num(point.y), self._num(2)))
-
- def visit_line(self, line):
- self.file_like.write("<!-- line -->\n")
- x1, x2 = line.start.x, line.end.x
- y1, y2 = line.start.y, line.end.y
- self._line(x1, y1, x2, y2)
- #arrows
- p1 = complex(line.start.x,line.start.y)
- p2 = complex(line.end.x,line.end.y)
- if line.start_style:
- self.file_like.write("<!-- start arrow -->\n")
- directon_vector = p1 - p2
- directon_vector /= abs(directon_vector)
- self._line_c(p1, p1-directon_vector+directon_vector*0.5j)
- self._line_c(p1, p1-directon_vector+directon_vector*-0.5j)
- if line.end_style:
- self.file_like.write("<!-- end arrow -->\n")
- directon_vector = p2 - p1
- directon_vector /= abs(directon_vector)
- self._line_c(p2, p2-directon_vector+directon_vector*0.5j)
- self._line_c(p2, p2-directon_vector+directon_vector*-0.5j)
-
- def visit_rectangle(self, rectangle):
- self._rectangle(
- rectangle.p1.x, rectangle.p1.y,
- rectangle.p2.x, rectangle.p2.y
- )
-
- def visit_label(self, label):
- # font-weight="bold"
- self.file_like.write("""\
-<text x="%s" y="%s"
- font-family="Verdana,sans-serif"
- font-size="%s"
->
- %s
-</text>
-""" % (
- self._num(label.position.x), self._num(label.position.y-0.3), #XXX static offset not good in all situations
- self._num(self.aa_image.nominal_size),
- escape(label.text)
- ))
-