a
    èÝEb$  ã                   @   sŠ   d Z ddlmZ g d¢ZdZde Zde Zdd„ ZG d	d
„ d
eƒZeƒ Z	ddd„Z
ddd„Zedkr†ddlZddlZe e ¡ j¡ dS )a¦  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

: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)]
	>>>
é    )Ú
NamedTuple)Ú	TransformÚIdentityÚOffsetÚScalegVçž¯Ò<é   éÿÿÿÿc                 C   s0   t | ƒtk rd} n| tkr d} n| tk r,d} | S )Nr   r   r   )ÚabsÚ_EPSILONÚ_ONE_EPSILONÚ_MINUS_ONE_EPSILON)Úv© r   úX/home/ja/django-apps/lartica_env/lib/python3.9/site-packages/fontTools/misc/transform.pyÚ_normSinCos?   s    r   c                   @   sÐ   e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed< dZ
eed< dZeed	< d
d„ Zdd„ Zdd„ Zdd„ Zd'dd„Zd(dd„Zdd„ Zd)dd„Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ ZdS )*r   a„  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]>
	r   Úxxr   ÚxyÚyxÚyyÚdxÚdyc           
      C   s@   |\}}| \}}}}}}	|| ||  | || ||  |	 fS )z�Transform a point.

		:Example:

			>>> t = Transform()
			>>> t = t.scale(2.5, 5.5)
			>>> t.transformPoint((100, 100))
			(250.0, 550.0)
		r   )
ÚselfÚpÚxÚyr   r   r   r   r   r   r   r   r   ÚtransformPoint    s    
zTransform.transformPointc                    s,   | \‰‰‰‰‰ ‰‡ ‡‡‡‡‡fdd„|D ƒS )z¹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)]
			>>>
		c                    s8   g | ]0\}}ˆ| ˆ|  ˆ  ˆ| ˆ|  ˆ f‘qS r   r   )Ú.0r   r   ©r   r   r   r   r   r   r   r   Ú
<listcomp>¹   ó    z-Transform.transformPoints.<locals>.<listcomp>r   )r   Zpointsr   r   r   ÚtransformPoints®   s    
zTransform.transformPointsc                 C   s<   |\}}| dd… \}}}}|| ||  || ||  fS )z©Transform an (dx, dy) vector, treating translation as zero.

		:Example:

			>>> t = Transform(2, 0, 0, 2, 10, 20)
			>>> t.transformVector((3, -4))
			(6, -8)
			>>>
		Né   r   )r   r   r   r   r   r   r   r   r   r   r   ÚtransformVector»   s    
zTransform.transformVectorc                    s,   | dd… \‰ ‰‰‰‡ ‡‡‡fdd„|D ƒS )zÈ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)]
			>>>
		Nr!   c                    s0   g | ](\}}ˆ | ˆ|  ˆ| ˆ|  f‘qS r   r   )r   r   r   ©r   r   r   r   r   r   r   Ó   r   z.Transform.transformVectors.<locals>.<listcomp>r   )r   Zvectorsr   r#   r   ÚtransformVectorsÉ   s    	zTransform.transformVectorsc                 C   s   |   dddd||f¡S )z¡Return a new transformation, translated (offset) by x, y.

		:Example:
			>>> t = Transform()
			>>> t.translate(20, 30)
			<Transform [1 0 0 1 20 30]>
			>>>
		r   r   ©Ú	transform©r   r   r   r   r   r   Ú	translateÕ   s    	zTransform.translateNc                 C   s"   |du r|}|   |dd|ddf¡S )a  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]>
			>>>
		Nr   r%   r'   r   r   r   Úscaleà   s    zTransform.scalec                 C   s<   ddl }t| |¡ƒ}t| |¡ƒ}|  ||| |ddf¡S )z¶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]>
			>>>
		r   N)Úmathr   ÚcosÚsinr&   )r   Zangler*   ÚcÚsr   r   r   Úrotateð   s    
zTransform.rotatec                 C   s*   ddl }|  d| |¡| |¡dddf¡S )z¨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]>
			>>>
		r   Nr   )r*   r&   Útan)r   r   r   r*   r   r   r   Úskewÿ   s    
zTransform.skewc              
   C   s„   |\}}}}}}| \}}	}
}}}|   || ||
  ||	 ||  || ||
  ||	 ||  || |
|  | |	| ||  | ¡S )zÉ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]>
			>>>
		©Ú	__class__©r   ÚotherZxx1Zxy1Zyx1Zyy1Zdx1Zdy1Zxx2Zxy2Zyx2Zyy2Zdx2Zdy2r   r   r   r&     s    
úzTransform.transformc              
   C   s„   | \}}}}}}|\}}	}
}}}|   || ||
  ||	 ||  || ||
  ||	 ||  || |
|  | |	| ||  | ¡S )a‡  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]>
			>>>
		r2   r4   r   r   r   ÚreverseTransform   s    úzTransform.reverseTransformc                 C   sŽ   | t kr| S | \}}}}}}|| ||  }|| | | | | || f\}}}}| | ||  | | ||   }}|  ||||||¡S )zä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)
			>>>
		)r   r3   )r   r   r   r   r   r   r   Zdetr   r   r   Úinverse7  s    (&zTransform.inversec                 C   s   d|  S )zŽReturn 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]r   ©r   r   r   r   ÚtoPSK  s    
zTransform.toPSc                 C   s   | t kS )a)  Returns 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
		)r   r8   r   r   r   Ú__bool__W  s    zTransform.__bool__c                 C   s   d| j jf|   S )Nz<%s [%g %g %g %g %g %g]>)r3   Ú__name__r8   r   r   r   Ú__repr__m  s    zTransform.__repr__)r   r   )r   N)r   r   )r;   Ú
__module__Ú__qualname__Ú__doc__r   ÚfloatÚ__annotations__r   r   r   r   r   r   r    r"   r$   r(   r)   r/   r1   r&   r6   r7   r9   r:   r<   r   r   r   r   r   I   s*   
N


r   c                 C   s   t dddd| |ƒS )zuReturn the identity transformation offset by x, y.

	:Example:
		>>> Offset(2, 3)
		<Transform [1 0 0 1 2 3]>
		>>>
	r   r   ©r   ©r   r   r   r   r   r   s  s    r   Nc                 C   s   |du r| }t | dd|ddƒS )zÃ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]>
		>>>
	Nr   rB   rC   r   r   r   r   }  s    	r   Ú__main__)r   r   )N)r?   Útypingr   Ú__all__r
   r   r   r   r   r   r   r   r;   ÚsysÚdoctestÚexitÚtestmodÚfailedr   r   r   r   Ú<module>   s    3
  *


