349 lines
12 KiB
Python
349 lines
12 KiB
Python
from io import BytesIO
|
|
import cgm_input
|
|
import cgm_enums
|
|
import cgm_parse
|
|
|
|
import pytest
|
|
|
|
import inkex
|
|
|
|
|
|
def stream_commands(*commands):
|
|
conv = cgm_input.CGMConverter()
|
|
for command in commands:
|
|
conv.stream(command)
|
|
return conv.svg
|
|
|
|
|
|
def test_polygon_set():
|
|
"""Test polygon sets with re-shuffling and points, as well as fill and stroke."""
|
|
data = [
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.PolygonSet(
|
|
[
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(500, 500), cgm_enums.PolygonSetLineTypeEnum.VISIBLE
|
|
),
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(800, 1000),
|
|
cgm_enums.PolygonSetLineTypeEnum.INVISIBLE,
|
|
),
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(1100, 500),
|
|
cgm_enums.PolygonSetLineTypeEnum.CLOSE_VISIBLE,
|
|
),
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(600, 600), cgm_enums.PolygonSetLineTypeEnum.VISIBLE
|
|
),
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(800, 800), cgm_enums.PolygonSetLineTypeEnum.VISIBLE
|
|
),
|
|
cgm_enums.PolygonSetEntry(
|
|
cgm_enums.Point(1000, 600),
|
|
cgm_enums.PolygonSetLineTypeEnum.CLOSE_VISIBLE,
|
|
),
|
|
]
|
|
),
|
|
]
|
|
|
|
svg = stream_commands(*data)
|
|
|
|
assert (
|
|
str(svg[1][0].path)
|
|
== "M 800 1000 L 1100 500 L 500 500 Z M 600 600 L 800 800 L 1000 600 Z"
|
|
)
|
|
assert (
|
|
str(svg[1][1].path)
|
|
== "M 800 1000 M 1100 500 L 500 500 L 800 1000 M 600 600 L 800 800 L 1000 600 L 600 600 Z"
|
|
)
|
|
|
|
|
|
def test_defaults_replacement():
|
|
"""Check that the metafile defaults replacement is applied to every page"""
|
|
svg = stream_commands(
|
|
cgm_parse.MetafileDefaultsReplacement(
|
|
data=(
|
|
cgm_parse.VDCExtent(
|
|
first_corner=cgm_enums.Point(x=0, y=0),
|
|
second_corner=cgm_enums.Point(x=4095, y=4095),
|
|
),
|
|
)
|
|
),
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.EndPicture(),
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.EndPicture(),
|
|
)
|
|
# Check that we now have two pages with the specified width/height
|
|
assert len(svg.namedview) == 2
|
|
assert isinstance(svg.namedview[0], inkex.Page)
|
|
assert svg.namedview[0].width == 4095
|
|
assert svg.namedview[0].height == 4095
|
|
assert isinstance(svg.namedview[1], inkex.Page)
|
|
assert svg.namedview[1].width == 4095
|
|
assert svg.namedview[1].height == 4095
|
|
|
|
|
|
def test_rectangle():
|
|
"""Draw a rectangle (fill + edge) with indexed colours"""
|
|
svg = stream_commands(
|
|
cgm_parse.ColourTable(
|
|
colour_index=cgm_enums.IndexColour(index=0),
|
|
colours=[
|
|
cgm_enums.DirectColour(v1=255, v2=255, v3=255, v4=0),
|
|
cgm_enums.DirectColour(v1=255, v2=0, v3=0, v4=0),
|
|
cgm_enums.DirectColour(v1=255, v2=0, v3=255, v4=0),
|
|
cgm_enums.DirectColour(v1=255, v2=255, v3=0, v4=0),
|
|
],
|
|
),
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.FillColour(cgm_enums.IndexColour(index=2)),
|
|
cgm_parse.EdgeColour(cgm_enums.IndexColour(index=3)),
|
|
cgm_parse.Rectangle(
|
|
p1=cgm_enums.Point(x=10, y=20), p2=cgm_enums.Point(x=30, y=50)
|
|
),
|
|
cgm_parse.EdgeVisibility(visibility=cgm_enums.EdgeVisibilityEnum.ON),
|
|
cgm_parse.InteriorStyle(interior_style=cgm_enums.InteriorStyleEnum.SOLID),
|
|
cgm_parse.Rectangle(
|
|
p1=cgm_enums.Point(x=30, y=40), p2=cgm_enums.Point(x=70, y=50)
|
|
),
|
|
)
|
|
|
|
assert len(svg[1]) == 2
|
|
assert isinstance(svg[1][0], inkex.Rectangle)
|
|
assert svg[1][0].left == 10
|
|
assert svg[1][0].top == 20
|
|
assert svg[1][0].width == 20
|
|
assert svg[1][0].height == 30
|
|
|
|
assert svg[1][0].style("fill") == None
|
|
assert svg[1][0].style("stroke") == None
|
|
assert isinstance(svg[1][1], inkex.Rectangle)
|
|
assert svg[1][1].style("fill") == inkex.Color([255, 0, 255])
|
|
assert svg[1][1].style("stroke") == inkex.Color([255, 255, 0])
|
|
|
|
|
|
def test_circle():
|
|
"""Draw a circle, assert fill and stroke"""
|
|
svg = stream_commands(
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.FillColour(cgm_enums.DirectColour(255, 255, 0)),
|
|
cgm_parse.InteriorStyle(interior_style=cgm_enums.InteriorStyleEnum.SOLID),
|
|
cgm_parse.EdgeColour(cgm_enums.DirectColour(0, 127, 127)),
|
|
cgm_parse.EdgeVisibility(visibility=cgm_enums.EdgeVisibilityEnum.ON),
|
|
cgm_parse.Circle(cgm_enums.Point(x=10, y=20), 10),
|
|
)
|
|
|
|
assert len(svg[1]) == 1
|
|
circle = svg[1][0]
|
|
assert isinstance(circle, inkex.Circle)
|
|
assert circle.center == 10 + 20j
|
|
assert circle.radius == 10
|
|
assert circle.style("fill") == inkex.Color([255, 255, 0])
|
|
assert circle.style("stroke") == inkex.Color([0, 127, 127])
|
|
|
|
|
|
def test_polyline():
|
|
"""Draw a polyline, assert no fill and stroke taken from Edge config"""
|
|
svg = stream_commands(
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.FillColour(cgm_enums.DirectColour(255, 255, 0)),
|
|
cgm_parse.InteriorStyle(interior_style=cgm_enums.InteriorStyleEnum.SOLID),
|
|
cgm_parse.EdgeColour(cgm_enums.DirectColour(0, 127, 127)),
|
|
cgm_parse.LineColour(cgm_enums.DirectColour(0, 30, 40)),
|
|
cgm_parse.EdgeVisibility(visibility=cgm_enums.EdgeVisibilityEnum.ON),
|
|
cgm_parse.Polyline(
|
|
points=[
|
|
cgm_enums.Point(x=580, y=286),
|
|
cgm_enums.Point(x=630, y=329),
|
|
cgm_enums.Point(x=636, y=325),
|
|
cgm_enums.Point(x=630, y=329),
|
|
]
|
|
),
|
|
cgm_parse.DisjointPolyline(
|
|
points=[
|
|
cgm_enums.Point(x=390, y=388),
|
|
cgm_enums.Point(x=388, y=386),
|
|
cgm_enums.Point(x=369, y=391),
|
|
cgm_enums.Point(x=369, y=398),
|
|
]
|
|
),
|
|
)
|
|
|
|
assert len(svg[1]) == 2
|
|
polyline = svg[1][0]
|
|
assert isinstance(polyline, inkex.PathElement)
|
|
assert polyline.path == inkex.Path("M 580, 286 L 630, 329 L 636 325 L 630 329")
|
|
assert polyline.style("fill") == None
|
|
assert polyline.style("stroke") == inkex.Color([0, 30, 40])
|
|
|
|
disjoint = svg[1][1]
|
|
assert isinstance(disjoint, inkex.PathElement)
|
|
assert disjoint.path == inkex.Path("M 390 388 L 388 386 M 369 391 L 369 398")
|
|
assert disjoint.style("fill") == None
|
|
assert disjoint.style("stroke") == inkex.Color([0, 30, 40])
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"linestyle, expected",
|
|
[
|
|
(cgm_enums.LineTypeEnum.DASH, [9, 9]),
|
|
(cgm_enums.LineTypeEnum.SOLID, []),
|
|
(cgm_enums.LineTypeEnum.PRIVATE, []),
|
|
(cgm_enums.LineTypeEnum.DASH_DOT, [12, 6, 3, 6]),
|
|
(cgm_enums.LineTypeEnum.DOT, [3, 3]),
|
|
(cgm_enums.LineTypeEnum.DASH_DOT_DOT, [12, 6, 3, 6, 3, 6]),
|
|
],
|
|
)
|
|
def test_line_styles(linestyle, expected):
|
|
svg = stream_commands(
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.EdgeColour(cgm_enums.DirectColour(0, 127, 127)),
|
|
cgm_parse.EdgeWidth(3),
|
|
cgm_parse.EdgeType(linestyle),
|
|
cgm_parse.EdgeVisibility(visibility=cgm_enums.EdgeVisibilityEnum.ON),
|
|
cgm_parse.Circle(cgm_enums.Point(x=10, y=20), 10),
|
|
)
|
|
assert len(svg[1]) == 1
|
|
assert svg[1][0].style("stroke-dasharray") == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"command, expected",
|
|
[
|
|
(
|
|
cgm_parse.Polybezier(
|
|
cgm_enums.PolybezierContinuityEnum.CONTINUOUS,
|
|
[
|
|
cgm_enums.Point(5, 5),
|
|
cgm_enums.Point(5, 10),
|
|
cgm_enums.Point(10, 10),
|
|
cgm_enums.Point(10, 5),
|
|
cgm_enums.Point(10, 0),
|
|
cgm_enums.Point(15, 0),
|
|
cgm_enums.Point(15, 5),
|
|
],
|
|
),
|
|
f"M 5 5 C 5 10 10 10 10 5 C 10 0 15 0 15 5",
|
|
),
|
|
(
|
|
cgm_parse.Polybezier(
|
|
cgm_enums.PolybezierContinuityEnum.DISCONTINUOUS,
|
|
[
|
|
cgm_enums.Point(5, 5),
|
|
cgm_enums.Point(5, 10),
|
|
cgm_enums.Point(10, 10),
|
|
cgm_enums.Point(10, 5),
|
|
cgm_enums.Point(10, 2),
|
|
cgm_enums.Point(10, 0),
|
|
cgm_enums.Point(15, 0),
|
|
cgm_enums.Point(15, 5),
|
|
],
|
|
),
|
|
f"M 5 5 C 5 10 10 10 10 5 M 10 2 C 10 0 15 0 15 5",
|
|
),
|
|
],
|
|
)
|
|
def test_polybezier(command, expected):
|
|
svg = stream_commands(
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.LineColour(cgm_enums.DirectColour(0, 127, 127)),
|
|
cgm_parse.LineWidth(3),
|
|
cgm_parse.LineType(cgm_enums.LineTypeEnum.SOLID),
|
|
command,
|
|
)
|
|
assert len(svg[1]) == 1
|
|
assert int(svg[1][0].style("stroke-width")) == 3
|
|
assert svg[1][0].path == inkex.Path(expected)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"command, expected",
|
|
[
|
|
(
|
|
cgm_parse.Ellipse(
|
|
cgm_enums.Point(5, 5), cgm_enums.Point(5, 10), cgm_enums.Point(10, 10)
|
|
),
|
|
f"M 0 0 a 8.09017 3.09017 58.2825 1 1 5 10 a 8.09017 3.09017 58.2825 0 1 -5 -10 z",
|
|
),
|
|
(
|
|
cgm_parse.CircularArc3Point(
|
|
cgm_enums.Point(5, 5), cgm_enums.Point(5, 10), cgm_enums.Point(10, 10)
|
|
),
|
|
f"m 10 10 a 3.53553 3.53553 0 0 1 -5 0 a 3.53553 3.53553 0 0 1 -2.66454e-15 -5",
|
|
),
|
|
(
|
|
cgm_parse.CircularArc3PointClose(
|
|
cgm_enums.Point(5, 5),
|
|
cgm_enums.Point(5, 10),
|
|
cgm_enums.Point(8, 11),
|
|
cgm_enums.ArcClosureEnum.CHORD,
|
|
),
|
|
f"m 8 11 a 3.53553 3.53553 0 0 1 -3.66228 -1.91886 a 3.53553 3.53553 0 0 1 0.662278 -4.08114 z",
|
|
),
|
|
(
|
|
cgm_parse.CircularArc3PointClose(
|
|
cgm_enums.Point(5, 5),
|
|
cgm_enums.Point(5, 10),
|
|
cgm_enums.Point(8, 11),
|
|
cgm_enums.ArcClosureEnum.PIE,
|
|
),
|
|
f"m 8 11 a 3.53553 3.53553 0 0 1 -3.66228 -1.91886 a 3.53553 3.53553 0 0 1 0.662278 -4.08114 l 2.5 2.5 z",
|
|
),
|
|
(
|
|
cgm_parse.CircularArcCentre(cgm_enums.Point(5, 5), 3, 6, 0, 5, 5),
|
|
f"m 7.23607 9.47214 a 5 5 0 0 1 -2.23607 0.527864",
|
|
),
|
|
(
|
|
cgm_parse.CircularArcCentreClose(
|
|
cgm_enums.Point(5, 5), 3, 6, 0, 5, 5, cgm_enums.ArcClosureEnum.PIE
|
|
),
|
|
f"m 7.23607 9.47214 a 5 5 0 0 1 -2.23607 0.527864 l 0 -5 z",
|
|
),
|
|
],
|
|
)
|
|
def test_ellipse_arc(command, expected):
|
|
svg = stream_commands(cgm_parse.BeginPicture(""), command)
|
|
assert len(svg[1]) == 1
|
|
assert svg[1][0].path == inkex.Path(expected), str(svg[1][0].path)
|
|
|
|
|
|
def test_text():
|
|
svg = stream_commands(
|
|
cgm_parse.BeginPicture(""),
|
|
cgm_parse.FontList(fonts=["Times-Roman", "Helvetica"]),
|
|
cgm_parse.TextFontIndex(index=2),
|
|
cgm_parse.CharacterHeight(10),
|
|
cgm_parse.CharacterOrientation(0, 10, 10, 0),
|
|
cgm_parse.TextColour(cgm_enums.DirectColour(255, 120, 5)),
|
|
cgm_parse.TextAlignment(
|
|
cgm_enums.TextHorizontalAlignmentEnum.CENTER,
|
|
cgm_enums.TextVerticalAlignmentEnum.HALF,
|
|
0,
|
|
0,
|
|
),
|
|
cgm_parse.CharacterExpansionFactor(1.5),
|
|
cgm_parse.CharacterSpacing(1.5),
|
|
cgm_parse.Text(
|
|
point=cgm_enums.Point(x=105.0, y=290.0),
|
|
flag=cgm_enums.TextFinalFlag.FINAL,
|
|
string="Text in Helvetica",
|
|
),
|
|
)
|
|
assert len(svg[1]) == 1
|
|
text = svg[1][0]
|
|
assert len(text) == 1
|
|
assert isinstance(text, inkex.TextElement)
|
|
assert isinstance(text[0], inkex.Tspan)
|
|
assert text[0].text == "Text in Helvetica"
|
|
assert text[0].style("font-family") == "Helvetica"
|
|
assert float(text.get("x")) == 105
|
|
assert float(text.get("y")) == -290
|
|
assert text[0].style("font-size") == 10
|
|
assert text.style("font-size") == 10
|
|
assert text.style("text-anchor") == "middle"
|
|
assert text[0].style("fill") == inkex.Color([255, 120, 5])
|
|
assert text[0].style("font-stretch") == "150.0%"
|
|
assert text.get("dy") == "0.4em"
|
|
assert text[0].style("letter-spacing") == "1.5"
|
|
assert text.transform == inkex.Transform((1, 0, 0, -1, 0, 0))
|