diff options
author | wiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2006-01-09 20:44:25 +0000 |
---|---|---|
committer | wiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2006-01-09 20:44:25 +0000 |
commit | d77fdfef70e08114f57cbef5d91707df8717ea9f (patch) | |
tree | 49444e3486c0c333cb7b33dfa721296c08ee4ece /sandbox/cliechti/aafigure | |
parent | 53cd16ca6ca5f638cbe5956988e88f9339e355cf (diff) | |
parent | 3993c4097756e9885bcfbd07cb1cc1e4e95e50e4 (diff) | |
download | docutils-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.txt | 177 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/aa.py | 93 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/aafigure.py | 308 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/aafigure_directive.py | 49 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/makefile | 5 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/rst2html.py | 27 | ||||
-rw-r--r-- | sandbox/cliechti/aafigure/svg.py | 145 |
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) - )) - |