Esempio n. 1
0
def overlapping_path():
    path = Path()
    path.moveTo(0, 0)
    path.lineTo(10, 0)
    path.lineTo(10, 10)
    path.lineTo(0, 10)
    path.close()
    path.moveTo(5, 5)
    path.lineTo(15, 5)
    path.lineTo(15, 15)
    path.lineTo(5, 15)
    path.close()
    return path
Esempio n. 2
0
    def _convert_vmobject_to_skia_path(self, vmobject: VMobject) -> SkiaPath:
        """Converts a :class:`~.VMobject` to SkiaPath. This method only works for
        cairo renderer because it treats the points as Cubic beizer curves.

        Parameters
        ----------
        vmobject:
            The :class:`~.VMobject` to convert from.

        Returns
        -------
        SkiaPath:
            The converted path.
        """
        path = SkiaPath()

        if not np.all(np.isfinite(vmobject.points)):
            points = np.zeros((1, 3))  # point invalid?
        else:
            points = vmobject.points

        if len(points) == 0:  # what? No points so return empty path
            return path

        # In OpenGL it's quadratic beizer curves while on Cairo it's cubic...
        if config.renderer == "opengl":
            subpaths = vmobject.get_subpaths_from_points(points)
            for subpath in subpaths:
                quads = vmobject.get_bezier_tuples_from_points(subpath)
                start = subpath[0]
                path.moveTo(*start[:2])
                for p0, p1, p2 in quads:
                    path.quadTo(*p1[:2], *p2[:2])
                if vmobject.consider_points_equals(subpath[0], subpath[-1]):
                    path.close()
        else:
            subpaths = vmobject.gen_subpaths_from_points_2d(points)
            for subpath in subpaths:
                quads = vmobject.gen_cubic_bezier_tuples_from_points(subpath)
                start = subpath[0]
                path.moveTo(*start[:2])
                for p0, p1, p2, p3 in quads:
                    path.cubicTo(*p1[:2], *p2[:2], *p3[:2])

                if vmobject.consider_points_equals_2d(subpath[0], subpath[-1]):
                    path.close()

        return path
Esempio n. 3
0
    def test_pen_addComponent_decomposed_from_glyphSet(self):
        a = Path()
        a.moveTo(0, 0)
        a.lineTo(1, 0)
        a.lineTo(1, 1)
        a.lineTo(0, 1)
        a.close()
        glyphSet = {"a": a}

        b = Path()
        pen = b.getPen(glyphSet=glyphSet)
        pen.addComponent("a", (2, 0, 0, 2, 10, 10))
        glyphSet["b"] = b

        assert list(b) == [
            (PathVerb.MOVE, ((10, 10),)),
            (PathVerb.LINE, ((12, 10),)),
            (PathVerb.LINE, ((12, 12),)),
            (PathVerb.LINE, ((10, 12),)),
            (PathVerb.CLOSE, ()),
        ]

        c = Path()
        pen = c.getPen(glyphSet=glyphSet)
        pen.addComponent("a", (1, 0, 0, 1, 2, 2))
        pen.addComponent("b", (1, 0, 0, 1, -10, -10))
        glyphSet["c"] = c

        assert list(c) == [
            (PathVerb.MOVE, ((2, 2),)),
            (PathVerb.LINE, ((3, 2),)),
            (PathVerb.LINE, ((3, 3),)),
            (PathVerb.LINE, ((2, 3),)),
            (PathVerb.CLOSE, ()),
            (PathVerb.MOVE, ((0, 0),)),
            (PathVerb.LINE, ((2, 0),)),
            (PathVerb.LINE, ((2, 2),)),
            (PathVerb.LINE, ((0, 2),)),
            (PathVerb.CLOSE, ()),
        ]
Esempio n. 4
0
    def test_transform(self):
        path = Path()
        path.moveTo(125, 376)
        path.cubicTo(181, 376, 218, 339, 218, 290)
        path.cubicTo(218, 225, 179, 206, 125, 206)
        path.close()

        # t = Transform().rotate(radians(-45)).translate(-100, 0)
        matrix = (0.707107, -0.707107, 0.707107, 0.707107, -70.7107, 70.7107)

        result = path.transform(*matrix)

        expected = Path()
        expected.moveTo(
            bits2float(0x438dc663),  # 283.55
            bits2float(0x437831ce),  # 248.195
        )
        expected.cubicTo(
            bits2float(0x43a192ee),  # 323.148
            bits2float(0x435098b8),  # 208.597
            bits2float(0x43a192ee),  # 323.148
            bits2float(0x431c454a),  # 156.271
            bits2float(0x43903ff5),  # 288.5
            bits2float(0x42f33ead),  # 121.622
        )
        expected.cubicTo(
            bits2float(0x437289a8),  # 242.538
            bits2float(0x42975227),  # 75.6605
            bits2float(0x43498688),  # 201.526
            bits2float(0x42b39aee),  # 89.8026
            bits2float(0x4323577c),  # 163.342
            bits2float(0x42fff906),  # 127.986
        )
        expected.close()

        result.dump(as_hex=True)
        assert result == expected
Esempio n. 5
0
def test_strip_collinear_moveTo():
    # https://github.com/fonttools/skia-pathops/issues/12
    path = Path()
    path.moveTo(
        bits2float(0x440b8000),  # 558
        bits2float(0x0),  # 0
    )
    path.lineTo(
        bits2float(0x44098000),  # 550
        bits2float(0x0),  # 0
    )
    path.lineTo(
        bits2float(0x440c247f),  # 560.57
        bits2float(0x41daf87e),  # 27.3713
    )
    path.lineTo(
        bits2float(0x440e247f),  # 568.57
        bits2float(0x41daf87e),  # 27.3713
    )
    path.close()
    path.moveTo(
        bits2float(0x440b0000),  # 556
        bits2float(0x40e00000),  # 7
    )
    path.lineTo(
        bits2float(0x440a4000),  # 553
        bits2float(0x0),  # 0
    )
    path.lineTo(
        bits2float(0x44049c26),  # 530.44
        bits2float(0x0),  # 0
    )
    path.lineTo(
        bits2float(0x44052891),  # 532.634
        bits2float(0x40e00000),  # 7
    )
    path.close()

    path.simplify()

    expected = Path()
    expected.moveTo(
        bits2float(0x440b8000),  # 558
        bits2float(0x0),  # 0
    )
    expected.lineTo(
        bits2float(0x440e247f),  # 568.57
        bits2float(0x41daf87e),  # 27.3713
    )
    expected.lineTo(
        bits2float(0x440c247f),  # 560.57
        bits2float(0x41daf87e),  # 27.3713
    )
    expected.lineTo(
        bits2float(0x440a2d02),  # 552.703
        bits2float(0x40e00000),  # 7
    )
    expected.lineTo(
        bits2float(0x44052891),  # 532.634
        bits2float(0x40e00000),  # 7
    )
    expected.lineTo(
        bits2float(0x44049c26),  # 530.44
        bits2float(0x0),  # 0
    )
    # expected.lineTo(
    #     bits2float(0x44098000),  # 550
    #     bits2float(0x0),  # 0
    # )
    expected.close()

    assert list(path) == list(expected)
Esempio n. 6
0
def test_duplicate_start_point():
    # https://github.com/fonttools/skia-pathops/issues/13
    path = Path()
    path.moveTo(
        bits2float(0x43480000),  # 200
        bits2float(0x43db8ce9),  # 439.101
    )
    path.lineTo(
        bits2float(0x43480000),  # 200
        bits2float(0x4401c000),  # 519
    )
    path.cubicTo(
        bits2float(0x43480000),  # 200
        bits2float(0x441f0000),  # 636
        bits2float(0x43660000),  # 230
        bits2float(0x44340000),  # 720
        bits2float(0x43c80000),  # 400
        bits2float(0x44340000),  # 720
    )
    path.cubicTo(
        bits2float(0x4404c000),  # 531
        bits2float(0x44340000),  # 720
        bits2float(0x440d0000),  # 564
        bits2float(0x442b8000),  # 686
        bits2float(0x44118000),  # 582
        bits2float(0x4416c000),  # 603
    )
    path.lineTo(
        bits2float(0x442cc000),  # 691
        bits2float(0x441c8000),  # 626
    )
    path.cubicTo(
        bits2float(0x44260000),  # 664
        bits2float(0x443d4000),  # 757
        bits2float(0x44114000),  # 581
        bits2float(0x444a8000),  # 810
        bits2float(0x43c88000),  # 401
        bits2float(0x444a8000),  # 810
    )
    path.cubicTo(
        bits2float(0x43350000),  # 181
        bits2float(0x444a8000),  # 810
        bits2float(0x42c80000),  # 100
        bits2float(0x442e0000),  # 696
        bits2float(0x42c80000),  # 100
        bits2float(0x4401c000),  # 519
    )
    path.lineTo(
        bits2float(0x42c80000),  # 100
        bits2float(0x438a8000),  # 277
    )
    path.cubicTo(
        bits2float(0x42c80000),  # 100
        bits2float(0x42cc0000),  # 102
        bits2float(0x433e0000),  # 190
        bits2float(0xc1200000),  # -10
        bits2float(0x43cd0000),  # 410
        bits2float(0xc1200000),  # -10
    )
    path.cubicTo(
        bits2float(0x441d8000),  # 630
        bits2float(0xc1200000),  # -10
        bits2float(0x442f0000),  # 700
        bits2float(0x42e60000),  # 115
        bits2float(0x442f0000),  # 700
        bits2float(0x437a0000),  # 250
    )
    path.lineTo(
        bits2float(0x442f0000),  # 700
        bits2float(0x43880000),  # 272
    )
    path.cubicTo(
        bits2float(0x442f0000),  # 700
        bits2float(0x43d18000),  # 419
        bits2float(0x44164000),  # 601
        bits2float(0x43fa0000),  # 500
        bits2float(0x43c88000),  # 401
        bits2float(0x43fa0000),  # 500
    )
    path.cubicTo(
        bits2float(0x43964752),  # 300.557
        bits2float(0x43fa0000),  # 500
        bits2float(0x436db1ed),  # 237.695
        bits2float(0x43ef6824),  # 478.814
        bits2float(0x43480000),  # 200
        bits2float(0x43db8ce9),  # 439.101
    )
    path.close()
    path.moveTo(
        bits2float(0x434805cb),  # 200.023
        bits2float(0x43881798),  # 272.184
    )
    path.cubicTo(
        bits2float(0x43493da4),  # 201.241
        bits2float(0x43b2a869),  # 357.316
        bits2float(0x437bd6b1),  # 251.839
        bits2float(0x43cd0000),  # 410
        bits2float(0x43c80000),  # 400
        bits2float(0x43cd0000),  # 410
    )
    path.cubicTo(
        bits2float(0x44098000),  # 550
        bits2float(0x43cd0000),  # 410
        bits2float(0x44160000),  # 600
        bits2float(0x43b20000),  # 356
        bits2float(0x44160000),  # 600
        bits2float(0x43868000),  # 269
    )
    path.lineTo(
        bits2float(0x44160000),  # 600
        bits2float(0x43808000),  # 257
    )
    path.cubicTo(
        bits2float(0x44160000),  # 600
        bits2float(0x43330000),  # 179
        bits2float(0x44110000),  # 580
        bits2float(0x429c0000),  # 78
        bits2float(0x43cd0000),  # 410
        bits2float(0x429c0000),  # 78
    )
    path.cubicTo(
        bits2float(0x43725298),  # 242.323
        bits2float(0x429c0000),  # 78
        bits2float(0x43491e05),  # 201.117
        bits2float(0x431ccd43),  # 156.802
        bits2float(0x434805cb),  # 200.023
        bits2float(0x43881797),  # 272.184
    )
    path.close()

    contours = list(path.contours)

    # on the second contour, the last and first points' Y coordinate only
    # differ by one bit: 0x43881798 != 0x43881797
    points = contours[1].points
    assert points[0] != points[-1]
    assert points[0] == pytest.approx(points[-1])

    # when "drawn" as segments, almost equal last/first points are treated
    # as exactly equal, without the need of an extra closing lineTo
    for contour in path.contours:
        segments = list(contour.segments)
        assert segments[-1][0] == "closePath"
        first_type, first_pts = segments[0]
        last_type, last_pts = segments[-2]
        assert first_type == "moveTo"
        assert last_type == "curveTo"
        assert last_pts[-1] == first_pts[-1]