
    ]Mh=                    0   d Z ddlmZ ddlZddlmZ ddlmZ g dZdZ	de	z
  Z
d	e	z   ZddZ G d de          Z e            ZdddZdddZe G d d                      Zedk    r,ddlZddlZ ej         ej                    j                   dS dS )a7  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)]
	>>>
    )annotationsN)
NamedTuple)	dataclass)	TransformIdentityOffsetScaleDecomposedTransformgV瞯<   vfloatreturnc                r    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)r   s    X/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/fontTools/misc/transform.py_normSinCosr   F   sB    
1vv	
\			
		H    c                      e Zd ZU dZdZded<   dZded<   dZded<   dZded<   dZ	ded	<   dZ
ded
<   d Zd Zd Zd Zd#d$dZd%d&dZd'dZd#d$dZd Zd Z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   r   xxr   xyyxyydxdyc                V    |\  }}| \  }}}}}}	||z  ||z  z   |z   ||z  ||z  z   |	z   fS )zTransform a point.

        :Example:

                >>> t = Transform()
                >>> t = t.scale(2.5, 5.5)
                >>> t.transformPoint((100, 100))
                (250.0, 550.0)
         )
selfpxyr   r   r   r   r   r   s
             r   transformPointzTransform.transformPoint   sL     A!%BBBQa"$b1frAvo&:;;r   c                F    | \  fd|D             S )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)]
                >>>
        c                N    g | ]!\  }}|z  |z  z   z   |z  |z  z   z   f"S r    r    )	.0r#   r$   r   r   r   r   r   r   s	      r   
<listcomp>z-Transform.transformPoints.<locals>.<listcomp>   sD    PPPAa"q&2%rAvQ';<PPPr   r    )r!   pointsr   r   r   r   r   r   s     @@@@@@r   transformPointszTransform.transformPoints   sE     "&BBBPPPPPPPPPPPPPr   c                V    |\  }}| dd         \  }}}}||z  ||z  z   ||z  ||z  z   fS )zTransform 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   s           r   transformVectorzTransform.transformVector   sG     RbqbBBR"r'!27R"W#455r   c                J    | dd         \  fd|D             S )a  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                B    g | ]\  }}|z  |z  z   |z  |z  z   fS r    r    )r(   r   r   r   r   r   r   s      r   r)   z.Transform.transformVectors.<locals>.<listcomp>   s<    MMM62rb27"BGb2g$56MMMr   r    )r!   vectorsr   r   r   r   s     @@@@r   transformVectorszTransform.transformVectors   s@     bqbBBMMMMMMMWMMMMr   r#   r$   c                8    |                      dddd||f          S )zReturn 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$   s      r   	translatezTransform.translate   s#     ~~q!Q1a0111r   Nfloat | Nonec                @    ||}|                      |dd|ddf          S )ak  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   r4   r6   s      r   scalezTransform.scale   s-     9A~~q!Q1a0111r   anglec                    t          t          j        |                    }t          t          j        |                    }|                     ||| |ddf          S )a  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   )r   mathcossinr5   )r!   r;   css       r   rotatezTransform.rotate   sO     ((((~~q!aRAq1222r   c                    |                      dt          j        |          t          j        |          dddf          S )zReturn 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   r   )r5   r=   tanr6   s      r   skewzTransform.skew  s3     ~~q$(1++tx{{Aq!DEEEr   c           
         |\  }}}}}}| \  }}	}
}}}|                      ||z  ||
z  z   ||	z  ||z  z   ||z  ||
z  z   ||	z  ||z  z   ||z  |
|z  z   |z   |	|z  ||z  z   |z             S )a  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!   otherxx1xy1yx1yy1dx1dy1xx2xy2yx2yy2dx2dy2s                 r   r5   zTransform.transform  s     (-$S#sC'+$S#sC~~#Ic	!#Ic	!#Ic	!#Ic	!#Ic	!C'#Ic	!C'
 
 	
r   c           
         | \  }}}}}}|\  }}	}
}}}|                      ||z  ||
z  z   ||	z  ||z  z   ||z  ||
z  z   ||	z  ||z  z   ||z  |
|z  z   |z   |	|z  ||z  z   |z             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]>
                >>>
        rG   rI   s                 r   reverseTransformzTransform.reverseTransform%  s     (,$S#sC',$S#sC~~#Ic	!#Ic	!#Ic	!#Ic	!#Ic	!C'#Ic	!C'
 
 	
r   c                    | t           k    r| S | \  }}}}}}||z  ||z  z
  }||z  | |z  | |z  ||z  f\  }}}}| |z  ||z  z
  | |z  ||z  z
  }}|                     ||||||          S )aK  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   rH   )r!   r   r   r   r   r   r   dets           r   inversezTransform.inverse=  s     8K!%BBB2gRcB39rcCicABBrBG#bS2XR%7B~~b"b"b"555r   r   strc                    d| z  S )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]r    r!   s    r   toPSzTransform.toPSQ  s     %t++r   'DecomposedTransform'c                6    t                               |           S )z%Decompose into a DecomposedTransform.)r
   fromTransformr^   s    r   toDecomposedzTransform.toDecomposed]  s    "00666r   boolc                    | 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   r^   s    r   __bool__zTransform.__bool__a  s    ( xr   c                (    d| j         j        f| z   z  S )Nz<%s [%g %g %g %g %g %g]>)rH   __name__r^   s    r   __repr__zTransform.__repr__w  s    )dn.E-G$-NOOr   r   r   )r#   r   r$   r   )r   N)r#   r   r$   r8   )r;   r   )r   r\   )r   r`   )r   rd   )rh   
__module____qualname____doc__r   __annotations__r   r   r   r   r   r%   r+   r.   r2   r7   r:   rB   rE   r5   rX   r[   r_   rc   rf   ri   r    r   r   r   r   P   s        L L\ BMMMMBMMMMBMMMMBMMMMBMMMMBMMMM< < <Q Q Q6 6 6
N 
N 
N	2 	2 	2 	2 	22 2 2 2 2 3 3 3 3
F 
F 
F 
F 
F
 
 
*
 
 
06 6 6(
, 
, 
, 
,7 7 7 7       ,P P P P P Pr   r   r#   r$   c                *    t          dddd| |          S )zReturn the identity transformation offset by x, y.

    :Example:
            >>> Offset(2, 3)
            <Transform [1 0 0 1 2 3]>
            >>>
    r   r   r   r#   r$   s     r   r   r   ~  s     Q1aA&&&r   r8   c                2    || }t          | dd|dd          S )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)
            <Transform [2 0 0 3 0 0]>
            >>>
    Nr   rp   rq   s     r   r	   r	     s&     	yQ1aA&&&r   c                      e Zd ZU dZdZded<   dZded<   dZded<   dZded<   dZ	ded	<   dZ
ded
<   dZded<   dZded<   dZded<   d Zed             ZddZdS )r
   zThe DecomposedTransform class implements a transformation with separate
    translate, rotation, scale, skew, and transformation-center components.
    r   r   
translateX
translateYrotationr   scaleXscaleYskewXskewYtCenterXtCenterYc                    | j         dk    pW| j        dk    pL| j        dk    pA| j        dk    p6| j        dk    p+| j        dk    p | j        dk    p| j        dk    p
| j        dk    S )Nr   r   )	rt   ru   rv   rw   rx   ry   rz   r{   r|   r^   s    r   rf   zDecomposedTransform.__bool__  s    Oq  "!#"}!" {a" {a	"
 zQ" zQ" }!" }!
	
r   c                   |\  }}}}}}t          j        d|          }|dk     r
||z  }||z  }||z  ||z  z
  }	d}
dx}}d}|dk    s|dk    r}t          j        ||z  ||z  z             }|dk    rt          j        ||z            nt          j        ||z             }
||	|z  }}t          j        ||z  ||z  z   ||z  z            }nx|dk    s|dk    rkt          j        ||z  ||z  z             }t           j        dz  |dk    rt          j        | |z            nt          j        ||z             z
  }
|	|z  |}}n	 t          ||t          j        |
          ||z  |t          j        |          |z  ddd	  	        S )au  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)
        r   r      g        )r=   copysignsqrtacosatanpir
   degrees)r!   r5   abr@   dr#   r$   sxdeltarv   rw   rx   ry   rrA   s                   r   rb   z!DecomposedTransform.fromTransform  s     %1aAq]1a  66GAGAAA 66Q!VV	!a%!a%-((A+,66tyQ'''	!a%8H8H7HHFFIq1uq1u}Q788EE!VVqAvv	!a%!a%-((Aw{%&!VV	1"q&!!!$)AE2B2B1BH $aiFFF "L""RKL"$

 

 
	
r   r   r   c                   t                      }|                    | j        | j        z   | j        | j        z             }|                    t          j        | j	                            }|
                    | j        | j                  }|                    t          j        | j                  t          j        | j                            }|                    | j         | j                   }|S )zReturn the Transform() equivalent of this transformation.

        :Example:
                >>> DecomposedTransform(scaleX=2, scaleY=2).toTransform()
                <Transform [2 0 0 2 0 0]>
                >>>
        )r   r7   rt   r{   ru   r|   rB   r=   radiansrv   r:   rw   rx   rE   ry   rz   )r!   ts     r   toTransformzDecomposedTransform.toTransform  s     KKKKOdm+T_t}-L
 
 HHT\$-0011GGDK--FF4<
++T\$*-E-EFFKK77r   N)r   r   )rh   rk   rl   rm   rt   rn   ru   rv   rw   rx   ry   rz   r{   r|   rf   classmethodrb   r   r    r   r   r
   r
     s           JJHFFEEHH
 
 
 6
 6
 [6
p     r   r
   __main__)r   r   r   r   rj   )r#   r   r$   r   r   r   )N)r#   r   r$   r8   r   r   )rm   
__future__r   r=   typingr   dataclassesr   __all__r   r   r   r   r   r   r   r	   r
   rh   sysdoctestexittestmodfailedr    r   r   <module>r      s  4 4l # " " " " "        ! ! ! ! ! ! N
M
M 8|(]    hP hP hP hP hP
 hP hP hPV	 9;;' ' ' ' '' ' ' ' ' e e e e e e e eP zJJJNNNCH_W_%&&&&&	 r   