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