Пример #1
0
def test_text_spans():
    # <tspan> is not supported in SVG Tiny 1.2 and these tags should be ignored
    # (though their contents retained, just in the wrong space). This test just
    # checks this is occurring and that support has not been added without
    # being noticed...
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <text
              style="stroke-width:0.1;font-size:1;stroke:black"
              x="0" y="1"
            >T<tspan dy="1">T</tspan></text>
        </svg>
    """)
    out = svg_to_outlines(svg)

    assert len(out) == 2

    colour_0, width_0, line_0 = out[0]
    colour_1, width_1, line_1 = out[1]

    letter_0 = Polygon(line_0)
    letter_1 = Polygon(line_1)

    letter_0_ymin = letter_0.bounds[1]
    letter_1_ymin = letter_1.bounds[1]

    assert letter_0_ymin == letter_1_ymin
Пример #2
0
def test_resolution(pixels_per_mm):
    # Check varying the resolution does correctly increase/decrease the detail
    # added to a curve
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path style="stroke-width:0.1;stroke:black" d="M0,0 Q1,1 2,0"/>
        </svg>
    """)
    out = svg_to_outlines(svg, pixels_per_mm=pixels_per_mm)

    assert len(out) == 1

    colour, width, line = out[0]

    line_buf = LineString(line).buffer(1.0 / pixels_per_mm)
    line_fine_buf = LineString(line).buffer(0.01 / pixels_per_mm)

    points_on_bezier = [
        Point(quadratic_bezier((0, 0), (10, 10), (20, 0), p / 1000.0))
        for p in range(1001)
    ]

    # All points should be within the expected tollerance for this level of
    # detail.
    assert all(line_buf.intersects(point) for point in points_on_bezier)

    # When we use an excessively fine tollerance for the detail level tested,
    # some points may not lie on the line.
    assert not all(
        line_fine_buf.intersects(point) for point in points_on_bezier)
Пример #3
0
def test_occlusion():
    # Occlusion is not supported; this test make sure this doesn't change
    # without me noticing...
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <rect
              style="fill:white;stroke-width:0.1;stroke:#00ff00"
              width="2"
              height="1"
              x="0"
              y="0"
            />
            <rect
              style="fill:white;stroke-width:0.1;stroke:#ff0000"
              width="1"
              height="1"
              x="1"
              y="0"
            />
        </svg>
    """)
    (
        (colour_0, width_0, lines_0),
        (colour_1, width_1, lines_1),
    ) = svg_to_outlines(svg)

    assert colour_0 == (0, 1, 0, 1)
    assert colour_1 == (1, 0, 0, 1)

    assert width_0 == width_1 == 1

    assert Polygon(lines_0).equals(box(0, 0, 20, 10))
    assert Polygon(lines_1).equals(box(10, 0, 20, 10))
Пример #4
0
def test_clipping():
    # Clipping is not part of the SVG Tiny 1.2 spec and clipping paths will be
    # ignored. This test checks that this doesn't change unepxectedly.
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <defs>
                <clipPath id="clip0" clipPathUnits="userSpaceOnUse">
                    <rect
                      style="fill:white"
                      width="1"
                      height="1"
                      x="-0.5"
                      y="-0.5"
                    />
                </clipPath>
            </defs>
            <rect
              clip-path="url(#clip0)"
              style="stroke-width:0.1;stroke:#00ff00"
              width="2"
              height="1"
              x="0"
              y="0"
            />
        </svg>
    """)
    ((colour, width, lines), ) = svg_to_outlines(svg)

    assert colour == (0, 1, 0, 1)
    assert width == 1

    # Expect no clipping to actually take place
    assert Polygon(lines).equals(box(0, 0, 20, 10))
Пример #5
0
def test_rect():
    # Simple case: A <rect>
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <rect
              style="stroke-width:0.1;stroke:#ffffff"
              width="2"
              height="1"
              x="0"
              y="0"
            />
        </svg>
    """)
    out = svg_to_outlines(svg)

    assert len(out) == 1
    colour, width, line = out[0]

    assert colour == (1, 1, 1, 1)
    assert width == 1

    assert len(line) == 5
    edges = set(
        tuple(sorted([start, end])) for start, end in zip(line, line[1:]))
    assert edges == set([
        ((0, 0), (0, 10)),
        ((0, 0), (20, 0)),
        ((20, 0), (20, 10)),
        ((0, 10), (20, 10)),
    ])
Пример #6
0
def test_text_paths():
    # Test for text-on-path support. This is not provided in SVG Tiny 1.2 and
    # so is not expected to work here so this test actually checks for
    # non-functioning text path support to spot if this changes in the future.
    #
    # When text path support works correctly, a 'T' will be rendered upside
    # down since the path it is on runs from right-to-left.
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1"
          xmlns:xlink="http://www.w3.org/1999/xlink">
          <path
             id="p0"
             d="M2,0 L0,0"
           />
          <text
             style="font-size:1;stroke-width:0.1"
             id="text38403">
            <textPath
               xlink:href="#p0"
               id="textPath38413">T</textPath>
          </text>
        </svg>
    """)
    out = svg_to_outlines(svg)

    # Currently unsupported so expect no text to be shown.
    assert len(out) == 0
Пример #7
0
def test_empty():
    # Simple case: An empty file
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
        </svg>
    """)
    assert svg_to_outlines(svg) == []
Пример #8
0
def test_no_stroke():
    # Simple case: A file with line not stroked
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path style="stroke:none" d="M0,0 L2,1"/>
        </svg>
    """)
    assert svg_to_outlines(svg) == []
Пример #9
0
def test_straight_line():
    # Simple case: A straight red line
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path style="stroke-width:0.1;stroke:#ff0000" d="M0,0 L2,1"/>
        </svg>
    """)
    assert svg_to_outlines(svg) == [
        ((1, 0, 0, 1), 1, [(0, 0), (20, 10)]),
    ]
Пример #10
0
def test_display_none():
    # Simple case: A file with an invisible line
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path
              style="stroke-width:0.1;stroke:#ff0000;display:none"
              d="M0,0 L2,1"
            />
        </svg>
    """)
    assert svg_to_outlines(svg) == []
Пример #11
0
def test_polyline():
    # Simple case: A line with several steps
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path
              style="stroke-width:0.1;stroke:#ffff00"
              d="M0,0 L0,1 L2,1 L2,0"
            />
        </svg>
    """)
    assert svg_to_outlines(svg) == [
        ((1, 1, 0, 1), 1, [(0, 0), (0, 10), (20, 10), (20, 0)]),
    ]
Пример #12
0
def test_dashes():
    # Simple case: A dashed path
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path
              style="stroke-width:1;stroke:black;stroke-width:1;stroke-dasharray:0.75,0.25"
              d="M0,0 L2,0"
            />
        </svg>
    """)
    assert svg_to_outlines(svg) == [
        ((0, 0, 0, 1), 10, [(0, 0), (7.5, 0)]),
        ((0, 0, 0, 1), 10, [(10, 0), (17.5, 0)]),
    ]
Пример #13
0
def test_bezier():
    # Check bezier curves work correctly
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path style="stroke-width:0.1;stroke:black" d="M0,0 Q1,1 2,0"/>
        </svg>
    """)
    out = svg_to_outlines(svg)

    assert len(out) == 1

    colour, width, line = out[0]

    line_buf = LineString(line).buffer(0.2)
    for p in range(101):
        point = Point(quadratic_bezier((0, 0), (10, 10), (20, 0), p / 100.0))
        assert line_buf.intersects(point), (p, line_buf.distance(point))
Пример #14
0
def test_scale_transform():
    # Check scaling works (and also applies correctly to dashed lines)
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <g transform="scale(2, 1)">
                <path
                  style="stroke:black;stroke-width:1;stroke-dasharray:0.75,0.25"
                  d="M0,0 L1,0"
                />
            </g>
        </svg>
    """)
    out = svg_to_outlines(svg)
    assert len(out) == 1
    colour, width, lines = out[0]
    assert colour == (0, 0, 0, 1)
    assert lines == [(0, 0), (15, 0)]
Пример #15
0
def test_text_line_width_and_colour():
    # Check text is rendered with the correct line width and colour
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <text
              style="stroke-width:0.1;font-size:1;stroke:black"
              x="0" y="1"
            >T</text>
        </svg>
    """)
    out = svg_to_outlines(svg)

    assert len(out) == 1

    colour, width, line = out[0]

    assert colour == (0, 0, 0, 1)
    assert width == 1
Пример #16
0
def test_gradient():
    # Make sure gradient strokes result in 'None' as the output colour.
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <defs>
                <linearGradient id="g1" x1="0" y1="0" x2="2" y2="1">
                    <stop style="stop-color:red" offset="0"/>
                    <stop style="stop-color:blue" offset="1"/>
                </linearGradient>
            </defs>
            <path
              id="p1"
              style="stroke-width:0.1;stroke:url(#g1)"
              d="M0,0 L2,1"
            />
        </svg>
    """)
    assert svg_to_outlines(svg) == [
        (None, 1, [(0, 0), (20, 10)]),
    ]
Пример #17
0
def test_text():
    # Check text is rendered sensibly
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <text
              style="stroke-width:0.1;font-size:1;stroke:black"
              x="0" y="1"
            >T</text>
        </svg>
    """)
    out = svg_to_outlines(svg)

    assert len(out) == 1

    colour, width, line = out[0]

    # Since we can't really guess the font that will be used, just check for
    # sanity
    letter = Polygon(line)

    # Is it *approximately* the right size?
    minx, miny, maxx, maxy = letter.bounds
    width = maxx - minx
    height = maxy - miny
    assert 2 < width < 15
    assert 5 < height < 15

    # In approximately the right place?
    assert -2 < minx < 2
    assert -2 < miny < 5

    # With approximately the correct proportions (i.e. wide bit of the 'T' at
    # the top, lower parts narrower)
    btm_rect = box(minx, miny + height * 0.666, maxx, maxy)
    mid_rect = box(minx, miny + height * 0.333, maxx, miny + height * 0.666)
    top_rect = box(minx, miny + height, maxx, miny + height * 0.333)
    btm_area = btm_rect.intersection(letter).area
    mid_area = mid_rect.intersection(letter).area
    top_area = top_rect.intersection(letter).area
    assert top_area > mid_area
    assert top_area > btm_area
Пример #18
0
def test_use():
    # Make sure <use> directives work
    svg = ElementTree.fromstring("""
        <svg width="2cm" height="1cm" viewBox="0 0 2 1">
            <path
              id="p1"
              style="stroke-width:0.1;stroke:#ff0000" d="M0,0 L2,0"
            />
            <use
              x="0"
              y="0"
              href="#p1"
              width="100%"
              height="100%"
              transform="translate(0, 1)"
            />
        </svg>
    """)
    assert svg_to_outlines(svg) == [
        ((1, 0, 0, 1), 1, [(0, 0), (20, 0)]),
        ((1, 0, 0, 1), 1, [(0, 10), (20, 10)]),
    ]