U
    #vh                     @   s  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	 zddl
Z
W n$ eefk
rh   ddlm
Z
 Y nX e
jZdZe	dd	d
dgZddddddddddddddddddddd d!d"d#d$d%d&d'gZdd)dZd*d+ Ze
e
je
je
je
je
je
jd,e
je
je
je
jd-d.d/ Ze
e
je
je
je
je
je
jd0e
je
je
jd1dd2dZd3Zd4Ze
je
je
e
je
je
je
jd5d6d7 Ze
je
je
e
je
je
jd8d9d: Z d;d Z!e
e
je
je
je
je
je
je
je
je
jd<e
je
je
je
je
je
je
je
jd=d>d Z"d?d Z#e
e
je
je
je
je
jd@e
je
je
je
jdAdBd Z$dCd Z%dDd Z&e
e
je
je
je
je
je
jd0e
je
je
je
je
je
jdEdFd Z'dGd Z(dHd Z)dId Z*dJd Z+dKd Z,dLd Z-e
je
je
je
je
je
je
je
je
jdMdNd Z.e
e
je
je
je
je
je
je
je
je
je
jdOe
je
je
je
je
jdPdQd Z/dRdS Z0dTdU Z1e
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dVdWdX Z2ddYlm3Z3m4Z4m5Z5m6Z6 e3fdZdZ7d[d Z8d\d] Z9d^d_ Z:e
je
je
je
je
je
je
je
je
je
jd`dadb Z;dcdd Z<dedf Z=e
je
je
je
je
je
je
je
je
je
jdgdhdi Z>djd" Z?dkd Z@dld  ZAe
e
je
je
je
je
je
je
jdme
je
je
je
jdndod! ZBdpd# ZCdqdr ZDdsdt ZEdud$ ZFdvdw ZGdxdy ZHdzd% ZId{d| ZJd}d~ ZKdddZLdd ZMdd& ZNdd' ZOdd ZPdd ZQeRdkrddlSZSddlTZTeSUeTV jW dS )zNfontTools.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                 C   s    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	tolerance r/   >/tmp/pip-unpacked-wheel-1ufboor8/fontTools/misc/bezierTools.pyr   8   s        c                 C   s\   | d||   | d }|| | |  d }| | | d || |f||| || d |ffS )N   g      ?      ?r/   )p0p1p2p3ZmidZderiv3r/   r/   r0   _split_cubic_into_twoK   s
    r7   )r3   r4   r5   r6   )multarchboxc           	      C   s~   t || }t || t ||  t ||  }||  t |krL|| d S t||||\}}t| f| t| f|  S d S Nr2   )absEPSILONr7   _calcCubicArcLengthCRecurse)	r8   r3   r4   r5   r6   r9   r:   ZoneZtwor/   r/   r0   r>   T   s    	$r>   r*   r+   r,   r-   )r.   r8   c                 C   s   dd|  }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      ?)r>   )r*   r+   r,   r-   r.   r8   r/   r/   r0   r   h   s       g|=v1v2c                 C   s   | |   jS N)	conjugaterealrB   r/   r/   r0   _dot   s    rH   xc                 C   s(   | t | d d  d t | d  S )N      )mathsqrtasinhrI   r/   r/   r0   _intSecAtan   s    rP   c                 C   s   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,   r/   r/   r0   r      s     )r*   r+   r,   d0d1dn)scaleorigDistabx0x1Lenc                 C   s   ||  }|| }|| }|d }t |}|dkr<t ||  S t||}t |tk rt||dkrlt ||  S t |t | }	}
|	|	 |
|
  |	|
  S t||| }t||| }t dt|t|  | |||   }|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   rK   )r<   rH   epsilonrP   )r*   r+   r,   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r/   r/   r0   r      s"     
(c                 C   s   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)   rQ   r/   r/   r0   r      s    rQ   )v0rC   rD   c                 C   sT   t d|  d|  d|  }t ||  d }t d|  d|  d|  }|| | 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?r<   )r*   r+   r,   r_   rC   rD   r/   r/   r0   r      s    !c                    s   t | ||\\ \\ d }d }g }|dkrJ| |  |dkrb| |   fdd|D | |g }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                    sT   g | ]L}d |  krdk rn q | | |   | | |   fqS r   rL   r/   .0taxaybxbycxcyr/   r0   
<listcomp>D  s
    
 z'calcQuadraticBounds.<locals>.<listcomp>)calcQuadraticParametersappendr   )r*   r+   r,   Zax2Zay2rootspointsr/   rf   r0   r   *  s    c                 C   s   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)   r?   r/   r/   r0   r   L  s       )r_   rC   rD   v3v4c           	      C   s   t ||  d }t d|  d|  d|  d|  }t ||  | | d }t d|  d|  d|  d|  }t || d }|| | | | 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?r`   )	r*   r+   r,   r-   r_   rC   rD   rr   rs   r/   r/   r0   r   j  s,    c                    s   t | |||\\ \\\ d }d }d }d }dd t||D }dd t||D }	||	 }
 fdd|
D | |g }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
          @ra   c                 S   s(   g | ] }d |  krdk rn q|qS rb   r/   rc   r/   r/   r0   rm     s
      
  z#calcCubicBounds.<locals>.<listcomp>c                 S   s(   g | ] }d |  krdk rn q|qS rb   r/   rc   r/   r/   r0   rm     s
      
  c                    s\   g | ]T} | | | | |  |   | | | | |  |   fqS r/   r/   rc   rg   rh   ri   rj   rk   rl   dxdyr/   r0   rm     s   &&)calcCubicParametersr   r   )r*   r+   r,   r-   Zax3Zay3Zbx2Zby2ZxRootsZyRootsrp   rq   r/   ru   r0   r     s    &c                 C   s   | \}}|\}}|| }|| }	|}
|}||	f| }|dkrF| |fgS ||
|f|  | }d|  krndk rn n(|| |
 |	| | f}| |f||fgS | |fgS d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   rL   Nr/   )r*   r+   whereisHorizontalZpt1xZpt1yZpt2xZpt2yrg   rh   ri   rj   rX   re   ZmidPtr/   r/   r0   r     s    $
c           	      C   sb   t | ||\}}}t|| || || | }tdd |D }|sP| ||fgS t|||f| 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                 s   s*   | ]"}d |  krdk rn q|V  qdS r   rL   Nr/   rc   r/   r/   r0   	<genexpr>"  s
      
  z!splitQuadratic.<locals>.<genexpr>)rn   r   sorted_splitQuadraticAtT)	r*   r+   r,   ry   rz   rX   rY   c	solutionsr/   r/   r0   r     s    #  
c                 C   sp   t | |||\}}}}	t|| || || |	| | }
tdd |
D }
|
s\| |||fgS t||||	f|
 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                 s   s*   | ]"}d |  krdk rn q|V  qdS r{   r/   rc   r/   r/   r0   r|   G  s
      
  zsplitCubic.<locals>.<genexpr>)rx   r   r}   _splitCubicAtT)r*   r+   r,   r-   ry   rz   rX   rY   r   rT   r   r/   r/   r0   r   (  s       
c                 G   s$   t | ||\}}}t|||f| 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))
    )rn   r~   )r*   r+   r,   tsrX   rY   r   r/   r/   r0   r   M  s    c           
      G   sb   t | |||\}}}}t||||f| }	| f|	d dd |	d< |	d dd |f|	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   rL   N)rx   r   )
r*   r+   r,   r-   r   rX   rY   r   rT   splitr/   r/   r0   r   e  s
    )r*   r+   r,   r-   rX   rY   r   rT   c           	      g   s4   t | |||\}}}}t||||f| E dH  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,   r-   r   rX   rY   r   rT   r/   r/   r0   r     s    )re   r*   r+   r,   r-   pointAtToff1off2)r   _1_t_1_t_2_2_t_1_tc                 C   s   || }d| }|| }d| | }|| |  d|| | || |    || |  }	||  ||  ||  }
|| ||  ||  }| ||  |  }||| |  }| ||
|	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).
    rL   rK   r1   r/   )r*   r+   r,   r-   re   r   r   r   r   r   r   r   r/   r/   r0   r     s    2c                 G   s  t |}g }|dd |d | \}}|\}}|\}	}
tt|d D ]}|| }||d  }|| }|| }|| }|| }d| | | | }d| | | | }|| }|| ||  |	 }|| ||  |
 }t||f||f||f\}}}||||f qJ|S )Nr   r]   r@   rL   rK   )listinsertro   rangelencalcQuadraticPoints)rX   rY   r   r   segmentsrg   rh   ri   rj   rk   rl   ir
   r   deltadelta_2a1xa1yb1xb1yt1_2c1xc1yr*   r+   r,   r/   r/   r0   r~     s,    
r~   c           "      G   s  t |}|dd |d g }| \}}|\}}	|\}
}|\}}tt|d D ](}|| }||d  }|| }|| }|| }|| }|| }|| }|| }d| | | | }d| | |	 | }d| | |
 d| |  | }d|	 | | d| |  | }|| ||  |
|  | }|| |	|  ||  | }t||f||f||f||f\}}} }!|||| |!f qR|S Nr   r]   r@   rL   r1   rK   )r   r   ro   r   r   calcCubicPoints)"rX   rY   r   rT   r   r   rg   rh   ri   rj   rk   rl   rv   rw   r   r
   r   r   r   delta_3r   t1_3r   r   r   r   r   r   Zd1xZd1yr*   r+   r,   r-   r/   r/   r0   r     s@    
     r   )rX   rY   r   rT   r
   r   r   r   r   a1b1c1rS   c                 g   s   t |}|dd |d tt|d D ]}|| }||d  }|| }|| }	||	 }
|| }|| }| |
 }d|  | | |	 }d| | | d|  |  | }| | ||  ||  | }t||||\}}}}||||fV  q.d S r   )r   r   ro   r   r   calcCubicPointsC)rX   rY   r   rT   r   r   r
   r   r   r   r   r   r   r   r   r   rS   r*   r+   r,   r-   r/   r/   r0   r     s"    
 r   )rN   acoscospic                 C   s~   t | tk r,t |tk rg }qz| | g}nN|| d|  |  }|dkrv||}| | d |  | | d |  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!
          @r]   ra   r<   r^   )rX   rY   r   rN   rp   ZDDZrDDr/   r/   r0   r   /  s    &c                 C   s  t | tk rt|||S t| } ||  }||  }||  }|| d|  d }d| | | d| |  d|  d }|| }	|| | }
|	tk rdn|	}	t |
tk rdn|
}
|	|
 }|	dkr|
dkrt| d t}|||gS |td kr@ttt|t	|
 d	d
}dt	| }|d }|t
|d  | }|t
|dt  d  | }|t
|dt  d  | }t|||g\}}}|| tk r|| tk rt|| | d t } }}n~|| tk rt|| d t }}t|t}nN|| tk rt|t}t|| d t }}nt|t}t|t}t|t}|||gS tt	|t | d}|||  }|dkrr| }t||d  t}|gS d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
    rt   g      "@ra   g      ;@g      K@r   r]   r2   r@   g      g       r   UUUUUU?N)r<   r^   r   floatroundepsilonDigitsr   maxminrN   r   r   r}   pow)rX   rY   r   rT   r   Za2a3QRZR2ZQ3ZR2_Q3rJ   thetaZrQ2Za1_3rZ   r[   x2r/   r/   r0   r   P  sT    &(
 





c                 C   s^   |\}}|\}}| \}}|| d }	|| d }
|| |	 }|| |
 }||f|	|
f||ffS )Nra   r/   )r*   r+   r,   r   y2x3y3rk   rl   ri   rj   rg   rh   r/   r/   r0   rn     s    rn   c                 C   s   |\}}|\}}|\}}	| \}
}||
 d }|| d }|| d | }|| d | }||
 | | }|	| | | }||f||f||f|
|ffS Nrt   r/   )r*   r+   r,   r-   r   r   r   r   x4y4rv   rw   rk   rl   ri   rj   rg   rh   r/   r/   r0   rx     s    rx   )r*   r+   r,   r-   rX   rY   r   c                 C   s8   ||  d }|| d | }||  | | }|||| fS r   r/   )r*   r+   r,   r-   r   rY   rX   r/   r/   r0   r     s    r   c                 C   sf   | \}}|\}}|\}}|}	|}
|d | }|d | }|| | }|| | }|	|
f||f||ffS r;   r/   )rX   rY   r   rg   rh   ri   rj   rk   rl   r[   y1r   r   r   r   r/   r/   r0   r     s    r   c                 C   s   | \}}|\}}|\}}	|\}
}|
}|}|d |
 }|	d | }|| d | }||	 d | }||
 | | }|| |	 | }||f||f||f||ffS r   r/   )rX   rY   r   rT   rg   rh   ri   rj   rk   rl   rv   rw   r[   r   r   r   r   r   r   r   r/   r/   r0   r     s    r   rX   rY   r   rT   r5   r6   Zp4c                 C   s8   |d | }|| d | }| | | | }||||fS )Nr   r/   r   r/   r/   r0   r     s    r   c                 C   s8   | d d|  |d |  | d d|  |d |  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   rL   r/   )r*   r+   re   r/   r/   r0   r"     s    
c                 C   s   d| d|  | d  dd|  | |d   || |d   }d| d|  | d  dd|  | |d   || |d   }||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.
    rL   r   rK   r/   )r*   r+   r,   re   rJ   yr/   r/   r0   r     s    
@@c           
      C   s   || }d| }|| }|| | d  d|| |d  || |d     || |d   }|| | d  d|| |d  || |d     || |d   }	||	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.
    rL   r   r1   r/   )
r*   r+   r,   r-   re   r   r   r   rJ   r   r/   r/   r0   r    ,  s     
"")re   r*   r+   r,   r-   )r   r   r   c                 C   sL   || }d| }|| }|| |  d|| | || |    || |  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.
    rL   r1   r/   )r*   r+   r,   r-   re   r   r   r   r/   r/   r0   r!   F  s    c                 C   sZ   t | dkrt| |f S t | dkr4t| |f S t | dkrNt| |f S tdd S NrK   r1      Unknown curve degree)r   r"   r   r    
ValueError)segre   r/   r/   r0   r#   _  s    c           	      C   sx   | \}}|\}}|\}}t || tk r<t || tk r<dS t || t || krd|| ||  S || ||  S d S )Nr   r   )	ser	   ZsxZsyexZeyZpxpyr/   r/   r0   _line_t_of_ptn  s     r   c                 C   sR   | d |d  |d |d   }| d |d  |d |d   }|dkoN|dk S )Nr   rL   r]   r/   )rX   rY   originZxDiffZyDiffr/   r/   r0   '_both_points_are_on_same_side_of_origin|  s      r   c                 C   s  | \}}|\}}|\}}	|\}
}t ||
rHt ||rHt ||sHg S t |	|rpt ||rpt ||	spg S t ||
rt |	|rg S t ||rt ||rg S t ||r|}||	 |
|  }|||  |	 }||f}t|t| ||t|||dgS t ||
r\|}|| ||  }|||  | }||f}t|t| ||t|||dgS || ||  }||	 |
|  }t ||rg S || | ||  |	 ||  }|||  | }||f}t||| rt|||rt|t| ||t|||d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	   r
   r   )rM   iscloser   r   r   )s1e1s2e2Zs1xZs1yZe1xZe1yZs2xZs2yZe2xZe2yrJ   Zslope34r   r	   Zslope12r/   r/   r0   r$     s    





 
 
 
 
   
 
 
c                 C   sT   | d }| d }t |d |d  |d |d  }t| |d  |d  S )Nr   r   rL   )rM   atan2r   rotate	translate)segmentstartendZangler/   r/   r0   _alignment_transformation  s    $r   c                 C   s   t || }t| dkrBt| \}}}t|d |d |d }nDt| dkr~t| \}}}}t|d |d |d |d }ntdtdd |D S )Nr1   rL   r   r   c                 s   s*   | ]"}d |  krdkrn q|V  qdS )r]   rL   Nr/   rd   r   r/   r/   r0   r|     s
      
  z._curve_line_intersections_t.<locals>.<genexpr>)	r   transformPointsr   rn   r   rx   r   r   r}   )curvelineZaligned_curverX   rY   r   intersectionsrT   r/   r/   r0   _curve_line_intersections_t  s     r   c                 C   s   t | dkrt}nt | dkr$t}ntdg }t| |D ]B}|| |f }t||f }t||f }|t|||d q:|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)
    r1   r   r   r   )	r   r   r    r   r   r   r"   ro   r   )r   r   ZpointFinderr   re   r	   Zline_tr/   r/   r0   r%     s    c                 C   s4   t | dkrt|  S t | dkr(t|  S tdd S )Nr1   r   r   )r   r   r   r   )r   r/   r/   r0   _curve_bounds  s
    r   c                 C   sp   t | dkr0| \}}t|||}||f||fgS t | dkrJt| |f S t | dkrdt| |f S tdd S r   )r   r"   r   r   r   )r   re   r   r   midpointr/   r/   r0   _split_segment_at_t  s    r   MbP?c              	      sx  t | }t |}|sd}|s d}t||\}}|s6g S dd }	t| k rht| k rh|	||	|fgS t| d\}
}|d |	|f}|	||d f}t|d\}}|d |	|f}|	||d f}g }|t|
| ||d |t|| ||d |t|
| ||d |t|| ||d  fdd	}t }g }|D ]0}||}||kr\qB|| || qB|S )
N)r]   r@   c                 S   s   d| d | d   S )Nr2   r   rL   r/   )rr/   r/   r0   r   1  s    z._curve_curve_intersections_t.<locals>.midpointr2   r   rL   )range1range2c                    s    t | d   t | d   fS )Nr   rL   )int)r   	precisionr/   r0   <lambda>V      z._curve_curve_intersections_t.<locals>.<lambda>)	r   r   r   r   extend_curve_curve_intersections_tsetaddro   )curve1curve2r   r   r   Zbounds1Zbounds2Z
intersects_r   Zc11Zc12Z	c11_rangeZ	c12_rangeZc21Zc22Z	c21_rangeZ	c22_rangefoundZ
unique_keyseenZunique_valuesr   keyr/   r   r0   r   !  s                    

r   c                 C   s    t | | }tdd |D S )Nc                 s   s   | ]}t |d  dV  qdS )rL   r]   N)rM   r   )rd   pr/   r/   r0   r|   f  s     z_is_linelike.<locals>.<genexpr>)r   r   all)r   Z	maybeliner/   r/   r0   _is_lineliked  s    r   c                    s   t  rH d  d f}t |r<|d |d f}t|| S t||S n"t |rj|d |d f}t |S t |} fd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                    s,   g | ]$}t t |d  |d  |d dqS )r   rL   r   )r   r#   )rd   r   r   r/   r0   rm     s   z+curveCurveIntersections.<locals>.<listcomp>)r   r$   r%   r   )r   r   Zline1Zline2Zintersection_tsr/   r   r0   r&   i  s    


c                 C   s   d}t |t | kr"| | }} d}t | dkrRt |dkrFt| |}qt| |}n.t | dkrxt |dkrxt| | }ntd|s|S d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)

    FTrK   z4Couldn't work out which intersection function to usec                 S   s    g | ]}t |j|j|jd qS )r   )r   r	   r   r
   r   r/   r/   r0   rm     s     z/segmentSegmentIntersections.<locals>.<listcomp>)r   r&   r%   r$   r   )Zseg1Zseg2Zswappedr   r/   r/   r0   r'     s    
c                 C   sF   zt | }W n tk
r(   d|   Y S X dddd |D  S dS )zw
    >>> _segmentrepr([1, [2, 3], [], [[2, [3, 4], [0.1, 2.2]]]])
    '(1, (2, 3), (), ((2, (3, 4), (0.1, 2.2))))'
    z%gz(%s)z, c                 s   s   | ]}t |V  qd S rE   )_segmentrepr)rd   rJ   r/   r/   r0   r|     s     z_segmentrepr.<locals>.<genexpr>N)iter	TypeErrorjoin)objitr/   r/   r0   r     s
    r   c                 C   s   | D ]}t t| qdS )zlHelper for the doctests, displaying each segment in a list of
    segments on a single line as a tuple.
    N)printr   )r   r   r/   r/   r0   printSegments  s    r   __main__)r(   )r(   )r   NN)X__doc__ZfontTools.misc.arrayToolsr   r   r   ZfontTools.misc.transformr   rM   collectionsr   r   AttributeErrorImportErrorZfontTools.miscZcompiledZCOMPILEDr=   r   __all__r   r7   Zreturnsdoublelocalsr)   r>   r   r   r^   ZcfuncinlinerH   rP   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r~   r   r   rN   r   r   r   r   r   rn   rx   r   r   r   r   r"   r   r    r!   r#   r   r   r$   r   r   r%   r   r   r   r   r&   r'   r   r   __name__sysdoctestexittestmodfailedr/   r/   r/   r0   <module>   s   
	



#
		 
!"
$&9-%



   #
!a		
N
&     
C'0
