#!/usr/bin/env python # -*- coding: utf-8 -*- #Copyright (c) 2009-12 Walter Bender #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal #in the Software without restriction, including without limitation the rights #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #copies of the Software, and to permit persons to whom the Software is #furnished to do so, subject to the following conditions: #The above copyright notice and this permission notice shall be included in #all copies or substantial portions of the Software. #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. import pygtk pygtk.require('2.0') import gtk import os from taconstants import HIT_RED, HIT_GREEN, HIDE_WHITE, SHOW_WHITE, \ PALETTE_COLOR, TOOLBAR_COLOR class SVG: def __init__(self): self._x = 0 self._y = 0 self._min_x = 10000 self._min_y = 10000 self._max_x = -10000 self._max_y = -10000 self._width = 0 self._height = 0 self.docks = [] self._scale = 1 self._orientation = 0 self._radius = 8 self._stroke_width = 1 self._innie = [False] self._outie = False self._innie_x1 = (9 - self._stroke_width) / 2 self._innie_y1 = 3 self._innie_x2 = (9 - self._stroke_width) / 2 self._innie_y2 = (9 - self._stroke_width) / 2 self._innie_spacer = 9 self._slot = True self._cap = False self._tab = True self._bool = False self._slot_x = 10 self._slot_y = 2 self._tail = False self._porch = False self._porch_x = self._innie_x1 + self._innie_x2 + \ 4 * self._stroke_width self._porch_y = self._innie_y2 self._expand_x = 0 self._expand_x2 = 0 self._expand_y = 0 self._expand_y2 = 0 self._second_clamp = False self._arm = True self._else = False self._draw_innies = True self._hide = False self._show = False self._collapsible = False self._show_x = 0 self._show_y = 0 self._hide_x = 0 self._hide_y = 0 self._dot_radius = 8 self._fill = "#00FF00" self._stroke = "#00A000" self._gradient_color = "#FFFFFF" self._gradient = False self.margins = [0, 0, 0, 0] """ The block construction methods typically start on the left side of a block and proceed clockwise around the block, first constructing a left-side connector ("outie"), a corner (1, -1), a slot or hat on along the top, a corner (1, 1), right side connectors ("innie"), possibly a "porch" to suggest an order of arguments, another corner (-1, 1), a tab or tail, and the fourth corner (-1, -1). """ def basic_block(self): ''' The most common block type: used for 0, 1, 2, or 3 argument commands, stacks, et al. ''' self.reset_min_max() (x, y) = self._calculate_x_y() self.margins[2] = 0 self.margins[3] = 0 svg = self.new_path(x, y) svg += self._corner(1, -1) svg += self._do_slot() svg += self._rline_to(self._expand_x, 0) xx = self._x svg += self._corner(1, 1) for i in range(len(self._innie)): if self._innie[i] is True: svg += self._do_innie() if i == 0: svg += self._rline_to(0, self._expand_y) if i == 0 and self._porch is True: svg += self._do_porch(False) elif len(self._innie) - 1 > i: svg += self._rline_to(0, 2 * self._innie_y2 + self._innie_spacer) # moved expand_y to just after first innie above # svg += self._rline_to(0, self._expand_y) svg += self._corner(-1, 1) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) if self._tab: svg += self._do_tab() else: svg += self._do_tail() svg += self._corner(-1, -1) svg += self._rline_to(0, -self._expand_y) if True in self._innie: svg += self.line_to(x, self._radius + self._innie_y2 + self._stroke_width / 2.0) svg += self._do_outie() self.calc_w_h() svg += self._close_path() svg += self.style() if self._show is True: svg += self._show_dot() if self._hide is True: svg += self._hide_dot() svg += self.footer() return self.header() + svg def invisible(self): ''' A block that is invisible but still has connectors: used when collapsing stacks. ''' self.reset_min_max() (x, y) = self._calculate_x_y() self.margins[2] = 0 self.margins[3] = 0 # calculate shape but don't include it in the svg output self.new_path(x, y) self._corner(1, -1) self._do_slot() xx = self._x self._corner(1, 1) self._corner(-1, 1) self._do_tab() self._corner(-1, -1) self.calc_w_h() self._close_path() self.style() return self.header() + self.footer() def basic_flow(self): ''' A flow block includes an arm that holds a branch in the flow ''' self.reset_min_max() (x, y) = self._calculate_x_y() self.margins[2] = 0 self.margins[3] = 0 svg = self.new_path(x, y) svg += self._corner(1, -1) svg += self._do_slot() xx = self._x svg += self._rline_to(self._expand_x, 0) if self._bool: svg += self._corner(1, 1, 90, 0, 1, True, False) elif True in self._innie: svg += self._corner(1, 1) for i in range(len(self._innie)): if self._innie[i] is True: svg += self._do_innie() svg += self._rline_to(0, self._innie_spacer) else: self.margins[2] = \ int((self._x - self._stroke_width + 0.5) * self._scale) if self._bool is True: svg += self._rline_to(0, self._radius / 2.0) svg += self._do_boolean() svg += self._rline_to(0, self._stroke_width) if self._else: svg += self._rline_to(self._radius * 3 + self._slot_x * 2, 0) else: svg += self._rline_to(self._radius + self._slot_x, 0) save_y = self._y hh = self._x svg += self._corner(1, 1) svg += self._rline_to(-self._radius, 0) if self._else: svg += self._do_tab() svg += self._rline_to(-self._radius * 2, 0) svg += self._do_tab() svg += self._inverse_corner(-1, 1, 90, 0, 0, True, False) svg += self._rline_to(0, self._expand_y) svg += self._corner(-1, 1, 90, 0, 1, False, True) svg += self.line_to(xx, self._y) if self._tab: svg += self._do_tab() else: svg += self._do_tail() svg += self._corner(-1, -1) svg += self._rline_to(0, -self._expand_y) if True in self._innie: svg += self.line_to(x, self._radius + self._innie_y2 + self._stroke_width) svg += self._close_path() self.calc_w_h() svg += self.style() if self._hide is True: svg += self._hide_dot() if self._show is True: svg += self._show_dot() svg += self.footer() if self._bool is True: # move secondary labels to arm self.margins[2] = self._radius * 1.5 * self._scale self.margins[3] = (self._max_y - save_y - self._radius + self._stroke_width) * self._scale return self.header() + svg def portfolio(self): ''' Deprecated block ''' self.reset_min_max() (x, y) = self._calculate_x_y() self.margins[0] = int(x + 2 * self._stroke_width + 0.5) self.margins[1] = int(y + self._stroke_width + 0.5 + self._slot_y) self.margins[2] = 0 self.margins[3] = 0 x += self._innie_x1 + self._innie_x2 svg = self.new_path(x, y) svg += self._corner(1, -1) svg += self._do_slot() xx = self._x svg += self._rline_to(self._expand_x, 0) svg += self._corner(1, 1) svg += self._rline_to(0, self._expand_y) for i in range(len(self._innie)): if self._innie[i] is True and i > 0 and self._draw_innies: svg += self._do_innie() svg += self._rline_to(0, 2 * self._innie_y2 + self._innie_spacer) else: svg += self._rline_to(0, 2 * self._innie_y2 + self._innie_spacer) svg += self._corner(-1, 1) svg += self.line_to(xx, self._y) svg += self._do_tab() svg += self._corner(-1, -1) for i in range(len(self._innie)): if self._innie[len(self._innie) - i - 1] is True: svg += self._rline_to(0, -2 * self._innie_y2 - self._innie_spacer) svg += self._do_reverse_innie() else: svg += self._rline_to(0, -2 * self._innie_y2 - self._innie_spacer) svg += self._close_path() self.calc_w_h() svg += self.style() svg += self.footer() return self.header() + svg def basic_box(self): ''' Basic argument style used for numbers, text, media ''' self.reset_min_max() self.set_outie(True) x = self._stroke_width / 2.0 + self._innie_x1 + self._innie_x2 self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale) self.margins[1] = int((self._stroke_width + 0.5) * self._scale) self.margins[2] = 0 self.margins[3] = 0 svg = self.new_path(x, self._stroke_width / 2.0) svg += self._rline_to(self._expand_x, 0) svg += self._rline_to(0, 2 * self._radius + self._innie_y2 + self._expand_y) svg += self._rline_to(-self._expand_x, 0) svg += self.line_to(x, self._radius + self._innie_y2 + self._stroke_width / 2.0) svg += self._do_outie() svg += self._close_path() self.calc_w_h() svg += self.style() svg += self.footer() return self.header() + svg def boolean_and_or(self): ''' Booleans are in a class of their own ''' self.reset_min_max() svg = self._start_boolean(self._stroke_width / 2.0, self._radius * 5.5 + self._stroke_width / 2.0 + self._innie_y2 + self._innie_spacer + self._expand_y) svg += self._rline_to(0, -self._radius * 3.5 - self._innie_y2 - self._innie_spacer - self._stroke_width) self._hide_x = self._x + self._radius + self._stroke_width self._hide_y = self._y self._show_x = self._x + self._radius + self._stroke_width svg += self._rarc_to(1, -1) svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) xx = self._x svg += self._rline_to(0, self._radius / 2.0) svg += self._do_boolean() svg += self._rline_to(0, self._radius * 1.5 + self._innie_y2 + self._innie_spacer) svg += self._rline_to(0, self._expand_y) svg += self._do_boolean() svg += self._rline_to(0, self._radius / 2.0) self._show_y = self._y self._show_y -= (self._innie_y1 + self._innie_y2 + self._stroke_width) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) svg += self._end_boolean() self.margins[0] = int((self._radius + self._stroke_width + 0.5) * self._scale) self.margins[1] = int(self._stroke_width * self._scale) self.margins[2] = int(self._stroke_width * self._scale) self.margins[3] = int(self._stroke_width * self._scale) return self.header() + svg def boolean_not(self, notnot): ''' Booleans are in a class of their own: not and not not ''' self.reset_min_max() if self._innie[0]: svg = self._start_boolean( self._stroke_width / 2.0, self._radius * 1.25 + self._stroke_width / 2.0) elif not notnot: svg = self._start_boolean( self._stroke_width / 2.0, self._radius * 2.0 + self._stroke_width / 2.0) else: svg = self._start_boolean( self._stroke_width / 2.0, self._radius + self._stroke_width / 2.0) svg += self._rline_to(0, -self._stroke_width) if self._innie[0]: svg += self._rline_to(0, -self._radius / 4.0) elif not notnot: svg += self._rarc_to(1, -1) svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) xx = self._x if self._innie[0]: svg += self._rline_to(0, self._radius) svg += self._do_innie() svg += self._rline_to(0, self._radius) elif not notnot: svg += self._rline_to(0, self._radius / 2.0) svg += self._do_boolean() svg += self._rline_to(0, self._radius / 2.0) else: svg += self._rline_to(0, self._radius * 2) svg += self.line_to(xx, self._y) if self._innie[0]: svg += self._rline_to(-self._radius / 2.0 - self._expand_x, 0) svg += self._rline_to(0, -self._radius / 4.0) elif not notnot: svg += self._rline_to(-self._expand_x, 0) else: svg += self._rline_to(-self._radius / 2.0 - self._expand_x, 0) svg += self._end_boolean(notnot) if notnot: self.margins[0] = int((self._radius + self._stroke_width + 0.5) * self._scale) self.margins[2] = int((self._radius + self._stroke_width + 0.5) * self._scale) else: self.margins[0] = int((self._stroke_width + 0.5) * self._scale) self.margins[2] = int((self._stroke_width + 0.5) * self._scale) self.margins[1] = int(self._stroke_width * self._scale) self.margins[3] = int(self._stroke_width * self._scale) return self.header() + svg def boolean_compare(self): ''' Booleans are in a class of their own ''' self.reset_min_max() yoffset = self._radius * 2 + 2 * self._innie_y2 + \ self._innie_spacer + self._stroke_width / 2.0 + \ self._expand_y svg = self._start_boolean(self._stroke_width / 2.0, yoffset) yoffset = -2 * self._innie_y2 - self._innie_spacer - self._stroke_width svg += self._rline_to(0, yoffset) self._hide_x = self._x + self._radius + self._stroke_width self._hide_y = self._y self._show_x = self._x + self._radius + self._stroke_width svg += self._rarc_to(1, -1) svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) svg += self._rline_to(0, self._radius) xx = self._x svg += self._do_innie() svg += self._rline_to(0, self._expand_y) if self._porch is True: svg += self._do_porch(False) else: svg += self._rline_to(0, 2 * self._innie_y2 + self._innie_spacer) svg += self._do_innie() svg += self._rline_to(0, self._radius) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) self._show_y = self._y self._show_y -= \ (self._innie_y1 + self._innie_y2 + self._stroke_width * 2) svg += self._end_boolean() self.margins[0] = int((self._radius + self._stroke_width) * self._scale) self.margins[1] = int(self._stroke_width * self._scale) self.margins[2] = int(self._stroke_width * self._scale) return self.header() + svg def triangle_up(self, colors): ''' A triangle that points up ''' self.reset_min_max() self._fill, self._stroke = colors[0], colors[1] self._width, self._height = 55 * self._scale, 55 * self._scale svg = self.new_path(5, 50) svg += self._rline_to(22.5, -45) svg += self._rline_to(22.5, 45) svg += self._close_path() svg += self.style() svg += self.footer() return self.header() + svg def triangle_down(self, colors): ''' A triangle that points down ''' self.reset_min_max() self._fill, self._stroke = colors[0], colors[1] self._width, self._height = 55 * self._scale, 55 * self._scale svg = self.new_path(5, 5) svg += self._rline_to(22.5, 45) svg += self._rline_to(22.5, -45) svg += self._close_path() svg += self.style() svg += self.footer() return self.header() + svg def turtle(self, colors): ''' Turtles are just another block ''' self.reset_min_max() self._fill, self._stroke = colors[1], colors[0] # Tail svg = ' \n' % (self._fill, self._stroke) # Feet x 4 svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) # Head svg += '' % \ (self._fill, self._stroke) # Shell svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._fill, self._stroke) svg += ' \n' % (self._stroke) svg += ' \n' % (self._stroke) svg += ' \n' % (self._stroke) self._width, self._height = 55, 55 svg += self.footer() return self.header() + svg def palette(self, width, height): ''' Just a rectangle with a hide button. ''' self.reset_min_max() self._width, self._height = width, height self._fill, self._stroke = PALETTE_COLOR, "none" svg = self._rect(width, height, 0, 0) self._hide_x = (width - self._radius) / 2 self._hide_y = (height - self._radius) / 2 svg += self._hide_dot(noscale=True) svg += self.footer() return self.header() + svg def toolbar(self, width, height): ''' Just a rectangle ''' self.reset_min_max() self._width, self._height = width, height self._fill, self._stroke = TOOLBAR_COLOR, "none" svg = self._rect(width, height, 0, 0) svg += self.footer() return self.header() + svg def clamp(self): ''' Special block for collapsible stacks; includes an 'arm" that extends down the left side of a stack and a bottom jaw to clamp the blocks. ''' self.reset_min_max() x = self._stroke_width / 2.0 y = self._stroke_width / 2.0 + self._radius self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale) self.margins[1] = int((self._stroke_width + 0.5) * self._scale) self.margins[2] = 0 self.margins[3] = 0 svg = self.new_path(x, y) svg += self._corner(1, -1) svg += self._do_slot() svg += self._rline_to(self._radius + self._stroke_width, 0) svg += self._rline_to(self._expand_x, 0) xx = self._x svg += self._corner(1, 1) if self._innie[0] is True: svg += self._do_innie() else: self.margins[2] = \ int((self._x - self._stroke_width + 0.5) * self._scale) if self._bool is True: svg += self._do_boolean() svg += self._corner(-1, 1) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) svg += self._do_tab() svg += self._inverse_corner(-1, 1, 90, 0, 0) svg += self._rline_to(0, self._expand_y) svg += self._inverse_corner(1, 1, 90, 0, 0) svg += self._do_slot() svg += self._rline_to(self._radius, 0) if self._second_clamp: svg += self._corner(-1, 1) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) svg += self._do_tab() svg += self._inverse_corner(-1, 1, 90, 0, 0) svg += self._rline_to(0, self._expand_y2) svg += self._inverse_corner(1, 1, 90, 0, 0) svg += self._do_slot() svg += self._rline_to(self._radius, 0) svg += self._corner(-1, 1) svg += self._rline_to(-self._radius - self._stroke_width, 0) svg += self._do_tab() svg += self._corner(-1, -1) svg += self._close_path() self.calc_w_h() svg += self.style() if self._collapsible: svg += self._hide_dot() svg += self.footer() return self.header() + svg def status_block(self, graphic=None): ''' Generate a status block ''' self.reset_min_max() (x, y) = self._calculate_x_y() self.margins[2] = 0 self.margins[3] = 0 svg = self.new_path(x, y) svg += self._corner(1, -1) svg += self._rline_to(self._expand_x, 0) xx = self._x svg += self._corner(1, 1) svg += self._rline_to(0, self._expand_y) svg += self._corner(-1, 1) svg += self.line_to(xx, self._y) svg += self._rline_to(-self._expand_x, 0) svg += self._corner(-1, -1) svg += self._rline_to(0, -self._expand_y) self.calc_w_h() svg += self._close_path() svg += self.style() if self._hide is True: svg += self._hide_dot() svg += self.footer() return self.header() + svg # # Utility methods # def set_tail(self, flag=True): self._tail = flag def set_draw_innies(self, flag=True): self._draw_innies = flag def set_hide(self, flag=False): self._hide = flag def set_show(self, flag=False): self._show = flag def set_collapsible(self, flag=False): self._collapsible = flag def get_width(self): return self._width def get_height(self): return self._height def get_innie_width(self): return (self._innie_x1 + self._innie_x2) * self._scale def get_slot_depth(self): return self._slot_y * self._scale def clear_docks(self): self.docks = [] def set_scale(self, scale=1): self._scale = scale def set_orientation(self, orientation=0): self._orientation = orientation def second_clamp(self, flag=False): self._second_clamp = flag def expand(self, w=0, h=0, w2=0, h2=0): self._expand_x = w self._expand_y = h self._expand_x2 = w2 self._expand_y2 = h2 def set_stroke_width(self, stroke_width=1.5): self._stroke_width = stroke_width self._calc_porch_params() def set_colors(self, colors=["#00FF00", "#00A000"]): self._fill = colors[0] self._stroke = colors[1] def set_fill_color(self, color="#00FF00"): self._fill = color def set_stroke_color(self, color="#00A000"): self._stroke = color def set_gradient(self, flag=False, color='#FFFFFF'): self._gradient = flag self._gradient_color = color def set_innie(self, innie_array=[False]): self._innie = innie_array def set_outie(self, flag=False): self._outie = flag def set_slot(self, flag=True): self._slot = flag if self._slot is True: self._cap = False def set_cap(self, flag=False): self._cap = flag if self._cap is True: self._slot = False def set_tab(self, flag=True): self._tab = flag def set_porch(self, flag=False): self._porch = flag def set_boolean(self, flag=False): self._bool = flag def set_else(self, flag=False): self._else = flag def set_arm(self, flag=True): self._arm = flag def reset_min_max(self): self._min_x = 10000 self._min_y = 10000 self._max_x = -10000 self._max_y = -10000 # # Exotic methods # def set_radius(self, radius=8): self._radius = radius def set_innie_params(self, x1=4, y1=3, x2=4, y2=4): self._innie_x1 = x1 self._innie_y1 = y1 self._innie_x2 = x2 self._innie_y2 = y2 self._calc_porch_params() def set_innie_spacer(self, innie_spacer=0): self._innie_spacer = innie_spacer def set_slot_params(self, x=12, y=4): self._slot_x = x self._slot_y = y def _calc_porch_params(self): self._porch_x = self._innie_x1 + self._innie_x2 + \ 4 * self._stroke_width self._porch_y = self._innie_y1 + self._innie_y2 + \ 4 * self._stroke_width # # SVG helper methods # def header(self, center=False): return '\n' % (self._width, self._height) + \ self._defs() + self._transform(center) def _defs(self): if self._gradient is True: return ' \n\ \n\ \n\ \n\ \n\ \n\ \n' % (self._gradient_color, self._fill, self._height / 2.0, self._width / self._scale, self._height / 2.0) else: return "" def _transform(self, center): if self._orientation != 0: orientation = "\n" % \ (self._orientation, self._width / 2.0, self._height / 2.0) else: orientation = "" if center: return "\n" % \ (-self._min_x, -self._min_y) else: return "\n%s" % \ (self._scale, self._scale, orientation) def footer(self): if self._orientation != 0: return " \n\n\n" else: return " \n\n" def style(self): if self._gradient is True: fill = "url(#linearGradient5678)" else: fill = self._fill return "%s%s;%s%s;%s%.1f;%s%s" % ( " style=\"fill:", fill, "fill-opacity:1;stroke:", self._stroke, "stroke-width:", self._stroke_width, "stroke-linecap:round;", "stroke-opacity:1;\" />\n") def text(self, x, y, size, width, string): self._x = x self._y = y self._check_min_max() self._x = x + width self._y = y - size self._check_min_max() return " %s%.1f%s%s%s%.1f%s%.1f%s%.1f%s%s%s%s%s" % ( "\n ", string, "\n \n") def image(self, x, y, w, h, path, image_data=None): self._x = x self._y = y self._check_min_max() self._x = x + w self._y = y + h self._check_min_max() if image_data is None: return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( "\n") else: return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( "\n") def _circle(self, r, cx, cy): return "%s%s%s%s%s%f%s%f%s%f%s" % \ ("\n") def _rect(self, w, h, x, y): return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("\n") def background(self, fill): return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("\n") def _check_min_max(self): if self._x < self._min_x: self._min_x = self._x if self._y < self._min_y: self._min_y = self._y if self._x > self._max_x: self._max_x = self._x if self._y > self._max_y: self._max_y = self._y def line_to(self, x, y): self._check_min_max() if self._x == x and self._y == y: return "" else: self._x = x self._y = y self._check_min_max() return "L %.1f %.1f " % (x, y) def _rline_to(self, dx, dy): if dx == 0 and dy == 0: return "" else: return self.line_to(self._x + dx, self._y + dy) def arc_to(self, x, y, r, a=90, l=0, s=1): self._check_min_max() if r == 0: return self.line_to(x, y) else: self._x = x self._y = y self._check_min_max() return "A %.1f %.1f %.1f %d %d %.1f %.1f " % ( r, r, a, l, s, x, y) def _rarc_to(self, sign_x, sign_y, a=90, l=0, s=1): if self._radius == 0: return "" else: x = self._x + sign_x * self._radius y = self._y + sign_y * self._radius return self.arc_to(x, y, self._radius, a, l, s) def _inverse_corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True): r2 = self._stroke_width + self._radius / 2.0 if start: if sign_x * sign_y == -1: svg_str = self._rline_to(sign_x * (r2 - self._stroke_width), 0) else: svg_str = self._rline_to(0, sign_y * (r2 - self._stroke_width)) x = self._x + sign_x * r2 y = self._y + sign_y * r2 svg_str += self.arc_to(x, y, r2, a, l, s) if end: if sign_x * sign_y == -1: svg_str += self._rline_to(0, sign_y * (r2 - self._stroke_width)) else: svg_str += self._rline_to(sign_x * (r2 - self._stroke_width), 0) return svg_str def _corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True): svg_str = "" if sign_x == 1 and sign_y == -1: # Upper-left corner self._hide_x = self._x + self._radius + self._stroke_width self._show_x = self._x + self._radius + self._stroke_width self._hide_y = self._y + self._stroke_width elif sign_x == 1 and sign_y == 1: # Upper-right corner if len(self._innie) == 1 and self._innie[0]: self._show_x = self._x - self._radius self._show_y = self._hide_y elif sign_x == -1 and sign_y == 1: # Lower-right corner if not (len(self._innie) == 1 and self._innie[0]): self._show_y = \ self._y - self._stroke_width if self._radius > 0: r2 = self._radius / 2.0 if start: if sign_x * sign_y == 1: svg_str += self._rline_to(sign_x * r2, 0) else: svg_str += self._rline_to(0, sign_y * r2) x = self._x + sign_x * r2 y = self._y + sign_y * r2 svg_str += self.arc_to(x, y, r2, a, l, s) if end: if sign_x * sign_y == 1: svg_str += self._rline_to(0, sign_y * r2) else: svg_str += self._rline_to(sign_x * r2, 0) return svg_str def new_path(self, x, y): """ self._min_x = x self._min_y = y self._max_x = x self._max_y = y """ self._x = x self._y = y return "