xref: /aosp_15_r20/external/fonttools/Tests/misc/transform_test.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughesfrom fontTools.misc.transform import (
2*e1fe3e4aSElliott Hughes    Transform,
3*e1fe3e4aSElliott Hughes    Identity,
4*e1fe3e4aSElliott Hughes    Offset,
5*e1fe3e4aSElliott Hughes    Scale,
6*e1fe3e4aSElliott Hughes    DecomposedTransform,
7*e1fe3e4aSElliott Hughes)
8*e1fe3e4aSElliott Hughesimport math
9*e1fe3e4aSElliott Hughesimport pytest
10*e1fe3e4aSElliott Hughes
11*e1fe3e4aSElliott Hughes
12*e1fe3e4aSElliott Hughesclass TransformTest(object):
13*e1fe3e4aSElliott Hughes    def test_examples(self):
14*e1fe3e4aSElliott Hughes        t = Transform()
15*e1fe3e4aSElliott Hughes        assert repr(t) == "<Transform [1 0 0 1 0 0]>"
16*e1fe3e4aSElliott Hughes        assert t.scale(2) == Transform(2, 0, 0, 2, 0, 0)
17*e1fe3e4aSElliott Hughes        assert t.scale(2.5, 5.5) == Transform(2.5, 0, 0, 5.5, 0, 0)
18*e1fe3e4aSElliott Hughes        assert t.scale(2, 3).transformPoint((100, 100)) == (200, 300)
19*e1fe3e4aSElliott Hughes
20*e1fe3e4aSElliott Hughes    def test__init__(self):
21*e1fe3e4aSElliott Hughes        assert Transform(12) == Transform(12, 0, 0, 1, 0, 0)
22*e1fe3e4aSElliott Hughes        assert Transform(dx=12) == Transform(1, 0, 0, 1, 12, 0)
23*e1fe3e4aSElliott Hughes        assert Transform(yx=12) == Transform(1, 0, 12, 1, 0, 0)
24*e1fe3e4aSElliott Hughes
25*e1fe3e4aSElliott Hughes    def test_transformPoints(self):
26*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, 0, 0)
27*e1fe3e4aSElliott Hughes        assert t.transformPoints([(0, 0), (0, 100), (100, 100), (100, 0)]) == [
28*e1fe3e4aSElliott Hughes            (0, 0),
29*e1fe3e4aSElliott Hughes            (0, 300),
30*e1fe3e4aSElliott Hughes            (200, 300),
31*e1fe3e4aSElliott Hughes            (200, 0),
32*e1fe3e4aSElliott Hughes        ]
33*e1fe3e4aSElliott Hughes
34*e1fe3e4aSElliott Hughes    def test_transformVector(self):
35*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, -10, 30)
36*e1fe3e4aSElliott Hughes        assert t.transformVector((-4, 5)) == (-8, 15)
37*e1fe3e4aSElliott Hughes
38*e1fe3e4aSElliott Hughes    def test_transformVectors(self):
39*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, -10, 30)
40*e1fe3e4aSElliott Hughes        assert t.transformVectors([(-4, 5), (-6, 7)]) == [(-8, 15), (-12, 21)]
41*e1fe3e4aSElliott Hughes
42*e1fe3e4aSElliott Hughes    def test_translate(self):
43*e1fe3e4aSElliott Hughes        t = Transform()
44*e1fe3e4aSElliott Hughes        assert t.translate(20, 30) == Transform(1, 0, 0, 1, 20, 30)
45*e1fe3e4aSElliott Hughes
46*e1fe3e4aSElliott Hughes    def test_scale(self):
47*e1fe3e4aSElliott Hughes        t = Transform()
48*e1fe3e4aSElliott Hughes        assert t.scale(5) == Transform(5, 0, 0, 5, 0, 0)
49*e1fe3e4aSElliott Hughes        assert t.scale(5, 6) == Transform(5, 0, 0, 6, 0, 0)
50*e1fe3e4aSElliott Hughes
51*e1fe3e4aSElliott Hughes    def test_rotate(self):
52*e1fe3e4aSElliott Hughes        t = Transform()
53*e1fe3e4aSElliott Hughes        assert t.rotate(math.pi / 2) == Transform(0, 1, -1, 0, 0, 0)
54*e1fe3e4aSElliott Hughes        t = Transform()
55*e1fe3e4aSElliott Hughes        assert t.rotate(-math.pi / 2) == Transform(0, -1, 1, 0, 0, 0)
56*e1fe3e4aSElliott Hughes        t = Transform()
57*e1fe3e4aSElliott Hughes        assert tuple(t.rotate(math.radians(30))) == pytest.approx(
58*e1fe3e4aSElliott Hughes            tuple(Transform(0.866025, 0.5, -0.5, 0.866025, 0, 0))
59*e1fe3e4aSElliott Hughes        )
60*e1fe3e4aSElliott Hughes
61*e1fe3e4aSElliott Hughes    def test_skew(self):
62*e1fe3e4aSElliott Hughes        t = Transform().skew(math.pi / 4)
63*e1fe3e4aSElliott Hughes        assert tuple(t) == pytest.approx(tuple(Transform(1, 0, 1, 1, 0, 0)))
64*e1fe3e4aSElliott Hughes
65*e1fe3e4aSElliott Hughes    def test_transform(self):
66*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, 1, 6)
67*e1fe3e4aSElliott Hughes        assert t.transform((4, 3, 2, 1, 5, 6)) == Transform(8, 9, 4, 3, 11, 24)
68*e1fe3e4aSElliott Hughes
69*e1fe3e4aSElliott Hughes    def test_reverseTransform(self):
70*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, 1, 6)
71*e1fe3e4aSElliott Hughes        reverse_t = t.reverseTransform((4, 3, 2, 1, 5, 6))
72*e1fe3e4aSElliott Hughes        assert reverse_t == Transform(8, 6, 6, 3, 21, 15)
73*e1fe3e4aSElliott Hughes        t = Transform(4, 3, 2, 1, 5, 6)
74*e1fe3e4aSElliott Hughes        reverse_t = t.transform((2, 0, 0, 3, 1, 6))
75*e1fe3e4aSElliott Hughes        assert reverse_t == Transform(8, 6, 6, 3, 21, 15)
76*e1fe3e4aSElliott Hughes
77*e1fe3e4aSElliott Hughes    def test_inverse(self):
78*e1fe3e4aSElliott Hughes        t = Transform().translate(2, 3).scale(4, 5)
79*e1fe3e4aSElliott Hughes        assert t.transformPoint((10, 20)) == (42, 103)
80*e1fe3e4aSElliott Hughes        it = t.inverse()
81*e1fe3e4aSElliott Hughes        assert it.transformPoint((42, 103)) == (10.0, 20.0)
82*e1fe3e4aSElliott Hughes        assert Transform().inverse() == Transform()
83*e1fe3e4aSElliott Hughes
84*e1fe3e4aSElliott Hughes    def test_toPS(self):
85*e1fe3e4aSElliott Hughes        t = Transform().scale(2, 3).translate(4, 5)
86*e1fe3e4aSElliott Hughes        assert t.toPS() == "[2 0 0 3 8 15]"
87*e1fe3e4aSElliott Hughes
88*e1fe3e4aSElliott Hughes    def test__ne__(self):
89*e1fe3e4aSElliott Hughes        assert Transform() != Transform(2, 0, 0, 2, 0, 0)
90*e1fe3e4aSElliott Hughes
91*e1fe3e4aSElliott Hughes    def test__hash__(self):
92*e1fe3e4aSElliott Hughes        t = Transform(12, 0, 0, 13, 0, 0)
93*e1fe3e4aSElliott Hughes        d = {t: None}
94*e1fe3e4aSElliott Hughes        assert t in d.keys()
95*e1fe3e4aSElliott Hughes
96*e1fe3e4aSElliott Hughes    def test__bool__(self):
97*e1fe3e4aSElliott Hughes        assert not bool(Transform())
98*e1fe3e4aSElliott Hughes        assert Transform(2, 0, 0, 2, 0, 0)
99*e1fe3e4aSElliott Hughes        assert Transform(1, 0, 0, 1, 1, 0)
100*e1fe3e4aSElliott Hughes
101*e1fe3e4aSElliott Hughes    def test__repr__(self):
102*e1fe3e4aSElliott Hughes        assert repr(Transform(1, 2, 3, 4, 5, 6)) == "<Transform [1 2 3 4 5 6]>"
103*e1fe3e4aSElliott Hughes
104*e1fe3e4aSElliott Hughes    def test_Identity(self):
105*e1fe3e4aSElliott Hughes        assert isinstance(Identity, Transform)
106*e1fe3e4aSElliott Hughes        assert Identity == Transform(1, 0, 0, 1, 0, 0)
107*e1fe3e4aSElliott Hughes
108*e1fe3e4aSElliott Hughes    def test_Offset(self):
109*e1fe3e4aSElliott Hughes        assert Offset() == Transform(1, 0, 0, 1, 0, 0)
110*e1fe3e4aSElliott Hughes        assert Offset(1) == Transform(1, 0, 0, 1, 1, 0)
111*e1fe3e4aSElliott Hughes        assert Offset(1, 2) == Transform(1, 0, 0, 1, 1, 2)
112*e1fe3e4aSElliott Hughes
113*e1fe3e4aSElliott Hughes    def test_Scale(self):
114*e1fe3e4aSElliott Hughes        assert Scale(1) == Transform(1, 0, 0, 1, 0, 0)
115*e1fe3e4aSElliott Hughes        assert Scale(2) == Transform(2, 0, 0, 2, 0, 0)
116*e1fe3e4aSElliott Hughes        assert Scale(1, 2) == Transform(1, 0, 0, 2, 0, 0)
117*e1fe3e4aSElliott Hughes
118*e1fe3e4aSElliott Hughes    def test_decompose(self):
119*e1fe3e4aSElliott Hughes        t = Transform(2, 0, 0, 3, 5, 7)
120*e1fe3e4aSElliott Hughes        d = t.toDecomposed()
121*e1fe3e4aSElliott Hughes        assert d.scaleX == 2
122*e1fe3e4aSElliott Hughes        assert d.scaleY == 3
123*e1fe3e4aSElliott Hughes        assert d.translateX == 5
124*e1fe3e4aSElliott Hughes        assert d.translateY == 7
125*e1fe3e4aSElliott Hughes
126*e1fe3e4aSElliott Hughes    def test_decompose(self):
127*e1fe3e4aSElliott Hughes        t = Transform(-1, 0, 0, 1, 0, 0)
128*e1fe3e4aSElliott Hughes        d = t.toDecomposed()
129*e1fe3e4aSElliott Hughes        assert d.scaleX == -1
130*e1fe3e4aSElliott Hughes        assert d.scaleY == 1
131*e1fe3e4aSElliott Hughes        assert d.rotation == 0
132*e1fe3e4aSElliott Hughes
133*e1fe3e4aSElliott Hughes        t = Transform(1, 0, 0, -1, 0, 0)
134*e1fe3e4aSElliott Hughes        d = t.toDecomposed()
135*e1fe3e4aSElliott Hughes        assert d.scaleX == 1
136*e1fe3e4aSElliott Hughes        assert d.scaleY == -1
137*e1fe3e4aSElliott Hughes        assert d.rotation == 0
138*e1fe3e4aSElliott Hughes
139*e1fe3e4aSElliott Hughes
140*e1fe3e4aSElliott Hughesclass DecomposedTransformTest(object):
141*e1fe3e4aSElliott Hughes    def test_identity(self):
142*e1fe3e4aSElliott Hughes        t = DecomposedTransform()
143*e1fe3e4aSElliott Hughes        assert (
144*e1fe3e4aSElliott Hughes            repr(t)
145*e1fe3e4aSElliott Hughes            == "DecomposedTransform(translateX=0, translateY=0, rotation=0, scaleX=1, scaleY=1, skewX=0, skewY=0, tCenterX=0, tCenterY=0)"
146*e1fe3e4aSElliott Hughes        )
147*e1fe3e4aSElliott Hughes        assert t == DecomposedTransform(scaleX=1.0)
148*e1fe3e4aSElliott Hughes
149*e1fe3e4aSElliott Hughes    def test_scale(self):
150*e1fe3e4aSElliott Hughes        t = DecomposedTransform(scaleX=2, scaleY=3)
151*e1fe3e4aSElliott Hughes        assert t.scaleX == 2
152*e1fe3e4aSElliott Hughes        assert t.scaleY == 3
153*e1fe3e4aSElliott Hughes
154*e1fe3e4aSElliott Hughes    def test_toTransform(self):
155*e1fe3e4aSElliott Hughes        t = DecomposedTransform(scaleX=2, scaleY=3)
156*e1fe3e4aSElliott Hughes        assert t.toTransform() == (2, 0, 0, 3, 0, 0)
157*e1fe3e4aSElliott Hughes
158*e1fe3e4aSElliott Hughes    @pytest.mark.parametrize(
159*e1fe3e4aSElliott Hughes        "decomposed",
160*e1fe3e4aSElliott Hughes        [
161*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=1, scaleY=0),
162*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=0, scaleY=1),
163*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=1, scaleY=0, rotation=30),
164*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=0, scaleY=1, rotation=30),
165*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=1, scaleY=1),
166*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, scaleY=1),
167*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=1, scaleY=-1),
168*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, scaleY=-1),
169*e1fe3e4aSElliott Hughes            DecomposedTransform(rotation=90),
170*e1fe3e4aSElliott Hughes            DecomposedTransform(rotation=-90),
171*e1fe3e4aSElliott Hughes            DecomposedTransform(skewX=45),
172*e1fe3e4aSElliott Hughes            DecomposedTransform(skewY=45),
173*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewX=45),
174*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewY=45),
175*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewX=45),
176*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewY=45),
177*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewX=45, rotation=30),
178*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewY=45, rotation=30),
179*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewX=45, rotation=30),
180*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewY=45, rotation=30),
181*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewX=45, rotation=-30),
182*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-1, skewY=45, rotation=-30),
183*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewX=45, rotation=-30),
184*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-1, skewY=45, rotation=-30),
185*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-2, skewX=45, rotation=30),
186*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-2, skewY=45, rotation=30),
187*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-2, skewX=45, rotation=30),
188*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-2, skewY=45, rotation=30),
189*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-2, skewX=45, rotation=-30),
190*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleX=-2, skewY=45, rotation=-30),
191*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-2, skewX=45, rotation=-30),
192*e1fe3e4aSElliott Hughes            DecomposedTransform(scaleY=-2, skewY=45, rotation=-30),
193*e1fe3e4aSElliott Hughes        ],
194*e1fe3e4aSElliott Hughes    )
195*e1fe3e4aSElliott Hughes    def test_roundtrip(lst, decomposed):
196*e1fe3e4aSElliott Hughes        assert decomposed.toTransform().toDecomposed().toTransform() == pytest.approx(
197*e1fe3e4aSElliott Hughes            tuple(decomposed.toTransform())
198*e1fe3e4aSElliott Hughes        ), decomposed
199