
    ]Mh                     >   d Z ddlmZmZmZ ddlmZ ddlZddlm	Z	 	 ddl
Z
n# eef$ r	 ddlm
Z
 Y nw xY we
j        ZdZ e	dg d	          Zg d
ZdWdZd Z e
j        e
j                   e
j        e
j        e
j        e
j        e
j                   e
j        e
j        e
j        e
j                  d                                     Z e
j        e
j                   e
j        e
j        e
j        e
j        e
j                   e
j        e
j        e
j                  dWd                                    ZdZdZe
j        e
j         e
j        e
j                   e
j        e
j        e
j                  d                                                 Ze
j        e
j         e
j        e
j                   e
j        e
j                  d                                                 Z d Z! e
j        e
j                   e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j                   e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j                  d                                     Z"d Z# e
j        e
j                   e
j        e
j        e
j        e
j                   e
j        e
j        e
j        e
j                   d!                                     Z$d" Z%d# Z& e
j        e
j                   e
j        e
j        e
j        e
j        e
j                   e
j        e
j        e
j        e
j        e
j        e
j        $          d%                                     Z'd& Z(d' Z)d( Z*d) Z+d* Z,d+ Z- e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        ,          d-             Z. e
j        e
j                   e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        .           e
j        e
j        e
j        e
j        e
j        /          d0                                     Z/d1 Z0d2 Z1 e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        3          d4             Z2dd5lm3Z3m4Z4m5Z5m6Z6 e3fd6Z7d7 Z8d8 Z9d9 Z:e
j        e
j         e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        :          d;                                     Z;d< Z<d= Z=e
j        e
j         e
j        e
j        e
j        e
j        e
j        e
j        e
j        e
j        >          d?                                     Z>d@ Z?dA Z@dB ZA e
j        e
j                   e
j        e
j        e
j        e
j        e
j        e
j        C           e
j        e
j        e
j        e
j        D          dE                                     ZBdF ZCdG ZDdH ZEdI ZFdJ ZGdK ZHdL ZIdM ZJdN ZK	 dXdPZLdQ ZMdR ZNdS ZOdT ZPdU ZQeRdVk    r,ddlSZSddlTZT eSjU         eTjV                    jW                   dS dS )YzNfontTools.misc.bezierTools.py -- tools for working with Bezier path segments.
    )
calcBoundssectRectrectArea)IdentityN)
namedtuple)cythong&.>Intersectionptt1t2)approximateCubicArcLengthapproximateCubicArcLengthCapproximateQuadraticArcLengthapproximateQuadraticArcLengthCcalcCubicArcLengthcalcCubicArcLengthCcalcQuadraticArcLengthcalcQuadraticArcLengthCcalcCubicBoundscalcQuadraticBounds	splitLinesplitQuadratic
splitCubicsplitQuadraticAtTsplitCubicAtTsplitCubicAtTCsplitCubicIntoTwoAtTCsolveQuadratic
solveCubicquadraticPointAtTcubicPointAtTcubicPointAtTClinePointAtTsegmentPointAtTlineLineIntersectionscurveLineIntersectionscurveCurveIntersectionssegmentSegmentIntersections{Gzt?c                 `    t          t          |  t          | t          | t          | |          S )a  Calculates the arc length for a cubic Bezier segment.

    Whereas :func:`approximateCubicArcLength` approximates the length, this
    function calculates it by "measuring", recursively dividing the curve
    until the divided segments are shorter than ``tolerance``.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        tolerance: Controls the precision of the calcuation.

    Returns:
        Arc length value.
    )r   complex)pt1pt2pt3pt4	tolerances        Z/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/fontTools/misc/bezierTools.pyr   r   8   s1     w}gsmWc]I      c                 |    | d||z   z  z   |z   dz  }||z   |z
  | z
  dz  }| | |z   dz  ||z
  |f|||z   ||z   dz  |ffS )N   g      ?      ? )p0p1p2p3midderiv3s         r2   _split_cubic_into_twor>   K   so    R"W"e
+C2glR5(F	b2g_cFlC0	cFlR"WOR0 r3   )r8   r9   r:   r;   )multarchboxc                 (   t          ||z
            }t          ||z
            t          ||z
            z   t          ||z
            z   }|| z  t          z   |k    r||z   dz  S t          ||||          \  }}t          | g|R  t          | g|R  z   S Nr6   )absEPSILONr>   _calcCubicArcLengthCRecurse)	r?   r8   r9   r:   r;   r@   rA   onetwos	            r2   rF   rF   T   s     rBw<<D
b2g,,R"W
%BG
4Cd{W##s
c!!(RR88S*46#6669T:
:
 :
 :
 
 	
r3   r-   r.   r/   r0   )r1   r?   c                 8    dd|z  z   }t          || |||          S )zCalculates the arc length for a cubic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.
        tolerance: Controls the precision of the calcuation.

    Returns:
        Arc length value.
          ?g      ?)rF   )r-   r.   r/   r0   r1   r?   s         r2   r   r   h   s(    * y D&tS#sC@@@r3      g|=v1v2c                 :    | |                                 z  j        S N)	conjugaterealrM   s     r2   _dotrT      s    
 %%r3   xc                 r    | t          j        | dz  dz             z  dz  t          j        |           dz  z   S )N      )mathsqrtasinhrU   s    r2   _intSecAtanr]      s8     tyA"""Q&A):::r3   c                 N    t          t          |  t          | t          |           S )a  Calculates the arc length for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as 2D tuple.
        pt2: Handle point of the Bezier as 2D tuple.
        pt3: End point of the Bezier as 2D tuple.

    Returns:
        Arc length value.

    Example::

        >>> calcQuadraticArcLength((0, 0), (0, 0), (0, 0)) # empty segment
        0.0
        >>> calcQuadraticArcLength((0, 0), (50, 0), (80, 0)) # collinear points
        80.0
        >>> calcQuadraticArcLength((0, 0), (0, 50), (0, 80)) # collinear points vertical
        80.0
        >>> calcQuadraticArcLength((0, 0), (50, 20), (100, 40)) # collinear points
        107.70329614269008
        >>> calcQuadraticArcLength((0, 0), (0, 100), (100, 0))
        154.02976155645263
        >>> calcQuadraticArcLength((0, 0), (0, 50), (100, 0))
        120.21581243984076
        >>> calcQuadraticArcLength((0, 0), (50, -10), (80, 50))
        102.53273816445825
        >>> calcQuadraticArcLength((0, 0), (40, 0), (-40, 0)) # collinear points, control point outside
        66.66666666666667
        >>> calcQuadraticArcLength((0, 0), (40, 0), (0, 0)) # collinear points, looping back
        40.0
    )r   r,   r-   r.   r/   s      r2   r   r      s#    @ #7C='3-#OOOr3   )r-   r.   r/   d0d1dn)scaleorigDistabx0x1Lenc                 8   || z
  }||z
  }||z
  }|dz  }t          |          }|dk    rt          || z
            S t          ||          }t          |          t          k     rUt          ||          dk    rt          || z
            S t          |          t          |          }
}	|	|	z  |
|
z  z   |	|
z   z  S t          ||          |z  }t          ||          |z  }t          dt          |          t          |          z
  z  |z  |||z
  z  z            }|S )a$  Calculates the arc length for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as a complex number.
        pt2: Handle point of the Bezier as a complex number.
        pt3: End point of the Bezier as a complex number.

    Returns:
        Arc length value.
    y              ?        r   rX   )rD   rT   epsilonr]   )r-   r.   r/   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   s                 r2   r   r      s   @ 
sB	sB
RA	BAFFE||39~~Ar{{H
8}}wB<<1sSy>>!2wwB1AA!a%((	ax	B	ax	B
a;r??[__45@ERRTWDUV
W
WCJr3   c                 N    t          t          |  t          | t          |           S )a  Calculates the arc length for a quadratic Bezier segment.

    Uses Gauss-Legendre quadrature for a branch-free approximation.
    See :func:`calcQuadraticArcLength` for a slower but more accurate result.

    Args:
        pt1: Start point of the Bezier as 2D tuple.
        pt2: Handle point of the Bezier as 2D tuple.
        pt3: End point of the Bezier as 2D tuple.

    Returns:
        Approximate arc length value.
    )r   r,   r_   s      r2   r   r      s#     *'3-#QTVVVr3   r_   )v0rN   rO   c                     t          d| z  d|z  z   d|z  z             }t          || z
            dz  }t          d| z  d|z  z
  d|z  z             }||z   |z   S )a  Calculates the arc length for a quadratic Bezier segment.

    Uses Gauss-Legendre quadrature for a branch-free approximation.
    See :func:`calcQuadraticArcLength` for a slower but more accurate result.

    Args:
        pt1: Start point of the Bezier as a complex number.
        pt2: Handle point of the Bezier as a complex number.
        pt3: End point of the Bezier as a complex number.

    Returns:
        Approximate arc length value.
    g̔xb߿gb?gFVW?gqq?gFVWg̔xb?rD   )r-   r.   r/   ro   rN   rO   s         r2   r   r      s    B 
S #4s#::=ORU=UU
 
B 
S3Y,	,B	c!$5$;;>ORU>UU
 
B 7R<r3   c                 ,  	
 t          | ||          \  \  \  	
\  dz  }dz  }g }|dk    r|                    	 |z             |dk    r|                    
 |z             	
fd|D             | |gz   }t          |          S )a  Calculates the bounding rectangle for a quadratic Bezier segment.

    Args:
        pt1: Start point of the Bezier as a 2D tuple.
        pt2: Handle point of the Bezier as a 2D tuple.
        pt3: End point of the Bezier as a 2D tuple.

    Returns:
        A four-item tuple representing the bounding rectangle ``(xMin, yMin, xMax, yMax)``.

    Example::

        >>> calcQuadraticBounds((0, 0), (50, 100), (100, 0))
        (0, 0, 100, 50.0)
        >>> calcQuadraticBounds((0, 0), (100, 0), (100, 100))
        (0.0, 0.0, 100, 100)
           @r   c                 t    g | ]4}d |cxk    rdk     n n"|z  |z  |z  z   z   |z  |z  |z  z   z   f5S r   rY   r7   ).0taxaybxbycxcys     r2   
<listcomp>z'calcQuadraticBounds.<locals>.<listcomp>D  sk       ::::A::::: 
a!b1f	r	!26A:Q#6#;<::r3   )calcQuadraticParametersappendr   )r-   r.   r/   ax2ay2rootspointsrx   ry   rz   r{   r|   r}   s          @@@@@@r2   r   r   *  s    $ $;3S#I#I HRhr2R
s(C
s(CE
axxbS3Y
axxbS3Y           
c
	F
 fr3   c                 ^    t          t          |  t          | t          | t          |           S )a  Approximates the arc length for a cubic Bezier segment.

    Uses Gauss-Lobatto quadrature with n=5 points to approximate arc length.
    See :func:`calcCubicArcLength` for a slower but more accurate result.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.

    Returns:
        Arc length value.

    Example::

        >>> approximateCubicArcLength((0, 0), (25, 100), (75, 100), (100, 0))
        190.04332968932817
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 50), (100, 100))
        154.8852074945903
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (150, 0)) # line; exact result should be 150.
        149.99999999999991
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, 0), (-50, 0)) # cusp; exact result should be 150.
        136.9267662156362
        >>> approximateCubicArcLength((0, 0), (50, 0), (100, -50), (-50, 0)) # cusp
        154.80848416537057
    )r   r,   rI   s       r2   r   r   L  s/    2 &w}gsmWc]  r3   )ro   rN   rO   v3v4c                 8   t          || z
            dz  }t          d| z  d|z  z   d|z  z   d|z  z             }t          || z
  |z   |z
            dz  }t          d| z  d|z  z
  d|z  z
  d|z  z             }t          ||z
            dz  }||z   |z   |z   |z   S )	zApproximates the arc length for a cubic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.

    Returns:
        Arc length value.
    g333333?gc1g85$t?gu|Y?g#$?g?g#$gc1?rq   )	r-   r.   r/   r0   ro   rN   rO   r   r   s	            r2   r   r   j  s    > 
S3Y$	B	S 
c
!	"
c
!	" c
!	"
 
B 
S3Y_s"	#	#&9	9B	S 
c
!	"
c
!	" c
!	"
 
B 
S3Y$	B7R<"r!!r3   c                 H   t          | |||          \  \  \  \  \  dz  }dz  }dz  }dz  }d t          ||          D             }d t          ||          D             }	||	z   }
fd|
D             | |gz   }t          |          S )aX  Calculates the bounding rectangle for a quadratic Bezier segment.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.

    Returns:
        A four-item tuple representing the bounding rectangle ``(xMin, yMin, xMax, yMax)``.

    Example::

        >>> calcCubicBounds((0, 0), (25, 100), (75, 100), (100, 0))
        (0, 0, 100, 75.0)
        >>> calcCubicBounds((0, 0), (50, 0), (100, 50), (100, 100))
        (0.0, 0.0, 100, 100)
        >>> print("%f %f %f %f" % calcCubicBounds((50, 0), (0, 100), (100, 100), (50, 0)))
        35.566243 0.000000 64.433757 75.000000
          @rs   c                 2    g | ]}d |cxk    rdk     n n|S ru   r7   rv   rw   s     r2   r~   z#calcCubicBounds.<locals>.<listcomp>  -    DDDAa!ar3   c                 2    g | ]}d |cxk    rdk     n n|S ru   r7   r   s     r2   r~   z#calcCubicBounds.<locals>.<listcomp>  r   r3   c                     g | ]<}|z  |z  |z  |z  |z  z   |z  z   z   |z  |z  |z  |z  |z  z   |z  z   	z   f=S r7   r7   )
rv   rw   rx   ry   rz   r{   r|   r}   dxdys
     r2   r~   z#calcCubicBounds.<locals>.<listcomp>  s       
  FQJNR!VaZ'"q&025FQJNR!VaZ'"q&025	
  r3   )calcCubicParametersr   r   )r-   r.   r/   r0   ax3ay3bx2by2xRootsyRootsr   r   rx   ry   rz   r{   r|   r}   r   r   s               @@@@@@@@r2   r   r     s   $ .Ac3PS-T-T*HRhr2R(2r
s(C
s(C
s(C
s(CDDS"55DDDFDDS"55DDDFVOE          
    
c
F fr3   c                     | \  }}|\  }}||z
  }||z
  }	|}
|}||	f|         }|dk    r| |fgS ||
|f|         z
  |z  }d|cxk    rdk     rn n||z  |
z   |	|z  |z   f}| |f||fgS | |fgS )a  Split a line at a given coordinate.

    Args:
        pt1: Start point of line as 2D tuple.
        pt2: End point of line as 2D tuple.
        where: Position at which to split the line.
        isHorizontal: Direction of the ray splitting the line. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two line segments (each line segment being two 2D tuples)
        if the line was successfully split, or a list containing the original
        line.

    Example::

        >>> printSegments(splitLine((0, 0), (100, 100), 50, True))
        ((0, 0), (50, 50))
        ((50, 50), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 100, True))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 0, True))
        ((0, 0), (0, 0))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((0, 0), (100, 100), 0, False))
        ((0, 0), (0, 0))
        ((0, 0), (100, 100))
        >>> printSegments(splitLine((100, 0), (0, 0), 50, False))
        ((100, 0), (50, 0))
        ((50, 0), (0, 0))
        >>> printSegments(splitLine((0, 100), (0, 0), 50, True))
        ((0, 100), (0, 50))
        ((0, 50), (0, 0))
    r   rY   r7   )r-   r.   whereisHorizontalpt1xpt1ypt2xpt2yrx   ry   rz   r{   rf   rw   midPts                  r2   r   r     s    H JD$JD$	B	B	B	B	RAAvvc
|	"b,'	'1,AAzzzzzzzzzQR!Vb[(eucl++c
|r3   c                     t          | ||          \  }}}t          ||         ||         ||         |z
            }t          d |D                       }|s| ||fgS t          |||g|R  S )a  Split a quadratic Bezier curve at a given coordinate.

    Args:
        pt1,pt2,pt3: Control points of the Bezier as 2D tuples.
        where: Position at which to split the curve.
        isHorizontal: Direction of the ray splitting the curve. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two curve segments (each curve segment being three 2D tuples)
        if the curve was successfully split, or a list containing the original
        curve.

    Example::

        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 150, False))
        ((0, 0), (50, 100), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, False))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, False))
        ((0, 0), (12.5, 25), (25, 37.5))
        ((25, 37.5), (62.5, 75), (100, 0))
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 25, True))
        ((0, 0), (7.32233, 14.6447), (14.6447, 25))
        ((14.6447, 25), (50, 75), (85.3553, 25))
        ((85.3553, 25), (92.6777, 14.6447), (100, -7.10543e-15))
        >>> # XXX I'm not at all sure if the following behavior is desirable:
        >>> printSegments(splitQuadratic((0, 0), (50, 100), (100, 0), 50, True))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (50, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
    c              3   :   K   | ]}d |cxk    rdk     n n|V  dS r   rY   Nr7   r   s     r2   	<genexpr>z!splitQuadratic.<locals>.<genexpr>"  6      ::QqAzzzzzzzzzqzzzz::r3   )r   r   sorted_splitQuadraticAtT)	r-   r.   r/   r   r   rf   rg   c	solutionss	            r2   r   r     s    F &c344GAq!	,<!L/E*A I ::):::::I !c3  aA2	2222r3   c                     t          | |||          \  }}}}	t          ||         ||         ||         |	|         |z
            }
t          d |
D                       }
|
s| |||fgS t          ||||	g|
R  S )a  Split a cubic Bezier curve at a given coordinate.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        where: Position at which to split the curve.
        isHorizontal: Direction of the ray splitting the curve. If true,
            ``where`` is interpreted as a Y coordinate; if false, then
            ``where`` is interpreted as an X coordinate.

    Returns:
        A list of two curve segments (each curve segment being four 2D tuples)
        if the curve was successfully split, or a list containing the original
        curve.

    Example::

        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 150, False))
        ((0, 0), (25, 100), (75, 100), (100, 0))
        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 50, False))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (68.75, 75), (87.5, 50), (100, 0))
        >>> printSegments(splitCubic((0, 0), (25, 100), (75, 100), (100, 0), 25, True))
        ((0, 0), (2.29379, 9.17517), (4.79804, 17.5085), (7.47414, 25))
        ((7.47414, 25), (31.2886, 91.6667), (68.7114, 91.6667), (92.5259, 25))
        ((92.5259, 25), (95.202, 17.5085), (97.7062, 9.17517), (100, 1.77636e-15))
    c              3   :   K   | ]}d |cxk    rdk     n n|V  dS r   r7   r   s     r2   r   zsplitCubic.<locals>.<genexpr>G  r   r3   )r   r    r   _splitCubicAtT)r-   r.   r/   r0   r   r   rf   rg   r   rb   r   s              r2   r   r   (  s    6 %S#sC88JAq!Q	,<!L/1\?U;R I ::):::::I &c3$%%!Q11y1111r3   c                 J    t          | ||          \  }}}t          |||g|R  S )a  Split a quadratic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3: Control points of the Bezier as 2D tuples.
        *ts: Positions at which to split the curve.

    Returns:
        A list of curve segments (each curve segment being three 2D tuples).

    Examples::

        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (75, 50), (100, 0))
        >>> printSegments(splitQuadraticAtT((0, 0), (50, 100), (100, 0), 0.5, 0.75))
        ((0, 0), (25, 50), (50, 50))
        ((50, 50), (62.5, 50), (75, 37.5))
        ((75, 37.5), (87.5, 25), (100, 0))
    )r   r   )r-   r.   r/   tsrf   rg   r   s          r2   r   r   M  s5    ( &c344GAq!aA+++++r3   c                     t          | |||          \  }}}}t          ||||g|R  }	| g|	d         dd         R |	d<   g |	d         dd         |R |	d<   |	S )a   Split a cubic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as 2D tuples.
        *ts: Positions at which to split the curve.

    Returns:
        A list of curve segments (each curve segment being four 2D tuples).

    Examples::

        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (68.75, 75), (87.5, 50), (100, 0))
        >>> printSegments(splitCubicAtT((0, 0), (25, 100), (75, 100), (100, 0), 0.5, 0.75))
        ((0, 0), (12.5, 50), (31.25, 75), (50, 75))
        ((50, 75), (59.375, 75), (68.75, 68.75), (77.3438, 56.25))
        ((77.3438, 56.25), (85.9375, 43.75), (93.75, 25), (100, 0))
    r   rY   N)r   r   )
r-   r.   r/   r0   r   rf   rg   r   rb   splits
             r2   r   r   e  s    ( %S#sC88JAq!Q1aA++++E
 #eAhqrrl##E!H&%)CRC.&#&&E"ILr3   )r-   r.   r/   r0   rf   rg   r   rb   c              '   d   K   t          | |||          \  }}}}t          ||||g|R  E d{V  dS )a  Split a cubic Bezier curve at one or more values of t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers..
        *ts: Positions at which to split the curve.

    Yields:
        Curve segments (each curve segment being four complex numbers).
    N)calcCubicParametersC_splitCubicAtTC)	r-   r.   r/   r0   r   rf   rg   r   rb   s	            r2   r   r     sW      ( &c3S99JAq!Qq!Q/B////////////r3   )rw   r-   r.   r/   r0   pointAtToff1off2)r   _1_t_1_t_2_2_t_1_tc                    ||z  }d|z
  }||z  }d|z  |z  }||z  | z  d||z  |z  ||z  |z  z   z  z   ||z  |z  z   }	|| z  ||z  z   ||z  z   }
||z  ||z  z   ||z  z   }| || z
  |z  z   }|||z
  |z  z   }| ||
|	f|	|||ffS )a  Split a cubic Bezier curve at t.

    Args:
        pt1,pt2,pt3,pt4: Control points of the Bezier as complex numbers.
        t: Position at which to split the curve.

    Returns:
        A tuple of two curve segments (each curve segment being four complex numbers).
    rY   rX   r5   r7   )r-   r.   r/   r0   rw   r   r   r   r   r   r   r   s               r2   r   r     s    0 
QBq5DD[F1ut|Ha6A:#3dRi#o#EFFaRUU  C<(S.(283DC<(S.(283D
sa
C
sd"
"C#tX&4c(BCCr3   c                    t          |          }g }|                    dd           |                    d           | \  }}|\  }}|\  }	}
t          t	          |          dz
            D ]}||         }||dz            }||z
  }||z  }||z  }||z  }d|z  |z  |z   |z  }d|z  |z  |z   |z  }||z  }||z  ||z  z   |	z   }||z  ||z  z   |
z   }t          ||f||f||f          \  }}}|                    |||f           |S )Nr   rl   rK   rY   rX   )listinsertr   rangelencalcQuadraticPoints)rf   rg   r   r   segmentsrx   ry   rz   r{   r|   r}   ir   r   deltadelta_2a1xa1yb1xb1yt1_2c1xc1yr-   r.   r/   s                             r2   r   r     sS   	bBHIIaIIcNNNFBFBFB3r77Q; ) )UAYR%-7l7l2v{R5(2v{R5(Bw4i"r'!B&4i"r'!B&+S#Jc
S#JOOS#c3((((Or3   c                    t          |          }|                    dd           |                    d           g }| \  }}|\  }}	|\  }
}|\  }}t          t	          |          dz
            D ]}||         }||dz            }||z
  }||z  }||z  }||z  }||z  }||z  }||z  }d|z  |z  |z   |z  }d|z  |z  |	z   |z  }d|z  |z  |
z   d|z  |z  z   |z  }d|	z  |z  |z   d|z  |z  z   |z  }||z  ||z  z   |
|z  z   |z   }||z  |	|z  z   ||z  z   |z   }t          ||f||f||f||f          \  }}} }!|                    ||| |!f           |S Nr   rl   rK   rY   r5   rX   )r   r   r   r   r   calcCubicPoints)"rf   rg   r   rb   r   r   rx   ry   rz   r{   r|   r}   r   r   r   r   r   r   r   delta_3r   t1_3r   r   r   r   r   r   d1xd1yr-   r.   r/   r0   s"                                     r2   r   r     s   	bBIIaIIcNNNHFBFBFBFB3r77Q; . .UAYR%-'/BwDy 7l7l2v{R7*2v{R7*2v{R!b&4-/582v{R!b&4-/584i"t)#b2g-24i"t)#b2g-2,#Jc
S#Jc

 
S#s 	c3,----Or3   )rf   rg   r   rb   r   r   r   r   r   a1b1c1ra   c              '     K   t          |          }|                    dd           |                    d           t          t	          |          dz
            D ]}||         }||dz            }||z
  }||z  }	||	z  }
||z  }||z  }| |
z  }d| z  |z  |z   |	z  }d|z  |z  |z   d| z  |z  z   |z  }| |z  ||z  z   ||z  z   |z   }t          ||||          \  }}}}||||fV  d S r   )r   r   r   r   r   calcCubicPointsC)rf   rg   r   rb   r   r   r   r   r   r   r   r   r   r   r   r   ra   r-   r.   r/   r0   s                        r2   r   r     s<       
bBIIaIIcNNN3r77Q; # #UAYR%-'/BwDy [!ebj1n'!ebj1nq1ut|+u4XD 1r6)A--b"b"==S#sCc"""""!# #r3   )r[   acoscospic                     t          |           t          k     r#t          |          t          k     rg }nB| |z  g}n:||z  d| z  |z  z
  }|dk    r$ ||          }| |z   dz  | z  | |z
  dz  | z  g}ng }|S )uK  Solve a quadratic equation.

    Solves *a*x*x + b*x + c = 0* where a, b and c are real.

    Args:
        a: coefficient of *x²*
        b: coefficient of *x*
        c: constant term

    Returns:
        A list of roots. Note that the returned list is neither guaranteed to
        be sorted nor to contain unique values!
          @rl   rs   rD   rm   )rf   rg   r   r[   r   DDrDDs          r2   r   r   /  s     1vvq66GEE R!VHEE US1Wq[ 99$r((Cb3h#%)QBH+;a+?@EE ELr3   c           
          t          |           t          k     rt          |||          S t          |           } || z  }|| z  }|| z  }||z  d|z  z
  dz  }d|z  |z  |z  d|z  |z  z
  d|z  z   dz  }||z  }	||z  |z  }
|	t          k     rdn|	}	t          |
          t          k     rdn|
}
|	|
z
  }|	dk    r$|
dk    rt	          | dz  t
                    }|||gS |t          dz  k    rt          t          t          |t          |
          z  d	          d
                    }dt          |          z  }|dz  }|t          |dz            z  |z
  }|t          |dt          z  z   dz            z  |z
  }|t          |dt          z  z   dz            z  |z
  }t          |||g          \  }}}||z
  t          k     r1||z
  t          k     r#t	          ||z   |z   dz  t
                    x}x}}n||z
  t          k     r3t	          ||z   dz  t
                    x}}t	          |t
                    }n||z
  t          k     r3t	          |t
                    }t	          ||z   dz  t
                    x}}n?t	          |t
                    }t	          |t
                    }t	          |t
                    }|||gS t          t          |          t          |          z   d          }|||z  z   }|dk    r| }t	          ||dz  z
  t
                    }|gS )ut  Solve a cubic equation.

    Solves *a*x*x*x + b*x*x + c*x + d = 0* where a, b, c and d are real.

    Args:
        a: coefficient of *x³*
        b: coefficient of *x²*
        c: coefficient of *x*
        d: constant term

    Returns:
        A list of roots. Note that the returned list is neither guaranteed to
        be sorted nor to contain unique values!

    Examples::

        >>> solveCubic(1, 1, -6, 0)
        [-3.0, -0.0, 2.0]
        >>> solveCubic(-10.0, -9.0, 48.0, -29.0)
        [-2.9, 1.0, 1.0]
        >>> solveCubic(-9.875, -9.0, 47.625, -28.75)
        [-2.911392, 1.0, 1.0]
        >>> solveCubic(1.0, -4.5, 6.75, -3.375)
        [1.5, 1.5, 1.5]
        >>> solveCubic(-12.0, 18.0, -9.0, 1.50023651123)
        [0.5, 0.5, 0.5]
        >>> solveCubic(
        ...     9.0, 0.0, 0.0, -7.62939453125e-05
        ... ) == [-0.0, -0.0, -0.0]
        True
    r   g      "@rs   g      ;@g      K@r   rl   r6   rK   g      g       r   UUUUUU?)rD   rm   r   floatroundepsilonDigitsr   maxminr[   r   r   r   pow)rf   rg   r   rb   r   a2a3QRR2Q3R2_Q3rV   thetarQ2a1_3rh   ri   x2s                      r2   r    r    P  s0   L 1vv aA&&&aA	
QB	
QB	
QB	b38	s"A	rB	cBhm	+dRi	74?A	
QB	
QB7llB"ggRBGE	SyyR3YY2#)]++1ay	'C-		SQb\3//6677T!WWnCx3us{###d*3b(C/000473b(C/00047RRL))
B7Wb7!2!2 "r'B,#!5}EEEBEbb"WwR"WO];;;Br=))BB"Wwr=))BR"WO];;;Br=))Br=))Br=))BB|Uc!ff$g..AI88A!b3h,..s
r3   c                 v    |\  }}|\  }}| \  }}||z
  dz  }	||z
  dz  }
||z
  |	z
  }||z
  |
z
  }||f|	|
f||ffS )Nrs   r7   )r-   r.   r/   r   y2x3y3r|   r}   rz   r{   rx   ry   s                r2   r   r     sj    FBFBFB
r'SB
r'SB	b2B	b2B8b"XBx''r3   c                     |\  }}|\  }}|\  }}	| \  }
}||
z
  dz  }||z
  dz  }||z
  dz  |z
  }||z
  dz  |z
  }||
z
  |z
  |z
  }|	|z
  |z
  |z
  }||f||f||f|
|ffS Nr   r7   )r-   r.   r/   r0   r   r   r   r   x4y4r   r   r|   r}   rz   r{   rx   ry   s                     r2   r   r     s    FBFBFBFB
r'SB
r'SB
r'S2	B
r'S2	B	b2	B	b2	B8b"XBx"b11r3   )r-   r.   r/   r0   rf   rg   r   c                 J    || z
  dz  }||z
  dz  |z
  }|| z
  |z
  |z
  }|||| fS r   r7   )r-   r.   r/   r0   r   rg   rf   s          r2   r   r     sE     
scA	scAAc	AAq!S>r3   c                 ~    | \  }}|\  }}|\  }}|}	|}
|dz  |z   }|dz  |z   }||z   |z   }||z   |z   }|	|
f||f||ffS rC   r7   )rf   rg   r   rx   ry   rz   r{   r|   r}   ri   y1r   r   r   r   s                  r2   r   r     st    FBFBFB	B	B
s(bB
s(bB	b2B	b2B8b"XBx''r3   c                     | \  }}|\  }}|\  }}	|\  }
}|
}|}|dz  |
z   }|	dz  |z   }||z   dz  |z   }||	z   dz  |z   }||
z   |z   |z   }||z   |	z   |z   }||f||f||f||ffS r   r7   )rf   rg   r   rb   rx   ry   rz   r{   r|   r}   r   r   ri   r   r   r   r   r   r   r   s                       r2   r   r     s    FBFBFBFB	B	B
s(bB
s(bB
r'S2	B
r'S2	B	b2	B	b2	B8b"XBx"b11r3   rf   rg   r   rb   r:   r;   p4c                 J    |dz  |z   }||z   dz  |z   }| |z   |z   |z   }||||fS )Nr   r7   r   s          r2   r   r     sC     
eqB
a%E	R	B	
QQBr2r?r3   c                 j    | d         d|z
  z  |d         |z  z   | d         d|z
  z  |d         |z  z   fS )zFinds the point at time `t` on a line.

    Args:
        pt1, pt2: Coordinates of the line as 2D tuples.
        t: The time along the line.

    Returns:
        A 2D tuple with the coordinates of the point.
    r   rY   r7   )r-   r.   rw   s      r2   r$   r$     sC     Vq1uA
*c!fA.>Q!.KMMr3   c                     d|z
  d|z
  z  | d         z  dd|z
  z  |z  |d         z  z   ||z  |d         z  z   }d|z
  d|z
  z  | d         z  dd|z
  z  |z  |d         z  z   ||z  |d         z  z   }||fS )zFinds the point at time `t` on a quadratic curve.

    Args:
        pt1, pt2, pt3: Coordinates of the curve as 2D tuples.
        t: The time along the curve.

    Returns:
        A 2D tuple with the coordinates of the point.
    rY   r   rX   r7   )r-   r.   r/   rw   rV   ys         r2   r!   r!     s     
Q1q5CF"Q!a%[1_s1v%==AANA	
Q1q5CF"Q!a%[1_s1v%==AANAq6Mr3   c                     ||z  }d|z
  }||z  }||z  | d         z  d||z  |d         z  ||z  |d         z  z   z  z   ||z  |d         z  z   }||z  | d         z  d||z  |d         z  ||z  |d         z  z   z  z   ||z  |d         z  z   }	||	fS )zFinds the point at time `t` on a cubic curve.

    Args:
        pt1, pt2, pt3, pt4: Coordinates of the curve as 2D tuples.
        t: The time along the curve.

    Returns:
        A 2D tuple with the coordinates of the point.
    rY   r   r5   r7   )
r-   r.   r/   r0   rw   r   r   r   rV   r  s
             r2   r"   r"   ,  s     
QBq5DD[FA
vzCF"TBYQ%77
8	9
q&3q6/	  	A
vzCF"TBYQ%77
8	9
q&3q6/	 
 q6Mr3   )rw   r-   r.   r/   r0   )r   r   r   c                 l    ||z  }d|z
  }||z  }||z  | z  d||z  |z  ||z  |z  z   z  z   ||z  |z  z   S )zFinds the point at time `t` on a cubic curve.

    Args:
        pt1, pt2, pt3, pt4: Coordinates of the curve as complex numbers.
        t: The time along the curve.

    Returns:
        A complex number with the coordinates of the point.
    rY   r5   r7   )r-   r.   r/   r0   rw   r   r   r   s           r2   r#   r#   F  s]    & 
QBq5DD[FD=3fqj3&6S&H!IIBQRFUXLXXr3   c                     t          |           dk    rt          g | |R  S t          |           dk    rt          g | |R  S t          |           dk    rt          g | |R  S t	          d          NrX   r5      Unknown curve degree)r   r$   r!   r"   
ValueError)segrw   s     r2   r%   r%   _  s    
3xx1}}$S$!$$$$	SQ )#)q))))	SQ%c%1%%%%
+
,
,,r3   c                    | \  }}|\  }}|\  }}t          ||z
            t          k     rt          ||z
            t          k     rdS t          ||z
            t          ||z
            k    r||z
  ||z
  z  S ||z
  ||z
  z  S )Nr   r   )	ser   sxsyexeypxpys	            r2   _line_t_of_ptr  n  s    FBFBFB
27||g#b2g,,"8"8r
27||c"r'll""RBG$$RBG$$r3   c                     | d         |d         z
  |d         |d         z
  z  }| d         |d         z
  |d         |d         z
  z  }|dk    o|dk     S )Nr   rY   rl   r7   )rf   rg   originxDiffyDiffs        r2   '_both_points_are_on_same_side_of_originr  |  s`    qTF1I!A$"23EqTF1I!A$"23E-#..r3   c           	         | \  }}|\  }}|\  }}	|\  }
}t          j        ||
          r,t          j        ||          rt          j        ||          sg S t          j        |	|          r,t          j        ||          rt          j        ||	          sg S t          j        ||
          rt          j        |	|          rg S t          j        ||          rt          j        ||          rg S t          j        ||          rM|}||	z
  |
|z
  z  }|||z
  z  |	z   }||f}t          |t          | ||          t          |||                    gS t          j        ||
          rM|}||z
  ||z
  z  }|||z
  z  |z   }||f}t          |t          | ||          t          |||                    gS ||z
  ||z
  z  }||	z
  |
|z
  z  }t          j        ||          rg S ||z  |z
  ||z  z
  |	z   ||z
  z  }|||z
  z  |z   }||f}t	          |||           rBt	          |||          r1t          |t          | ||          t          |||                    gS g S )a  Finds intersections between two line segments.

    Args:
        s1, e1: Coordinates of the first line as 2D tuples.
        s2, e2: Coordinates of the second line as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::

        >>> a = lineLineIntersections( (310,389), (453, 222), (289, 251), (447, 367))
        >>> len(a)
        1
        >>> intersection = a[0]
        >>> intersection.pt
        (374.44882952482897, 313.73458370177315)
        >>> (intersection.t1, intersection.t2)
        (0.45069111555824465, 0.5408153767394238)
    r
   )rZ   iscloser	   r  r  )s1e1s2e2s1xs1ye1xe1ys2xs2ye2xe2yrV   slope34r  r   slope12s                    r2   r&   r&     s    . HCHCHCHCS##'<S#9#9BF,sTWBXBX 	S##'<S#9#9BF,sTWBXBX 	|C $,sC"8"8 	|C $,sC"8"8 	|C 	
9s+q3w#%V-B33b"b8Q8Q  
 	

 |C 	
9s+q3w#%V-B33b"b8Q8Q  
 	
 SyS3Y'GSyS3Y'G|GW%% 		3	w}	,s	2w7HIA1s7c!A
QB.
B  

1"b"
=
=
 -B33b"b8Q8Q  
 	

 Ir3   c                     | d         }| d         }t          j        |d         |d         z
  |d         |d         z
            }t          j        |                               |d          |d                    S )Nr   r   rY   )rZ   atan2r   rotate	translate)segmentstartendangles       r2   _alignment_transformationr5    so     AJE
"+CJs1va(#a&58*;<<E?E6"",,eAhYq	BBBr3   c                    t          |                              |           }t          |           dk    r1t          | \  }}}t	          |d         |d         |d                   }n[t          |           dk    r9t          | \  }}}}t          |d         |d         |d         |d                   }nt          d          t          d |D                       S )Nr5   rY   r
  r  c              3   :   K   | ]}d |cxk    rdk    n n|V  dS )rl   rY   Nr7   rv   r   s     r2   r   z._curve_line_intersections_t.<locals>.<genexpr>  s6      <<cQmmmm!mmmmm!mmmm<<r3   )	r5  transformPointsr   r   r   r   r    r  r   )curvelinealigned_curverf   rg   r   intersectionsrb   s           r2   _curve_line_intersections_tr>    s    -d33CCEJJM
5zzQ)=91a&qtQqT1Q488	Uq(-8
1a"1Q41qtQqT::/000<<]<<<<<<r3   c                 P   t          |           dk    rt          }n*t          |           dk    rt          }nt          d          g }t	          | |          D ]M} |g | |R  }t          g ||R  }t          g ||R  }|                    t          |||                     N|S )a  Finds intersections between a curve and a line.

    Args:
        curve: List of coordinates of the curve segment as 2D tuples.
        line: List of coordinates of the line segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
        >>> line  = [ (25, 260), (230, 20) ]
        >>> intersections = curveLineIntersections(curve, line)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (84.9000930760723, 189.87306176459828)
    r5   r
  r  r
   )	r   r!   r"   r  r>  r  r$   r   r	   )r:  r;  pointFinderr=  rw   r   line_ts          r2   r'   r'     s    * 5zzQ'	Uq#/000M(55 C C[#%#### ))b)))(4((((\RA&AAABBBBr3   c                     t          |           dk    r	t          |  S t          |           dk    r	t          |  S t          d          )Nr5   r
  r  )r   r   r   r  )r   s    r2   _curve_boundsrC    sE    
1vv{{"A&&	Q1""
+
,
,,r3   c                    t          |           dk    r| \  }}t          |||          }||f||fgS t          |           dk    rt          g | |R  S t          |           dk    rt          g | |R  S t	          d          r	  )r   r$   r   r   r  )r   rw   r  r  midpoints        r2   _split_segment_at_trF    s    
1vv{{11a((H!}--
1vv{{ '!'Q''''	Q1#a#####
+
,
,,r3   MbP?c           	         t          |           }t          |          }|sd}|sd}t          ||          \  }}|sg S d }	t          |          k     r*t          |          k     r |	|           |	|          fgS t          | d          \  }
}|d          |	|          f} |	|          |d         f}t          |d          \  }}|d          |	|          f} |	|          |d         f}g }|                    t          |
|||                     |                    t          ||||                     |                    t          |
|||                     |                    t          ||||                     fd}t                      }g }|D ]<} ||          }||v r|                    |           |                    |           =|S )N)rl   rK   c                 *    d| d         | d         z   z  S )Nr6   r   rY   r7   )rs    r2   rE  z._curve_curve_intersections_t.<locals>.midpoint1  s    adQqTk""r3   r6   r   rY   )range1range2c                 d    t          | d         z            t          | d         z            fS )Nr   rY   )int)r   	precisions    r2   <lambda>z._curve_curve_intersections_t.<locals>.<lambda>V  s.    SA!233SA9J5K5KL r3   )	rC  r   r   rF  extend_curve_curve_intersections_tsetaddr   )curve1curve2rO  rK  rL  bounds1bounds2
intersects_rE  c11c12	c11_range	c12_rangec21c22	c21_range	c22_rangefound
unique_keyseenunique_valuesr   keys     `                     r2   rR  rR  !  s    F##GF##G   Wg..MJ 	# # # 9$$'):):Y)F)F&!!88F#3#3455"63//HCHHV,,-I&!!6!9-I"63//HCHHV,,-I&!!6!9-IE	LL$i	)	
 	
 	
  
 
LL$i	)	
 	
 	
  
 
LL$i	)	
 	
 	
  
 
LL$i	)	
 	
 	
   MLLLJ55DM ! !jnn$;;R    r3   c                 x    t          |                               |           }t          d |D                       S )Nc              3   L   K   | ]}t          j        |d          d          V   dS )rY   rl   N)rZ   r  )rv   ps     r2   r   z_is_linelike.<locals>.<genexpr>f  s2      ::1t|AaD#&&::::::r3   )r5  r9  all)r1  	maybelines     r2   _is_linelikerm  d  s:    )'22BB7KKI::	::::::r3   c                 V    t                     rM d          d         f}t          |          r|d         |d         f}t          g ||R  S t          ||          S t          |          r |d         |d         f}t           |          S t           |          } fd|D             S )a  Finds intersections between a curve and a curve.

    Args:
        curve1: List of coordinates of the first curve segment as 2D tuples.
        curve2: List of coordinates of the second curve segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
        >>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
        >>> intersections = curveCurveIntersections(curve1, curve2)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (81.7831487395506, 109.88904552375288)
    r   r   c           	      t    g | ]4}t          t          |d                    |d          |d                   5S )r   rY   r
   )r	   r%   )rv   r   rU  s     r2   r~   z+curveCurveIntersections.<locals>.<listcomp>  sN        	1662a5RUKKK  r3   )rm  r&   r'   rR  )rU  rV  line1line2intersection_tss   `    r2   r(   r(   i  s    * F 	5q	6":% 	91Ivbz)E(8%8%8888)&%888	f		 5q	6":%%fe444266BBO   !   r3   c                    d}t          |          t          |           k    r| |} }d}t          |           dk    r5t          |          dk    rt          | |          }nUt          | |          }nDt          |           dk    r"t          |          dk    rt          g | |R  }nt	          d          |s|S d |D             S )a)  Finds intersections between two segments.

    Args:
        seg1: List of coordinates of the first segment as 2D tuples.
        seg2: List of coordinates of the second segment as 2D tuples.

    Returns:
        A list of ``Intersection`` objects, each object having ``pt``, ``t1``
        and ``t2`` attributes containing the intersection point, time on first
        segment and time on second segment respectively.

    Examples::
        >>> curve1 = [ (10,100), (90,30), (40,140), (220,220) ]
        >>> curve2 = [ (5,150), (180,20), (80,250), (210,190) ]
        >>> intersections = segmentSegmentIntersections(curve1, curve2)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (81.7831487395506, 109.88904552375288)
        >>> curve3 = [ (100, 240), (30, 60), (210, 230), (160, 30) ]
        >>> line  = [ (25, 260), (230, 20) ]
        >>> intersections = segmentSegmentIntersections(curve3, line)
        >>> len(intersections)
        3
        >>> intersections[0].pt
        (84.9000930760723, 189.87306176459828)

    FTrX   z4Couldn't work out which intersection function to usec                 P    g | ]#}t          |j        |j        |j                   $S )r
   )r	   r   r   r   r8  s     r2   r~   z/segmentSegmentIntersections.<locals>.<listcomp>  s-    KKKLADQTad333KKKr3   )r   r(   r'   r&   r  )seg1seg2swappedr=  s       r2   r)   r)     s    < G
4yy3t994d
4yy1}}t99q==3D$??MM24>>MM	TaCIINN-;t;d;;;OPPP KK]KKKKr3   c                     	 t          |           }dd                    d |D                       z  S # t          $ r d| z  cY S w xY w)zw
    >>> _segmentrepr([1, [2, 3], [], [[2, [3, 4], [0.1, 2.2]]]])
    '(1, (2, 3), (), ((2, (3, 4), (0.1, 2.2))))'
    z(%s)z, c              3   4   K   | ]}t          |          V  d S rQ   )_segmentrepr)rv   rV   s     r2   r   z_segmentrepr.<locals>.<genexpr>  s(      !>!>a,q//!>!>!>!>!>!>r3   z%g)iterjoin	TypeError)objits     r2   rz  rz    sg    
?#YY 		!>!>2!>!>!>>>>>    czs   3 AAc                 H    | D ]}t          t          |                     dS )zlHelper for the doctests, displaying each segment in a list of
    segments on a single line as a tuple.
    N)printrz  )r   r1  s     r2   printSegmentsr    s6      % %l7##$$$$% %r3   __main__)r*   )rG  NN)X__doc__fontTools.misc.arrayToolsr   r   r   fontTools.misc.transformr   rZ   collectionsr   r   AttributeErrorImportErrorfontTools.misccompiledCOMPILEDrE   r	   __all__r   r>   returnsdoublelocalsr,   rF   r   r   rm   cfuncinlinerT   r]   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r[   r   r   r   r   r    r   r   r   r   r   r   r$   r!   r"   r#   r%   r  r  r&   r5  r>  r'   rC  rF  rR  rm  r(   r)   rz  r  __name__sysdoctestexittestmodfailedr7   r3   r2   <module>r     sa
    E D D D D D D D D D - - - - - -  " " " " " "&MMMM$ & & &%%%%%%%%& ?  z.*<*<*<==  @   &   ~~~~	   FM6=III	
 	
 JI  	
 	   m	  A A A	   A 
 &.V^444& & 54   & ; ;     ; P  P  PF ~~nn   
-]mm}}      &@W W W"   
 }}}  
    B  D  < 	   }}}}}  !" !"   !"H# # #L6 6 6r*3 *3 *3Z"2 "2 "2J, , ,0  > nnnn	 	 	0 0	 	0 m^			 	 	 }6=  D D 	 	  D4  6     F nnnn}}
-MM~~~~  # # #6 % $ $ $ $ $ $ $ $ $ $ $ "&    BY Y YB( ( (2 2 2 nnn      
( 
( 
(2 2 2  nnnn~~~      
N 
N 
N    4 m   &-fmFMJJJY Y KJ   Y - - -% % %/ / /K K K\C C C
= 
= 
=# # #L- - -	- 	- 	- 9=@ @ @ @F; ; ;
$ $ $N-L -L -L`
? 
? 
?% % % zJJJNNNCH_W_%&&&&&	 s   # 33