def _update_path(self): x, y = self.mouse() path = Path() if len(self._points) > 0: first = True for i in range(len(self._points)): # Construct the path. pt = self._points[i] if first: path.moveto(pt.x, pt.y) first = False else: if pt.cmd == CLOSE: path.close() elif pt.cmd == MOVETO: path.moveto(pt.x, pt.y) elif pt.cmd == LINETO: path.lineto(pt.x, pt.y) elif pt.cmd == CURVETO: path.curveto(pt.ctrl1.x, pt.ctrl1.y, pt.ctrl2.x, pt.ctrl2.y, pt.x, pt.y) # Set the current path, self.path = path
def parse_circle(e): x = float(get_attribute(e, "cx")) y = float(get_attribute(e, "cy")) r = float(get_attribute(e, "r")) p = Path() p.ellipse(x, y, r*2, r*2) p.close() return p
def parse_circle(e): x = float(get_attribute(e, "cx")) y = float(get_attribute(e, "cy")) r = float(get_attribute(e, "r")) p = Path() p.ellipse(x, y, r * 2, r * 2) p.close() return p
def parse_oval(e): x = float(get_attribute(e, "cx")) y = float(get_attribute(e, "cy")) w = float(get_attribute(e, "rx")) * 2 h = float(get_attribute(e, "ry")) * 2 p = Path() p.ellipse(x, y, w, h) p.close() return p
def parse_oval(e): x = float(get_attribute(e, "cx")) y = float(get_attribute(e, "cy")) w = float(get_attribute(e, "rx"))*2 h = float(get_attribute(e, "ry"))*2 p = Path() p.ellipse(x, y, w, h) p.close() return p
def parse_circle(e): cx = float(get_attribute(e, "cx")) cy = float(get_attribute(e, "cy")) r = float(get_attribute(e, "r")) if r < 0: print >> sys.stderr, "Error: invalid negative value for <circle> attribute r=\"%s\"" % r r = 0 p = Path() p.ellipse(cx, cy, r*2, r*2) p.close() return p
def parse_circle(e): cx = float(get_attribute(e, "cx")) cy = float(get_attribute(e, "cy")) r = float(get_attribute(e, "r")) if r < 0: print >> sys.stderr, "Error: invalid negative value for <circle> attribute r=\"%s\"" % r r = 0 p = Path() p.ellipse(cx, cy, r * 2, r * 2) p.close() return p
def star(position, points, outer, inner): p = Path() p.moveto(position.x, position.y + outer / 2) # Calculate the points of the star. for i in xrange(1, points * 2): angle = i * pi / points radius = i % 2 and inner / 2 or outer / 2 x = position.x + radius * sin(angle) y = position.y + radius * cos(angle) p.lineto(x, y) p.close() return p
def parse_ellipse(e): cx = float(get_attribute(e, "cx")) cy = float(get_attribute(e, "cy")) rx = float(get_attribute(e, "rx")) ry = float(get_attribute(e, "ry")) if rx < 0: print >> sys.stderr, "Error: invalid negative value for <ellipse> attribute rx=\"%s\"" % rx rx = 0 if ry < 0: print >> sys.stderr, "Error: invalid negative value for <ellipse> attribute ry=\"%s\"" % ry ry = 0 p = Path() p.ellipse(cx, cy, rx * 2, ry * 2) p.close() return p
def connect(points, closed=True): """Connects all points in a path.""" if points is None: return None if len(points) < 2: return None points = list(points) start = points[0] p = Path() p.moveto(start.x, start.y) for point in points[1:]: p.lineto(point.x, point.y) if closed: p.close() p.stroke = Color.BLACK p.strokeWidth = 1.0 return p
def polygon(position, radius, sides, align): """Draw a polygon.""" p = Path() x, y, r = position.x, position.y, radius sides = max(sides, 3) a = 360.0 / sides da = 0 if align: x0, y0 = coordinates(x, y, r, 0) x1, y1 = coordinates(x, y, r, a) da = -angle(x1, y1, x0, y0) for i in xrange(sides): x1, y1 = coordinates(x, y, r, (a*i) + da) if i == 0: p.moveto(x1, y1) else: p.lineto(x1, y1) p.close() return p
def polygon(position, radius, sides, align): """Draw a polygon.""" p = Path() x, y, r = position.x, position.y, radius sides = max(sides, 3) a = 360.0 / sides da = 0 if align: x0, y0 = coordinates(x, y, r, 0) x1, y1 = coordinates(x, y, r, a) da = -angle(x1, y1, x0, y0) for i in xrange(sides): x1, y1 = coordinates(x, y, r, (a * i) + da) if i == 0: p.moveto(x1, y1) else: p.lineto(x1, y1) p.close() return p
def parse_polygon(e): d = get_attribute(e, "points", default="") d = d.replace(" ", ",") d = d.replace("-", ",") d = d.split(",") points = [] for x in d: if x != "": points.append(float(x)) autoclosepath = True if (e.tagName == "polyline") : autoclosepath = False p = Path() p.moveto(points[0], points[1]) for i in range(len(points)/2): p.lineto(points[i*2], points[i*2+1]) if autoclosepath: p.close() return p
def parse_polygon(e): d = get_attribute(e, "points", default="") d = d.replace(" ", ",") d = d.replace("-", ",") d = d.split(",") points = [] for x in d: if x != "": points.append(float(x)) autoclosepath = True if (e.tagName == "polyline"): autoclosepath = False p = Path() p.moveto(points[0], points[1]) for i in range(len(points) / 2): p.lineto(points[i * 2], points[i * 2 + 1]) if autoclosepath: p.close() return p
def parse_path(e): d = get_attribute(e, "d", default="") # Divide the path data string into segments. # Each segment starts with a path command, # usually followed by coordinates. segments = [] i = 0 for j in range(len(d)): commands = ["M", "m", "Z", "z", "L", "l", "H", "h", "V", "v", "C","c", "S", "s", "A"] if d[j] in commands: segments.append(d[i:j].strip()) i = j segments.append(d[i:].strip()) segments.remove("") previous_command = "" # Path origin (moved by MOVETO). x0 = 0 y0 = 0 # The current point in the path. dx = 0 dy = 0 # The previous second control handle. dhx = 0 dhy = 0 path = Path() for segment in segments: command = segment[0] if command in ["Z", "z"]: path.close() else: # The command is a pen move, line or curve. # Get the coordinates. points = segment[1:].strip() points = points.replace("-", ",-") points = points.replace(" ", ",") points = re.sub(",+", ",", points) points = points.strip(",") points = [float(i) for i in points.split(",")] # Absolute MOVETO. # Move the current point to the new coordinates. if command == "M": for i in range(len(points)/2): path.moveto(points[i*2], points[i*2+1]) dx = points[i*2] dy = points[i*2+1] x0 = dx y0 = dy # Relative MOVETO. # Offset from the current point. elif command == "m": for i in range(len(points)/2): path.moveto(dx+points[i*2], dy+points[i*2+1]) dx += points[i*2] dy += points[i*2+1] x0 = dx y0 = dy # Absolute LINETO. # Draw a line from the current point to the new coordinate. elif command == "L": for i in range(len(points)/2): path.lineto(points[i*2], points[i*2+1]) dx = points[i*2] dy = points[i*2+1] # Relative LINETO. # Offset from the current point. elif command == "l": for i in range(len(points)/2): path.lineto(dx+points[i*2], dy+points[i*2+1]) dx += points[i*2] dy += points[i*2+1] # Absolute horizontal LINETO. # Only the vertical coordinate is supplied. elif command == "H": for i in range(len(points)): path.lineto(points[i], dy) dx = points[i] # Relative horizontal LINETO. # Offset from the current point. elif command == "h": for i in range(len(points)): path.lineto(dx+points[i], dy) dx += points[i] # Absolute vertical LINETO. # Only the horizontal coordinate is supplied. if command == "V": for i in range(len(points)): path.lineto(dx, points[i]) dy = points[i] # Relative vertical LINETO. # Offset from the current point. elif command == "v": for i in range(len(points)): path.lineto(dx, dy+points[i]) dy += points[i] # Absolute CURVETO. # Draw a bezier with given control handles and destination. elif command == "C": for i in range(len(points)/6): path.curveto(points[i*6], points[i*6+1], points[i*6+2], points[i*6+3], points[i*6+4], points[i*6+5]) dhx = points[i*6+2] dhy = points[i*6+3] dx = points[i*6+4] dy = points[i*6+5] # Relative CURVETO. # Offset from the current point. elif command == "c": for i in range(len(points)/6): path.curveto(dx+points[i*6], dy+points[i*6+1], dx+points[i*6+2], dy+points[i*6+3], dx+points[i*6+4], dy+points[i*6+5]) dhx = dx+points[i*6+2] dhy = dy+points[i*6+3] dx += points[i*6+4] dy += points[i*6+5] # Absolute reflexive CURVETO. # Only the second control handle is given, # the first is the reflexion of the previous handle. elif command == "S": for i in range(len(points)/4): if previous_command not in ["C", "c", "S", "s"]: dhx = dx dhy = dy else: dhx = dx-dhx dhy = dy-dhy path.curveto(dx+dhx, dy+dhy, points[i*4], points[i*4+1], points[i*4+2], points[i*4+3]) dhx = points[i*4] dhy = points[i*4+1] dx = points[i*4+2] dy = points[i*4+3] # Relative reflexive CURVETO. # Offset from the current point. elif command == "s": for i in range(len(points)/4): if previous_command not in ["C", "c", "S", "s"]: dhx = dx dhy = dy else: dhx = dx-dhx dhy = dy-dhy path.curveto(dx+dhx, dy+dhy, dx+points[i*4], dy+points[i*4+1], dx+points[i*4+2], dy+points[i*4+3]) dhx = dx+points[i*4] dhy = dy+points[i*4+1] dx += points[i*4+2] dy += points[i*4+3] # Absolute elliptical arc. elif command == "A": rx, ry, phi, large_arc_flag, sweep_flag, x2, y2 = points for p in arc.elliptical_arc_to(dx, dy, rx, ry, phi, large_arc_flag, sweep_flag, x2, y2): if len(p) == 2: path.lineto(*p) elif len(p) == 6: path.curveto(*p) dx = p[-2] dy = p[-1] previous_command = command return path
def parse_path(e): d = get_attribute(e, "d", default="") d = re.sub(r",", r" ", d) # get rid of all commas d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from commands d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from commands d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([^\s])", r"\1 \2", d) # separate commands from points d = re.sub(r"([^\s])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from points d = re.sub(r"([0-9])([+\-])", r"\1 \2", d) # separate digits when no comma d = re.sub(r"(\.[0-9]*)(\.)", r"\1 \2", d) # separate digits when no comma d = re.sub(r"([Aa](\s+[0-9]+){3})\s+([01])\s*([01])", r"\1 \3 \4 ", d) # shorthand elliptical arc path syntax d = re.sub(r"[\s\r\t\n]+", r" ", d) d = d.strip() path = Path() pp = PathParser(d) pp.reset() while not pp.isEnd(): pp.nextCommand() command = pp.command.lower() if command == 'm': p = pp.getAsCurrentPoint() path.moveto(p.x, p.y) pp.start = pp.current while not pp.isCommandOrEnd(): p = pp.getAsCurrentPoint() path.lineto(p.x, p.y) elif command == 'l': while not pp.isCommandOrEnd(): p = pp.getAsCurrentPoint() path.lineto(p.x, p.y) elif command == 'h': while not pp.isCommandOrEnd(): newP = Point((pp.isRelativeCommand() and pp.current.x or 0) + pp.getScalar(), pp.current.y) pp.current = newP path.lineto(pp.current.x, pp.current.y) elif command == 'v': while not pp.isCommandOrEnd(): newP = Point(pp.current.x, (pp.isRelativeCommand() and pp.current.y or 0) + pp.getScalar()) pp.current = newP path.lineto(pp.current.x, pp.current.y) elif command == 'c': while not pp.isCommandOrEnd(): curr = pp.current p1 = pp.getPoint() cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() path.curveto(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y) elif command == 's': while not pp.isCommandOrEnd(): curr = pp.current p1 = pp.getReflectedControlPoint() cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() path.curveto(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y) elif command == 'q': while not pp.isCommandOrEnd(): curr = pp.current cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() cp1x = curr.x + 2 / 3.0 * (cntrl.x - curr.x ) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp1y = curr.y + 2 / 3.0 * (cntrl.y - curr.y ) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp2x = cp1x + 1 / 3.0 * (cp.x - curr.x ) # CP2 = CP1 + 1 / 3 *(QP2-QP0) cp2y = cp1y + 1 / 3.0 * (cp.y - curr.y ) # CP2 = CP1 + 1 / 3 *(QP2-QP0) g.curveto(cp1x, cp1y, cp2x, cp2y, cp.x, cp.y) elif command == 't': while not pp.isCommandOrEnd(): curr = pp.current cntrl = pp.getReflectedControlPoint() pp.control = cntrl cp = pp.getAsCurrentPoint() cp1x = curr.x + 2 / 3.0 * (cntrl.x - curr.x ) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp1y = curr.y + 2 / 3.0 * (cntrl.y - curr.y ) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp2x = cp1x + 1 / 3.0 * (cp.x - curr.x ) # CP2 = CP1 + 1 / 3 *(QP2-QP0) cp2y = cp1y + 1 / 3.0 * (cp.y - curr.y ) # CP2 = CP1 + 1 / 3 *(QP2-QP0) path.curveto(cp1x, cp1y, cp2x, cp2y, cp.x, cp.y) elif command == 'a': while not pp.isCommandOrEnd(): curr = pp.current rx = pp.getScalar() ry = pp.getScalar() rot = pp.getScalar() # * (math.pi / 180.0) large = pp.getScalar() sweep = pp.getScalar() cp = pp.getAsCurrentPoint() ex = cp.x ey = cp.y segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, curr.x, curr.y) for seg in segs: bez = segmentToBezier(*seg) path.curveto(*bez) elif command == 'z': path.close() pp.current = pp.start return path
def parse_path(e): d = get_attribute(e, "d", default="") d = re.sub(r",", r" ", d) # get rid of all commas d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from commands d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from commands d = re.sub(r"([MmZzLlHhVvCcSsQqTtAa])([^\s])", r"\1 \2", d) # separate commands from points d = re.sub(r"([^\s])([MmZzLlHhVvCcSsQqTtAa])", r"\1 \2", d) # separate commands from points d = re.sub(r"([0-9])([+\-])", r"\1 \2", d) # separate digits when no comma d = re.sub(r"(\.[0-9]*)(\.)", r"\1 \2", d) # separate digits when no comma d = re.sub(r"([Aa](\s+[0-9]+){3})\s+([01])\s*([01])", r"\1 \3 \4 ", d) # shorthand elliptical arc path syntax d = re.sub(r"[\s\r\t\n]+", r" ", d) d = d.strip() path = Path() pp = PathParser(d) pp.reset() while not pp.isEnd(): pp.nextCommand() command = pp.command.lower() if command == 'm': p = pp.getAsCurrentPoint() path.moveto(p.x, p.y) pp.start = pp.current while not pp.isCommandOrEnd(): p = pp.getAsCurrentPoint() path.lineto(p.x, p.y) elif command == 'l': while not pp.isCommandOrEnd(): p = pp.getAsCurrentPoint() path.lineto(p.x, p.y) elif command == 'h': while not pp.isCommandOrEnd(): newP = Point((pp.isRelativeCommand() and pp.current.x or 0) + pp.getScalar(), pp.current.y) pp.current = newP path.lineto(pp.current.x, pp.current.y) elif command == 'v': while not pp.isCommandOrEnd(): newP = Point(pp.current.x, (pp.isRelativeCommand() and pp.current.y or 0) + pp.getScalar()) pp.current = newP path.lineto(pp.current.x, pp.current.y) elif command == 'c': while not pp.isCommandOrEnd(): curr = pp.current p1 = pp.getPoint() cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() path.curveto(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y) elif command == 's': while not pp.isCommandOrEnd(): curr = pp.current p1 = pp.getReflectedControlPoint() cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() path.curveto(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y) elif command == 'q': while not pp.isCommandOrEnd(): curr = pp.current cntrl = pp.getAsControlPoint() cp = pp.getAsCurrentPoint() cp1x = curr.x + 2 / 3.0 * (cntrl.x - curr.x) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp1y = curr.y + 2 / 3.0 * (cntrl.y - curr.y) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp2x = cp1x + 1 / 3.0 * (cp.x - curr.x) # CP2 = CP1 + 1 / 3 *(QP2-QP0) cp2y = cp1y + 1 / 3.0 * (cp.y - curr.y) # CP2 = CP1 + 1 / 3 *(QP2-QP0) g.curveto(cp1x, cp1y, cp2x, cp2y, cp.x, cp.y) elif command == 't': while not pp.isCommandOrEnd(): curr = pp.current cntrl = pp.getReflectedControlPoint() pp.control = cntrl cp = pp.getAsCurrentPoint() cp1x = curr.x + 2 / 3.0 * (cntrl.x - curr.x) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp1y = curr.y + 2 / 3.0 * (cntrl.y - curr.y) # CP1 = QP0 + 2 / 3 *(QP1-QP0) cp2x = cp1x + 1 / 3.0 * (cp.x - curr.x) # CP2 = CP1 + 1 / 3 *(QP2-QP0) cp2y = cp1y + 1 / 3.0 * (cp.y - curr.y) # CP2 = CP1 + 1 / 3 *(QP2-QP0) path.curveto(cp1x, cp1y, cp2x, cp2y, cp.x, cp.y) elif command == 'a': while not pp.isCommandOrEnd(): curr = pp.current rx = pp.getScalar() ry = pp.getScalar() rot = pp.getScalar() # * (math.pi / 180.0) large = pp.getScalar() sweep = pp.getScalar() cp = pp.getAsCurrentPoint() ex = cp.x ey = cp.y segs = arcToSegments(ex, ey, rx, ry, large, sweep, rot, curr.x, curr.y) for seg in segs: bez = segmentToBezier(*seg) path.curveto(*bez) elif command == 'z': path.close() pp.current = pp.start return path
def parse_path(e): d = get_attribute(e, "d", default="") # Divide the path data string into segments. # Each segment starts with a path command, # usually followed by coordinates. segments = [] i = 0 for j in range(len(d)): commands = [ "M", "m", "Z", "z", "L", "l", "H", "h", "V", "v", "C", "c", "S", "s", "A" ] if d[j] in commands: segments.append(d[i:j].strip()) i = j segments.append(d[i:].strip()) segments.remove("") previous_command = "" # Path origin (moved by MOVETO). x0 = 0 y0 = 0 # The current point in the path. dx = 0 dy = 0 # The previous second control handle. dhx = 0 dhy = 0 path = Path() for segment in segments: command = segment[0] if command in ["Z", "z"]: path.close() else: # The command is a pen move, line or curve. # Get the coordinates. points = segment[1:].strip() points = points.replace("-", ",-") points = points.replace(" ", ",") points = re.sub(",+", ",", points) points = points.strip(",") points = [float(i) for i in points.split(",")] # Absolute MOVETO. # Move the current point to the new coordinates. if command == "M": for i in range(len(points) / 2): path.moveto(points[i * 2], points[i * 2 + 1]) dx = points[i * 2] dy = points[i * 2 + 1] x0 = dx y0 = dy # Relative MOVETO. # Offset from the current point. elif command == "m": for i in range(len(points) / 2): path.moveto(dx + points[i * 2], dy + points[i * 2 + 1]) dx += points[i * 2] dy += points[i * 2 + 1] x0 = dx y0 = dy # Absolute LINETO. # Draw a line from the current point to the new coordinate. elif command == "L": for i in range(len(points) / 2): path.lineto(points[i * 2], points[i * 2 + 1]) dx = points[i * 2] dy = points[i * 2 + 1] # Relative LINETO. # Offset from the current point. elif command == "l": for i in range(len(points) / 2): path.lineto(dx + points[i * 2], dy + points[i * 2 + 1]) dx += points[i * 2] dy += points[i * 2 + 1] # Absolute horizontal LINETO. # Only the vertical coordinate is supplied. elif command == "H": for i in range(len(points)): path.lineto(points[i], dy) dx = points[i] # Relative horizontal LINETO. # Offset from the current point. elif command == "h": for i in range(len(points)): path.lineto(dx + points[i], dy) dx += points[i] # Absolute vertical LINETO. # Only the horizontal coordinate is supplied. if command == "V": for i in range(len(points)): path.lineto(dx, points[i]) dy = points[i] # Relative vertical LINETO. # Offset from the current point. elif command == "v": for i in range(len(points)): path.lineto(dx, dy + points[i]) dy += points[i] # Absolute CURVETO. # Draw a bezier with given control handles and destination. elif command == "C": for i in range(len(points) / 6): path.curveto(points[i * 6], points[i * 6 + 1], points[i * 6 + 2], points[i * 6 + 3], points[i * 6 + 4], points[i * 6 + 5]) dhx = points[i * 6 + 2] dhy = points[i * 6 + 3] dx = points[i * 6 + 4] dy = points[i * 6 + 5] # Relative CURVETO. # Offset from the current point. elif command == "c": for i in range(len(points) / 6): path.curveto(dx + points[i * 6], dy + points[i * 6 + 1], dx + points[i * 6 + 2], dy + points[i * 6 + 3], dx + points[i * 6 + 4], dy + points[i * 6 + 5]) dhx = dx + points[i * 6 + 2] dhy = dy + points[i * 6 + 3] dx += points[i * 6 + 4] dy += points[i * 6 + 5] # Absolute reflexive CURVETO. # Only the second control handle is given, # the first is the reflexion of the previous handle. elif command == "S": for i in range(len(points) / 4): if previous_command not in ["C", "c", "S", "s"]: dhx = dx dhy = dy else: dhx = dx - dhx dhy = dy - dhy path.curveto(dx + dhx, dy + dhy, points[i * 4], points[i * 4 + 1], points[i * 4 + 2], points[i * 4 + 3]) dhx = points[i * 4] dhy = points[i * 4 + 1] dx = points[i * 4 + 2] dy = points[i * 4 + 3] # Relative reflexive CURVETO. # Offset from the current point. elif command == "s": for i in range(len(points) / 4): if previous_command not in ["C", "c", "S", "s"]: dhx = dx dhy = dy else: dhx = dx - dhx dhy = dy - dhy path.curveto(dx + dhx, dy + dhy, dx + points[i * 4], dy + points[i * 4 + 1], dx + points[i * 4 + 2], dy + points[i * 4 + 3]) dhx = dx + points[i * 4] dhy = dy + points[i * 4 + 1] dx += points[i * 4 + 2] dy += points[i * 4 + 3] # Absolute elliptical arc. elif command == "A": rx, ry, phi, large_arc_flag, sweep_flag, x2, y2 = points for p in arc.elliptical_arc_to(dx, dy, rx, ry, phi, large_arc_flag, sweep_flag, x2, y2): if len(p) == 2: path.lineto(*p) elif len(p) == 6: path.curveto(*p) dx = p[-2] dy = p[-1] previous_command = command return path