transform: Tools for working with transformation matrices
Affine 2D transformation matrix class.
The Transform class implements various transformation matrix operations, both on the matrix itself, as well as on 2D coordinates.
Transform instances are effectively immutable: all methods that operate on the transformation itself always return a new instance. This has as the interesting side effect that Transform instances are hashable, ie. they can be used as dictionary keys.
This module exports the following symbols:
- Transform
this is the main class
- Identity
Transform instance set to the identity transformation
- Offset
Convenience function that returns a translating transformation
- Scale
Convenience function that returns a scaling transformation
The DecomposedTransform class implements a transformation with separate translate, rotation, scale, skew, and transformation-center components.
- Example:
>>> t = Transform(2, 0, 0, 3, 0, 0) >>> t.transformPoint((100, 100)) (200, 300) >>> t = Scale(2, 3) >>> t.transformPoint((100, 100)) (200, 300) >>> t.transformPoint((0, 0)) (0, 0) >>> t = Offset(2, 3) >>> t.transformPoint((100, 100)) (102, 103) >>> t.transformPoint((0, 0)) (2, 3) >>> t2 = t.scale(0.5) >>> t2.transformPoint((100, 100)) (52.0, 53.0) >>> import math >>> t3 = t2.rotate(math.pi / 2) >>> t3.transformPoint((0, 0)) (2.0, 3.0) >>> t3.transformPoint((100, 100)) (-48.0, 53.0) >>> t = Identity.scale(0.5).translate(100, 200).skew(0.1, 0.2) >>> t.transformPoints([(0, 0), (1, 1), (100, 100)]) [(50.0, 100.0), (50.550167336042726, 100.60135501775433), (105.01673360427253, 160.13550177543362)] >>>
- class fontTools.misc.transform.Transform(xx: float = 1, xy: float = 0, yx: float = 0, yy: float = 1, dx: float = 0, dy: float = 0)[source]
Bases:
NamedTuple
2x2 transformation matrix plus offset, a.k.a. Affine transform. Transform instances are immutable: all transforming methods, eg. rotate(), return a new Transform instance.
- Example:
>>> t = Transform() >>> t <Transform [1 0 0 1 0 0]> >>> t.scale(2) <Transform [2 0 0 2 0 0]> >>> t.scale(2.5, 5.5) <Transform [2.5 0 0 5.5 0 0]> >>> >>> t.scale(2, 3).transformPoint((100, 100)) (200, 300)
Transform’s constructor takes six arguments, all of which are optional, and can be used as keyword arguments:
>>> Transform(12) <Transform [12 0 0 1 0 0]> >>> Transform(dx=12) <Transform [1 0 0 1 12 0]> >>> Transform(yx=12) <Transform [1 0 12 1 0 0]>
Transform instances also behave like sequences of length 6:
>>> len(Identity) 6 >>> list(Identity) [1, 0, 0, 1, 0, 0] >>> tuple(Identity) (1, 0, 0, 1, 0, 0)
Transform instances are comparable:
>>> t1 = Identity.scale(2, 3).translate(4, 6) >>> t2 = Identity.translate(8, 18).scale(2, 3) >>> t1 == t2 1
But beware of floating point rounding errors:
>>> t1 = Identity.scale(0.2, 0.3).translate(0.4, 0.6) >>> t2 = Identity.translate(0.08, 0.18).scale(0.2, 0.3) >>> t1 <Transform [0.2 0 0 0.3 0.08 0.18]> >>> t2 <Transform [0.2 0 0 0.3 0.08 0.18]> >>> t1 == t2 0
Transform instances are hashable, meaning you can use them as keys in dictionaries:
>>> d = {Scale(12, 13): None} >>> d {<Transform [12 0 0 13 0 0]>: None}
But again, beware of floating point rounding errors:
>>> t1 = Identity.scale(0.2, 0.3).translate(0.4, 0.6) >>> t2 = Identity.translate(0.08, 0.18).scale(0.2, 0.3) >>> t1 <Transform [0.2 0 0 0.3 0.08 0.18]> >>> t2 <Transform [0.2 0 0 0.3 0.08 0.18]> >>> d = {t1: None} >>> d {<Transform [0.2 0 0 0.3 0.08 0.18]>: None} >>> d[t2] Traceback (most recent call last): File "<stdin>", line 1, in ? KeyError: <Transform [0.2 0 0 0.3 0.08 0.18]>
- xx: float
Alias for field number 0
- xy: float
Alias for field number 1
- yx: float
Alias for field number 2
- yy: float
Alias for field number 3
- dx: float
Alias for field number 4
- dy: float
Alias for field number 5
- transformPoint(p)[source]
Transform a point.
- Example:
>>> t = Transform() >>> t = t.scale(2.5, 5.5) >>> t.transformPoint((100, 100)) (250.0, 550.0)
- transformPoints(points)[source]
Transform a list of points.
- Example:
>>> t = Scale(2, 3) >>> t.transformPoints([(0, 0), (0, 100), (100, 100), (100, 0)]) [(0, 0), (0, 300), (200, 300), (200, 0)] >>>
- transformVector(v)[source]
Transform an (dx, dy) vector, treating translation as zero.
- Example:
>>> t = Transform(2, 0, 0, 2, 10, 20) >>> t.transformVector((3, -4)) (6, -8) >>>
- transformVectors(vectors)[source]
Transform a list of (dx, dy) vector, treating translation as zero.
- Example:
>>> t = Transform(2, 0, 0, 2, 10, 20) >>> t.transformVectors([(3, -4), (5, -6)]) [(6, -8), (10, -12)] >>>
- translate(x: float = 0, y: float = 0)[source]
Return a new transformation, translated (offset) by x, y.
- Example:
>>> t = Transform() >>> t.translate(20, 30) <Transform [1 0 0 1 20 30]> >>>
- scale(x: float = 1, y: float | None = None)[source]
Return a new transformation, scaled by x, y. The ‘y’ argument may be None, which implies to use the x value for y as well.
- Example:
>>> t = Transform() >>> t.scale(5) <Transform [5 0 0 5 0 0]> >>> t.scale(5, 6) <Transform [5 0 0 6 0 0]> >>>
- rotate(angle: float)[source]
Return a new transformation, rotated by ‘angle’ (radians).
- Example:
>>> import math >>> t = Transform() >>> t.rotate(math.pi / 2) <Transform [0 1 -1 0 0 0]> >>>
- skew(x: float = 0, y: float = 0)[source]
Return a new transformation, skewed by x and y.
- Example:
>>> import math >>> t = Transform() >>> t.skew(math.pi / 4) <Transform [1 0 1 1 0 0]> >>>
- transform(other)[source]
Return a new transformation, transformed by another transformation.
- Example:
>>> t = Transform(2, 0, 0, 3, 1, 6) >>> t.transform((4, 3, 2, 1, 5, 6)) <Transform [8 9 4 3 11 24]> >>>
- reverseTransform(other)[source]
Return a new transformation, which is the other transformation transformed by self. self.reverseTransform(other) is equivalent to other.transform(self).
- Example:
>>> t = Transform(2, 0, 0, 3, 1, 6) >>> t.reverseTransform((4, 3, 2, 1, 5, 6)) <Transform [8 6 6 3 21 15]> >>> Transform(4, 3, 2, 1, 5, 6).transform((2, 0, 0, 3, 1, 6)) <Transform [8 6 6 3 21 15]> >>>
- inverse()[source]
Return the inverse transformation.
- Example:
>>> t = Identity.translate(2, 3).scale(4, 5) >>> t.transformPoint((10, 20)) (42, 103) >>> it = t.inverse() >>> it.transformPoint((42, 103)) (10.0, 20.0) >>>
- toPS() str [source]
Return a PostScript representation
- Example:
>>> t = Identity.scale(2, 3).translate(4, 5) >>> t.toPS() '[2 0 0 3 8 15]' >>>
- toDecomposed() DecomposedTransform [source]
Decompose into a DecomposedTransform.
- fontTools.misc.transform.Offset(x: float = 0, y: float = 0) Transform [source]
Return the identity transformation offset by x, y.
- Example:
>>> Offset(2, 3) <Transform [1 0 0 1 2 3]> >>>
- fontTools.misc.transform.Scale(x: float, y: float | None = None) Transform [source]
Return the identity transformation scaled by x, y. The ‘y’ argument may be None, which implies to use the x value for y as well.
- Example:
>>> Scale(2, 3) <Transform [2 0 0 3 0 0]> >>>
- class fontTools.misc.transform.DecomposedTransform(translateX: float = 0, translateY: float = 0, rotation: float = 0, scaleX: float = 1, scaleY: float = 1, skewX: float = 0, skewY: float = 0, tCenterX: float = 0, tCenterY: float = 0)[source]
Bases:
object
The DecomposedTransform class implements a transformation with separate translate, rotation, scale, skew, and transformation-center components.
- translateX: float = 0
- translateY: float = 0
- rotation: float = 0
- scaleX: float = 1
- scaleY: float = 1
- skewX: float = 0
- skewY: float = 0
- tCenterX: float = 0
- tCenterY: float = 0
- classmethod fromTransform(transform)[source]
Return a DecomposedTransform() equivalent of this transformation. The returned solution always has skewY = 0, and angle in the (-180, 180].
- Example:
>>> DecomposedTransform.fromTransform(Transform(3, 0, 0, 2, 0, 0)) DecomposedTransform(translateX=0, translateY=0, rotation=0.0, scaleX=3.0, scaleY=2.0, skewX=0.0, skewY=0.0, tCenterX=0, tCenterY=0) >>> DecomposedTransform.fromTransform(Transform(0, 0, 0, 1, 0, 0)) DecomposedTransform(translateX=0, translateY=0, rotation=0.0, scaleX=0.0, scaleY=1.0, skewX=0.0, skewY=0.0, tCenterX=0, tCenterY=0) >>> DecomposedTransform.fromTransform(Transform(0, 0, 1, 1, 0, 0)) DecomposedTransform(translateX=0, translateY=0, rotation=-45.0, scaleX=0.0, scaleY=1.4142135623730951, skewX=0.0, skewY=0.0, tCenterX=0, tCenterY=0)