L i=$dZddlmZddlZddlmZddlmZgdZdZ de z Z d e zZ dd Z Gd d eZ e Zddd ZdddZeGddZedk(r4ddlZddlZej*ej,j.yy)a7Affine 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)] >>> ) annotationsN) NamedTuple) dataclass) TransformIdentityOffsetScaleDecomposedTransformgV瞯<cbt|tkrd}|S|tkDrd}|S|tkrd}|S)Nrr r )abs_EPSILON _ONE_EPSILON_MINUS_ONE_EPSILON)vs ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/fontTools/misc/transform.py _normSinCosrFsE 1v  H \   H    HceZdZUdZdZded<dZded<dZded<dZded<dZ ded <dZ ded <d Z d Z d Z dZdddZdddZddZdddZdZdZdZd dZd!dZd"dZd dZy)#ra 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 >>> t.scale(2) >>> t.scale(2.5, 5.5) >>> >>> 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(dx=12) >>> Transform(yx=12) 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 >>> t2 >>> t1 == t2 0 Transform instances are hashable, meaning you can use them as keys in dictionaries:: >>> d = {Scale(12, 13): None} >>> d {: 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 >>> t2 >>> d = {t1: None} >>> d {: None} >>> d[t2] Traceback (most recent call last): File "", line 1, in ? KeyError: r floatxxrxyyxyydxdycV|\}}|\}}}}}} ||z||zz|z||z||zz| zfS)zTransform a point. :Example: >>> t = Transform() >>> t = t.scale(2.5, 5.5) >>> t.transformPoint((100, 100)) (250.0, 550.0) ) selfpxyrrrrrrs rtransformPointzTransform.transformPointsLA!%BBBQa"$b1frAvo&:;;rc~|\}}}}}}|D cgc]!\}} ||z|| zz|z||z|| zz|zf#c} }Scc} }w)zTransform 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)] >>> r) r pointsrrrrrrr"r#s rtransformPointszTransform.transformPointssU"&BBBIOPAa"q&2%rAvQ';<PPPs&9cL|\}}|dd\}}}}||z||zz||z||zzfS)zTransform an (dx, dy) vector, treating translation as zero. :Example: >>> t = Transform(2, 0, 0, 2, 10, 20) >>> t.transformVector((3, -4)) (6, -8) >>> Nr)r rrrrrrrs rtransformVectorzTransform.transformVectorsERbqBBR"r'!27R"W#455rct|dd\}}}}|Dcgc]\}}||z||zz||z||zzfc}}Scc}}w)aTransform 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)] >>> Nr)r)r vectorsrrrrrrs rtransformVectorszTransform.transformVectorssNbqBBELM62rb27"BGb2g$56MMMs 4c0|jdddd||fS)zReturn a new transformation, translated (offset) by x, y. :Example: >>> t = Transform() >>> t.translate(20, 30) >>> r r transformr r"r#s r translatezTransform.translates ~~q!Q1a011rNc8||}|j|dd|ddfS)akReturn 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) >>> t.scale(5, 6) >>> rr/r1s rscalezTransform.scales* 9A~~q!Q1a011rcttj|}ttj|}|j ||| |ddfS)aReturn a new transformation, rotated by 'angle' (radians). :Example: >>> import math >>> t = Transform() >>> t.rotate(math.pi / 2) >>> r)rmathcossinr0)r anglecss rrotatezTransform.rotatesF  (  (~~q!aRAq122rc||jdtj|tj|dddfS)zReturn a new transformation, skewed by x and y. :Example: >>> import math >>> t = Transform() >>> t.skew(math.pi / 4) >>> r r)r0r6tanr1s rskewzTransform.skews0~~q$((1+txx{Aq!DEErc |\}}}}}}|\}} } } } } |j||z|| zz|| z|| zz||z|| zz|| z|| zz||z| |zz| z| |z| |zz| zS)aReturn a new transformation, transformed by another transformation. :Example: >>> t = Transform(2, 0, 0, 3, 1, 6) >>> t.transform((4, 3, 2, 1, 5, 6)) >>>  __class__r otherxx1xy1yx1yy1dx1dy1xx2xy2yx2yy2dx2dy2s rr0zTransform.transforms(-$S#sC'+$S#sC~~ #Ic ! #Ic ! #Ic ! #Ic ! #Ic !C ' #Ic !C '   rc |\}}}}}}|\}} } } } } |j||z|| zz|| z|| zz||z|| zz|| z|| zz||z| |zz| z| |z| |zz| zS)aReturn 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(4, 3, 2, 1, 5, 6).transform((2, 0, 0, 3, 1, 6)) >>> rArCs rreverseTransformzTransform.reverseTransform%s(,$S#sC',$S#sC~~ #Ic ! #Ic ! #Ic ! #Ic ! #Ic !C ' #Ic !C '   rc|tk(r|S|\}}}}}}||z||zz }||z | |z | |z ||z f\}}}}| |z||zz | |z||zz }}|j||||||S)aKReturn 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) >>> )rrB)r rrrrrrdets rinversezTransform.inverse=s 8 K!%BBB2gRcB39rcCicABBrBG#bS2XR%7B~~b"b"b"55rc d|zS)zReturn a PostScript representation :Example: >>> t = Identity.scale(2, 3).translate(4, 5) >>> t.toPS() '[2 0 0 3 8 15]' >>> z[%s %s %s %s %s %s]rr s rtoPSzTransform.toPSQs%t++rc,tj|S)z%Decompose into a DecomposedTransform.)r fromTransformrWs r toDecomposedzTransform.toDecomposed]s"0066rc|tk7S)aReturns True if transform is not identity, False otherwise. :Example: >>> bool(Identity) False >>> bool(Transform()) False >>> bool(Scale(1.)) False >>> bool(Scale(2)) True >>> bool(Offset()) False >>> bool(Offset(0)) False >>> bool(Offset(2)) True )rrWs r__bool__zTransform.__bool__as(xrc<d|jjf|zzS)Nz<%s [%g %g %g %g %g %g]>)rB__name__rWs r__repr__zTransform.__repr__ws)dnn.E.E-G$-NOOrrr)r"rr#r)r N)r"rr# float | None)r9r)returnstr)rcz'DecomposedTransform')rcbool)r_ __module__ __qualname____doc__r__annotations__rrrrrr$r'r*r-r2r4r<r?r0rRrUrXr[r]r`rrrrrPsL\BMBMBMBMBMBM < Q 6 N 22 3 F * 06( ,7 ,Prrc"tdddd||S)zReturn the identity transformation offset by x, y. :Example: >>> Offset(2, 3) >>> r rrr"r#s rrr~s Q1aA &&rc*||}t|dd|ddS)zReturn 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) >>> rrkrls rr r s# y  Q1aA &&rceZdZUdZdZded<dZded<dZded<dZded<dZ ded <dZ ded <dZ ded <dZ ded <dZ ded <dZedZddZy)r zThe DecomposedTransform class implements a transformation with separate translate, rotation, scale, skew, and transformation-center components. rr translateX translateYrotationr scaleXscaleYskewXskewYtCenterXtCenterYc0|jdk7xs|jdk7xsu|jdk7xsd|jdk7xsS|jdk7xsB|j dk7xs1|j dk7xs |jdk7xs|jdk7S)Nrr ) rorprqrrrsrtrurvrwrWs rr]zDecomposedTransform.__bool__s OOq  "!# "}}! "{{a "{{a  " zzQ  " zzQ  "}}! "}}! rc |\}}}}}}tjd|}|dkr ||z}||z}||z||zz } d} dx} } d} |dk7s|dk7rtj||z||zz}|dk\rtj||z ntj||z  } || |z } } tj||z||zz||zz } n||dk7s|dk7rqtj||z||zz}tj dz |dk\rtj| |z ntj||z  z } | |z |} } n t ||tj| | |z| tj| |zddd S)auReturn 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) r rg)r6copysignsqrtacosatanpir degrees)r r0abr:dr"r#sxdeltarqrrrsrtrr;s rrZz!DecomposedTransform.fromTransforms %1aAq ]]1a  6 GA GAAA  6Q!V !a%!a%-(A+,6tyyQ' !a%8H7HHFFIIq1uq1u}Q78E !VqAv !a%!a%-(Aww{%&!V 1"q&!$))AE2B1BH$aiFF " LL " RK  LL " $    rc*t}|j|j|jz|j|j z}|j tj|j}|j|j|j}|jtj|jtj|j}|j|j |j }|S)zReturn the Transform() equivalent of this transformation. :Example: >>> DecomposedTransform(scaleX=2, scaleY=2).toTransform() >>> )rr2rorvrprwr<r6radiansrqr4rrrsr?rtru)r ts r toTransformzDecomposedTransform.toTransforms K KK OOdmm +T__t}}-L  HHT\\$--0 1 GGDKK - FF4<< +T\\$**-E F KK 7rN)rcr)r_rfrgrhrorirprqrrrsrtrurvrwr] classmethodrZrrrrr r sJJHeFEFEE5E5HeHe  6 6 prr __main__)rrrcrra)r"rr#rrcr)N)r"rr#rbrcr)rh __future__rr6typingr dataclassesr__all__rrrrrrrr r r_sysdoctestexittestmodfailedrrrrs4l# ! N 8| (] hP hPV ;' ' ee eP z CHH_W__  % %& r