Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions features/reportlab.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Feature: ReportLab renderer
Scenario: SVG cubic path commands are translated to ReportLab path calls
Given an SVG path with move, line, cubic, and close commands
When the SVG path is rendered with the ReportLab backend
Then the ReportLab path should receive the expected drawing commands
57 changes: 57 additions & 0 deletions features/steps/reportlab_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2014, Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain
# rights in this software.

from behave import *

import unittest.mock
import xml.etree.ElementTree as xml

import test
import toyplot.reportlab


@given(u'an SVG path with move, line, cubic, and close commands')
def step_impl(context):
context.svg = xml.Element(
"svg",
width="10px",
height="10px",
style="border-style:none",
)
xml.SubElement(
context.svg,
"path",
d="M 0 0 L 1 1 C 2 3 4 5 6 7 Z",
style="fill:none;stroke:black;stroke-width:1",
)


@when(u'the SVG path is rendered with the ReportLab backend')
def step_impl(context):
context.path = unittest.mock.Mock()
context.canvas = unittest.mock.Mock()
context.canvas.beginPath.return_value = context.path
toyplot.reportlab.render(context.svg, context.canvas)


@then(u'the ReportLab path should receive the expected drawing commands')
def step_impl(context):
test.assert_equal(context.canvas.beginPath.call_count, 1)
test.assert_sequence_equal(
context.path.moveTo.call_args_list,
[unittest.mock.call(0.0, 0.0)],
)
test.assert_sequence_equal(
context.path.lineTo.call_args_list,
[unittest.mock.call(1.0, 1.0)],
)
test.assert_sequence_equal(
context.path.curveTo.call_args_list,
[unittest.mock.call(2.0, 3.0, 4.0, 5.0, 6.0, 7.0)],
)
test.assert_equal(context.path.close.call_count, 1)
test.assert_sequence_equal(
context.canvas.drawPath.call_args_list,
[unittest.mock.call(context.path)],
)
27 changes: 18 additions & 9 deletions toyplot/reportlab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ def set_stroke_color(canvas, color):
canvas.setStrokeColorRGB(color["r"], color["g"], color["b"])
canvas.setStrokeAlpha(color["a"].item())

def draw_svg_path(path, commands):
while commands:
command = commands.pop(0)
if command == "L":
path.lineTo(
as_float(commands.pop(0)), as_float(commands.pop(0)))
elif command == "M":
path.moveTo(
as_float(commands.pop(0)), as_float(commands.pop(0)))
elif command == "C":
path.curveTo(
as_float(commands.pop(0)), as_float(commands.pop(0)),
as_float(commands.pop(0)), as_float(commands.pop(0)),
as_float(commands.pop(0)), as_float(commands.pop(0)))
elif command in ["Z", "z"]:
path.close()

def render_element(root, element, canvas, styles):
canvas.saveState()

Expand Down Expand Up @@ -243,15 +260,7 @@ def render_element(root, element, canvas, styles):
set_stroke_color(canvas, stroke)
canvas.setLineCap(get_line_cap(current_style))
path = canvas.beginPath()
commands = element.get("d").split()
while commands:
command = commands.pop(0)
if command == "L":
path.lineTo(
as_float(commands.pop(0)), as_float(commands.pop(0)))
elif command == "M":
path.moveTo(
as_float(commands.pop(0)), as_float(commands.pop(0)))
draw_svg_path(path, element.get("d").split())
canvas.drawPath(path)
elif element.tag == "polygon":
fill, fill_gradient = get_fill(root, current_style)
Expand Down
Loading