
    BPc9                        d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
 ddlmZ ddlmZ dd	lmZmZmZ dd
lmZmZmZmZ ddlmZmZ ddlmZ ddlmZ 	 ddlm Z m!Z!  e!d          Z" e!de#e$          Z%n# e&$ r Y nw xY wde%de%de$fdZ'd Z( G d dej)                  Z* G d de*          Z+ G d de*          Z, G d de*          Z- G d de-          Z. G d  d!e*          Z/ G d" d#e/          Z0 G d$ d%e/          Z1 G d& d'e*          Z2 G d( d)e2          Z3 G d* d+e2          Z4 G d, d-e*          Z5 G d. d/e*          Z6 G d0 d1e6          Z7 G d2 d3e6          Z8dS )4zModule for interpolating attributes and styles

.. versionchanged:: 1.2
    Rewritten in inkex 1.2 in an object-oriented structure to support more attributes.
    )bisect_leftN   )Style)LinearGradientRadialGradientStop)	Transform)Color)convert_unit
parse_unitrender_unit)bezlenapprxcspbezsplitcspbezsplitatlength	csplength)PathCubicSuperPath)SvgDocumentElement)FragmentError)TupleTypeVarValueNumbercoord_acoord_btimec                 H    t          | |                              |          S )z3Interpolate single coordinate by the amount of time)ValueInterpolatorinterpolate)r   r   r   s      -/usr/share/inkscape/extensions/inkex/tween.pyinterpcoordr!   1   s     Wg..::4@@@    c                 H    t          | |                              |          S )z/Interpolate coordinate points by amount of time)ArrayInterpolatorr   )point1point2r   s      r    interppointsr'   6   s"     VV,,88>>>r"   c                   h    e Zd ZdZd Zed             Zedd            Zej	        d	d            Z
dS )
AttributeInterpolatorzInterpolate between attributesc                 "    || _         || _        d S Nstart_value	end_value)selfr-   r.   s      r    __init__zAttributeInterpolator.__init__?   s    &"r"   c                 Z    	 |                                  S # t          $ r
 | j        cY S w xY w)aw  Gets the best possible approximation to a node's style. For nodes inside the
        element tree of an SVG file, stylesheets defined in the defs of that file can be
        taken into account. This should be the case for input elements, but is not
        required - in that case, only the local inline style is used.

        During the interpolation process, some nodes are created temporarily, such as
        plain gradients of a single color to allow solid<->gradient interpolation. These
        are not attached to the document tree and therefore have no root. Since the only
        style relevant for them is the inline style, it is acceptable to fallback to it.

        Args:
            node (BaseElement): The node to get the best approximated style of

        Returns:
            Style: If the node is rooted, the CSS specified style. Else, the inline
            style.)specified_styler   style)nodes    r    
best_stylez AttributeInterpolator.best_styleC   sB    $	''))) 	 	 	:	s    **Nc                    |t           j        v rt                              | ||          S |dk    r|t          } || j        |j                  S |dk    rt          | |          S |                    d          r$t                              | ||dd                   S |dk    rt          | j	        |j	                  S |2 || 
                    |          |
                    |                    S t          d          )a  Creates an interpolator for an attribute. Currently, only path, transform and
        style attributes are supported

        Args:
            snode (BaseElement): start element
            enode (BaseElement): end element
            attribute (str): attribute name (for styles, starting with "style/")
            method (AttributeInterpolator, optional): (currently only used for paths).
                Specifies a method used to interpolate the attribute. Defaults to None.

        Raises:
            ValueError: if an attribute is passed that is not a style, path or transform
                attribute

        Returns:
            AttributeInterpolator: an interpolator whose type depends on attribute.
        dNr3   zstyle/   	transformz,only path and style attributes are supported)r   color_propsStyleInterpolatorcreate_from_fill_strokeFirstNodesInterpolatorpath
startswithcreateTransformInterpolatorr9   get
ValueError)snodeenode	attributemethods       r    create_from_attributez+AttributeInterpolator.create_from_attributeZ   s   & )))$<<UE9UUU~/6%*ej111$UE222)) 	I$++E5)ABB-HHH##(%/JJJ6%))I..		)0D0DEEEGHHHr"   r   c                     dS )z;Interpolation method, needs to be implemented by subclassesN r/   r   s     r    r   z!AttributeInterpolator.interpolate}   s	     	r"   r+   r   )__name__
__module____qualname____doc__r0   staticmethodr5   rH   abcabstractmethodr   rJ   r"   r    r)   r)   <   s        ((# # #   \,  I  I  I \ ID 	     r"   r)   c                   V     e Zd ZdZ fdZed             Zed             ZddZ xZ	S )r;   zClass to interpolate stylesc           
      r   t                                          ||           i | _        t          t                              g dt          |                     |                                                    z   t          |                     |                                                    z                       }|D ]v}|                     |          }|                     |          }||vr||vr5	 t          	                    | j
        | j        |          }|| j        |<   g# t          $ r Y sw xY wd S )N)fillstrokezfill-opacityzstroke-opacitystroke-width)superr0   interpolatorslistdictfromkeysr5   keysr;   r@   r-   r.   rC   )	r/   r-   r.   all_keysattrsstyleestyleinterp	__class__s	           r    r0   zStyleInterpolator.__init__   sM   i000 MMTTTt{3388::;;<ty11668899: 
 
  	 	D__[11F__Y//F6!!d&&8&8*11$dnd  ,2"4((   	 	s   60D''
D43D4c                    |t           j        v rt                              | ||          S |t           j        v rPt          t                              |           |          t                              |          |                    S |t           j        v rPt          t                              |           |          t                              |          |                    S t          d          )a  Creates an Interpolator for a given style attribute, depending on its type:

            - Color properties (such as fill, stroke) -> :class:`ColorInterpolator`,
              :class:`GradientInterpolator` ect.
            - Unit properties -> :class:`UnitValueInterpolator`
            - other properties -> :class:`ValueInterpolator`

        Args:
            snode (BaseElement): start element
            enode (BaseElement): end element
            attribute (str): attribute to interpolate

        Raises:
            ValueError: if the attribute is not in any of the lists

        Returns:
            AttributeInterpolator: an interpolator object whose type depends on the
            attribute.
        zUnknown attribute)r   r:   r;   r<   
unit_propsUnitValueInterpolatorr)   r5   opacity_propsr   rC   )rD   rE   rF   s      r    r@   zStyleInterpolator.create   s    * )))$<<UE9UUU((((%0077	BB%0077	BB  
 +++$%0077	BB%0077	BB  
 ,---r"   c                    |t           j        vrt          d          t                              |           }t                              |          }| |g||gg}|D ]-\  }} ||          d|j        |dz   <   |dk    r
d|j        d<   .t           ||          t          t          f          s%t           ||          t          t          f          rE	 t          
                    | ||          S # t          $ r t           ||                    cY S w xY w ||           ||          t          d          S t          
                    |||          S )a  Creates an Interpolator for a given color-like attribute

        Args:
            snode (BaseElement): start element
            enode (BaseElement): end element
            attribute (str): attribute to interpolate

        Raises:
            ValueError: if the attribute is not color-like
            ValueError: if the attribute is unset on both start and end style

        Returns:
            AttributeInterpolator: an interpolator object whose type depends on the
            attribute.
        z"attribute must be a color propertyN        -opacityrW   rX   none)r   r:   rC   r)   r5   r3   
isinstancer   r   GradientInterpolatorr@   TrivialInterpolatorColorInterpolator)rD   rE   rF   ra   rb   stylescurcurstyles           r    r<   z)StyleInterpolator.create_from_fill_stroke   s   " E---ABBB&11%88&11%88&/E6?3% 	4 	4OS(x	""*47	)j01((03CIn- F9?
 
 	>y))NN+KLL	>>+225%KKK > > >*66)+<+<=====> 6)$	):):)B&v... ''	BBBs   C1 1"DDr   c                     t                      }| j                                        D ]\  }}|                    |          ||<   |S )a1  Interpolates a style using the interpolators set in self.interpolators

        Args:
            time (int, optional): Interpolation position. If 0, start_value is returned,
                if 1, end_value is returned. Defaults to 0.

        Returns:
            inkex.Style: interpolated style
        )r   rZ   itemsr   )r/   r   r3   proprc   s        r    r   zStyleInterpolator.interpolate   sM      .4466 	3 	3LD& ,,T22E$KKr"   rL   )
rM   rN   rO   rP   r0   rQ   r@   r<   r   __classcell__rd   s   @r    r;   r;      s        %%    4 #. #. \#.J )C )C \)CV       r"   r;   c                   *     e Zd ZdZ fdZddZ xZS )ro   z2Trivial interpolator, returns value for every timec                 L    t                                          ||           d S r+   rY   r0   )r/   valuerd   s     r    r0   zTrivialInterpolator.__init__  s#    &&&&&r"   r   c                     | j         S r+   )r-   rK   s     r    r   zTrivialInterpolator.interpolate  s    r"   rL   rM   rN   rO   rP   r0   r   rw   rx   s   @r    ro   ro     sR        <<' ' ' ' '               r"   ro   c                   ,     e Zd ZdZd fd	ZddZ xZS )r   z)Class for interpolation of a single valuer   c                     t                                          t          |          t          |                     d S r+   )rY   r0   floatr/   r-   r.   rd   s      r    r0   zValueInterpolator.__init__  s3    {++U9-=-=>>>>>r"   c                 6    | j         | j        | j         z
  |z  z   S )a  (Linearly) interpolates a value

        Args:
            time (int, optional): Interpolation position. If 0, start_value is returned,
                if 1, end_value is returned. Defaults to 0.

        Returns:
            int: interpolated value
        r,   rK   s     r    r   zValueInterpolator.interpolate  s!     DNT5E$E#MNNr"   r   r   rL   r~   rx   s   @r    r   r     s_        33? ? ? ? ? ?
O 
O 
O 
O 
O 
O 
O 
Or"   r   c                   0     e Zd ZdZd fd	Zd fd	Z xZS )rg   z,Class for interpolation of a value with unitr   c                     t          |          \  }}t          ||          }t                                          ||           || _        d S r+   )r   r   rY   r0   unit)r/   r-   r.   	start_val
start_unitend_valrd   s         r    r0   zUnitValueInterpolator.__init__"  sI     *; 7 7	:y*55G,,,			r"   c                 l    t          t                                          |          | j                  S r+   )r   rY   r   r   r/   r   rd   s     r    r   z!UnitValueInterpolator.interpolate(  s'    577..t44di@@@r"   r   rL   r~   rx   s   @r    rg   rg     sk        66     A A A A A A A A A Ar"   rg   c                   *     e Zd ZdZ fdZddZ xZS )r$   zSInterpolates array-like objects element-wise, e.g. color, transform,
    coordinatec                     t                                          ||           d t          ||          D             | _        d S )Nc                 4    g | ]\  }}t          ||          S rJ   )r   ).0rr   others      r    
<listcomp>z.ArrayInterpolator.__init__.<locals>.<listcomp>2  s6     
 
 
e c5))
 
 
r"   )rY   r0   ziprZ   r   s      r    r0   zArrayInterpolator.__init__0  sN    i000
 
 #K ; ;
 
 
r"   r   c                 *    fd| j         D             S )zInterpolates an array element-wise

        Args:
            time (int, optional): [description]. Defaults to 0.

        Returns:
            List: interpolated array
        c                 :    g | ]}|                               S rJ   r   r   rc   r   s     r    r   z1ArrayInterpolator.interpolate.<locals>.<listcomp>@  s'    JJJV""4((JJJr"   )rZ   rK   s    `r    r   zArrayInterpolator.interpolate7  s#     KJJJt7IJJJJr"   rL   r~   rx   s   @r    r$   r$   ,  s^         
 
 
 
 
	K 	K 	K 	K 	K 	K 	K 	Kr"   r$   c                   T     e Zd ZdZ e             e            f fd	Zd fd	Z xZS )rA   z%Class for interpolation of transformsc                     t                                          |                                |                                           dS )a  Creates a transform interpolator.

        Args:
            start_value (inkex.Transform, optional): start transform. Defaults to
                inkex.Transform().
            end_value (inkex.Transform, optional): end transform. Defaults to
                inkex.Transform().
        N)rY   r0   to_hexadr   s      r    r0   zTransformInterpolator.__init__F  s=     	--//1C1C1E1EFFFFFr"   r   c                 `    t          t                                          |                    S )aK  Interpolates a transform by interpolating each item in the transform hexad
        separately.

        Args:
            time (int, optional): Interpolation position. If 0, start_value is returned,
                if 1, end_value is returned. Defaults to 0.

        Returns:
            Transform: interpolated transform
        )r	   rY   r   r   s     r    r   z!TransformInterpolator.interpolateQ  s%     ,,T22333r"   rL   )rM   rN   rO   rP   r	   r0   r   rw   rx   s   @r    rA   rA   C  sx        //#,9;;))++ 	G 	G 	G 	G 	G 	G4 4 4 4 4 4 4 4 4 4r"   rA   c                   n     e Zd ZdZed             Z ed           ed          f fd	Zd fd	Z xZ	S )rp   zClass for color interpolationc                 t   | |g}t          |t          |                    D ]<\  }}t           ||          t                    r ||           ||          ||<   =t	          t           |d         |                    t           |d         |                              }|t          d          |S )a  Creates a ColorInterpolator for either Fill or stroke, depending on the
        attribute.

        Args:
            sst (Style): Start style
            est (Style): End style
            attribute (string): either fill or stroke

        Raises:
            ValueError: if none of the start or end style is a color.

        Returns:
            ColorInterpolator: A ColorInterpolator object
        Nr   r   z2One of the two attribute needs to be a plain color)r   reversedrm   r
   rp   rC   )sstestrF   rq   rr   r   thiss          r    r@   zColorInterpolator.createb  s      sfhv&6&677 	2 	2JCcc)nne44 2I8N!&y!1!1I )&)I&&''yvay/C/C)D)D
 
 <QRRRr"   z#000000c                 L    t                                          ||           d S r+   r{   r   s      r    r0   zColorInterpolator.__init__}  s#    i00000r"   r   c           
          t          t          t          t          t	                                          |                                        S )a.  Interpolates a color by interpolating its r, g, b, a channels separately.

        Args:
            time (int, optional): Interpolation position. If 0, start_value is returned,
                if 1, end_value is returned. Defaults to 0.

        Returns:
            Color: interpolated color
        )r
   r[   mapintrY   r   r   s     r    r   zColorInterpolator.interpolate  s7     T#c577#6#6t#<#<==>>???r"   rL   )
rM   rN   rO   rP   rQ   r@   r
   r0   r   rw   rx   s   @r    rp   rp   _  s        ''  \4 $)5#3#3uuY?O?O 1 1 1 1 1 1
@ 
@ 
@ 
@ 
@ 
@ 
@ 
@ 
@ 
@r"   rp   c                   n     e Zd ZdZd	 fd	Zed             Zed             Zed             Zd
dZ	 xZ
S )rn   z%Base class for Gradient InterpolationNc                 "    t                                          ||           | _        || _        || _        t           j        j         j        j                   _         fd j        j        D              _	         j        j
         j        j
         j        j
        u st          t          t           j        j         j        j        z                                 }d }t                               j        j        t           j        j                  ||          }t                               j        j        t           j        j                  ||          }d t%          ||          D              _        d S d  _        d S )Nc           	          i | ]w}j                             |          [j                            |          6|t          j                             |          j                            |                    xS r+   )r-   rB   r.   rg   )r   r`   r/   s     r    
<dictcomp>z1GradientInterpolator.__init__.<locals>.<dictcomp>  s     )
 )
 )
 ##D))5""4((4 ' $$T**DN,>,>t,D,D 
 544r"   c                 H    t          | |                              |          S r+   )StopInterpolatorr   )startendr   s      r    funcz+GradientInterpolator.__init__.<locals>.func  s     's33??EEEr"   c                 4    g | ]\  }}t          ||          S rJ   )r   )r   s1s2s      r    r   z1GradientInterpolator.__init__.<locals>.<listcomp>  s4     ) ) )-3R R(() ) )r"   )rY   r0   svgr-   r.   rA   gradientTransformtransform_interpolatororientation_attributesorientation_interpolatorhrefsortedr[   setstop_offsetsrn   interpolate_linear_liststopsr   newstop_interpolator)	r/   r-   r.   r   
newoffsetsr   sstopsostopsrd   s	   `       r    r0   zGradientInterpolator.__init__  s   i000(D(DN&;.0P'
 '
#)
 )
 )
 )
 (?	)
 )
 )
% !- %)<<<  S)69TTUUVV JF F F *AA -T%+,,	 F *AA+T^)**	 F) )7:667J7J) ) )D%%% )-D%%%r"   c                 x   d}d}t                               |           }t                               |          }||fD ]}d}t           ||          t          t          f          r ||          }t          t
          gt          t          gfD ]2\  }	}
|+t          ||	          r||
}|	}|
|k    st          d          3|  |            |g| |            | gg}dD ]s}t                               ||         d                   } ||          }|5d||         d         j        |dz   <   |dk    rd||         d         j        d<   t          |t                    r|
                    ||         d	         ||         d                                                    t                      }t                      |_        ||j        d
<   d|_        ||         d	                             |           t                      }t                      |_        ||j        d
<   d	|_        ||         d	                             |           h|||         d	<   u|t          d          |t
          t          fv r% ||d         d	         |d	         d	         |           S  ||d         d	         |d	         d	                   S )a  Creates a `GradientInterpolator` for either fill or stroke, depending on
        attribute.

        Cases: (A, B) -> Interpolator

          - Linear Gradient, Linear Gradient -> LinearGradientInterpolator
          - Color or None, Linear Gradient -> LinearGradientInterpolator
          - Radial Gradient, Radial Gradient -> RadialGradientInterpolator
          - Color or None, Radial Gradient -> RadialGradientInterpolator
          - Radial Gradient, Linear Gradient -> ValueError
          - Color or None, Color or None -> ValueError

        Args:
            snode (BaseElement): start element
            enode (BaseElement): end element
            attribute (string): either fill or stroke

        Raises:
            ValueError: if none of the styles are a gradient or if they are gradients
                of different types

        Returns:
            GradientInterpolator: an Interpolator object
        NzGradient types don't match)r   r   r   rj   rk   rW   rX   r   z
stop-colorz$None of the two styles is a gradient)r)   r5   rm   r   r   LinearGradientInterpolatorRadialGradientInterpolatorrC   r3   r
   initialize_positionbounding_boxr   r   offsetadd)rD   rE   rF   interpolatorgradienttypera   rb   rr   curgradgradtyperc   iteratorindexrs   r|   stops                   r    r@   zGradientInterpolator.create  s   4 &11%88&11%88F# 	G 	GCG##i..>>*JKK )#i..!;<!;<% 	G 	G & &:gx+H+H&#+'-'/"l22()EFFF	G LLNNE2ULLNNE4RS 	+ 	+E,778JKKHHY''E} DG"(Z)?@((?BHUOA&,^<%'' + 00UOA&(:(G(G(I(I   vv"WW
+0
<("&&t,,,vv"WW
+0
<("&&t,,,,%*""CDDD68RSSS<AAFFF|HQKNHQKN;;;r"   c                     g }t          t          t          |                     } t          t          t          |                    }|D ]}t          |           dk    r|                    |d                    1t          dt          | |          dz
            }t          t          |           dz
  |dz             }|| |         z
  | |         | |         z
  z  }||         }	||         }
 ||	|
|          }|                    |           |S )aX  Interpolates a list of values given at n positions to the best approximation
        at m newpositions.

        >>>
            |
            |         x
            |  x
            _________________
               pq  q  p   q
            (x denotes function values, p: positions, q: newpositions)
            A function may be given to interpolate between given values.

        Args:
            positions (list[number-like]): position of current function values
            values (list[Type]): list of arbitrary type,
                ``len(values) == len(positions)``
            newpositions (list[number-like]): position of interpolated values
            func (Callable[[Type, Type, float], Type]): Function to interpolate between
                values

        Returns:
            list[Type]: interpolated function values at positions
        r   r   )r[   r   r   lenappendmaxr   min)	positionsvaluesnewpositionsr   	newvaluesposidxlidxrfractionvallvalrnewvals               r    r   z,GradientInterpolator.interpolate_linear_list  s   2 	UI..//	C|4455 	) 	)C9~~""  ++++ 1k)S99A=>>3y>>A-tax88)D/1io	RV6WXd|d|dD(33  ((((r"   c                    |                                 \  }}| )|                                 t          | t                    s|S | j        j                            |           t          |          dk    rK| j        j                            ||           |                    dd|	                                            |S )a  Splits a gradient into stops and orientation, appends it to the document's
        defs and returns the href to the orientation gradient.

        Args:
            element (BaseElement): an element inside the SVG that the gradient should be
                added to
            gradient (Gradient): the gradient to append to the document

        Returns:
            Gradient: the orientation gradient, or the gradient object if
            element has no root or is None
        Nr   z
xlink:href#)
stops_and_orientation	getparentrm   r   rootdefsr   r   r   get_id)elementgradientr   orientations       r    append_to_docz"GradientInterpolator.append_to_docB  s     &;;=={?'
7DV0W0W'Ok***u::>>L!!%555OOL*>ellnn*>*>???r"   r   c                    | j                                         }| j                                      |_        | j                                        D ]6}|                    || j        |                                                  7| j        5|	                    t                      |j        fd| j        D               | j        |S t                              | j        |          S )z"Interpolate with another gradient.Nc                 :    g | ]}|                               S rJ   r   r   s     r    r   z4GradientInterpolator.interpolate.<locals>.<listcomp>i  s'    SSSv&$$T**SSSr"   )r-   copyr   r   r   r   r^   r   r   
remove_allr   r   r   rn   r   )r/   r   newgradr`   s    `  r    r   z GradientInterpolator.interpolate[  s    "''))$($?$K$KD$Q$Q! 16688 	U 	UDKKd;DAMMdSSTTTT $0t$$$GKSSSS9RSSS  8N#11$(GDDDr"   r+   rL   )rM   rN   rO   rP   r0   rQ   r@   r   r   r   rw   rx   s   @r    rn   rn     s        //0- 0- 0- 0- 0- 0-d P< P< \P<d * * \*X   \0E E E E E E E Er"   rn   c                   `     e Zd ZdZ e             e            df fd	Zed             Z xZS )r   z+Class for interpolation of linear gradientsNc                 N    t                                          |||           d S r+   r{   r/   r-   r.   r   rd   s       r    r0   z#LinearGradientInterpolator.__init__s  '     	i55555r"   c                     |                      d|j                   |                      d|j                   |                      d|j        j                   |                      d|j        j                   dS )z(Initializes a linear gradient's positionx1x2y1y2N)r   leftrightcentery)gradbboxs     r    r   z.LinearGradientInterpolator.initialize_positionx  sf     	ty!!!tz"""t{}%%%t{}%%%%%r"   )	rM   rN   rO   rP   r   r0   rQ   r   rw   rx   s   @r    r   r   p  sw        55 ).**nn6F6FD6 6 6 6 6 6
 & & \& & & & &r"   r   c                   `     e Zd ZdZ e             e            df fd	Zed             Z xZS )r   z%Class to interpolate radial gradientsNc                 N    t                                          |||           d S r+   r{   r   s       r    r0   z#RadialGradientInterpolator.__init__  r   r"   c                    |j         \  }}|                     d|           |                     d|           |                     d|           |                     d|           |                     d|j        |j         j        z
             dS )z(Initializes a radial gradient's positioncxcyfxfyrN)r   r   r   x)r   r   r  r   s       r    r   z.RadialGradientInterpolator.initialize_position  s     {1qqqqdj4;=011111r"   )	rM   rN   rO   rP   r   r0   rQ   r   rw   rx   s   @r    r   r     sw        // ).**nn6F6FD6 6 6 6 6 6
 2 2 \2 2 2 2 2r"   r   c                   *     e Zd ZdZ fdZddZ xZS )r   z#Class to interpolate gradient stopsc                     t                                          ||           t          ||          | _        t	          t          |j                  t          |j                            | _        d S r+   )rY   r0   r;   style_interpolatorr   r   r   position_interpolatorr   s      r    r0   zStopInterpolator.__init__  sb    i000"3K"K"K%6+$%%uY-='>'>&
 &
"""r"   r   c                     t                      }| j                            |          |_        | j                            |          |_        |S )a5  Interpolates a gradient stop by interpolating style and offset separately

        Args:
            time (int, optional): Interpolation position. If 0, start_value is returned,
                if 1, end_value is returned. Defaults to 0.

        Returns:
            Stop: interpolated gradient stop
        )r   r	  r   r3   r
  r   )r/   r   newstops      r    r   zStopInterpolator.interpolate  sB     &&/;;DAA3??EEr"   rL   r~   rx   s   @r    r   r     sR        --
 
 
 
 
       r"   r   c                   V     e Zd ZdZ e             e            f fd	Zd ZddZ xZS )PathInterpolatorz!Base class for Path interpolationc                     t                                          |                                |                                           d | _        d | _        d S r+   )rY   r0   to_superpathprocessed_end_pathprocessed_start_pathr   s      r    r0   zPathInterpolator.__init__  sK    1133Y5K5K5M5MNNN"&$(!!!r"   c                    g g}g g}| j         r5| j        r-| j         d         r| j        d         rt|d                             | j         d                             d                     |d                             | j        d                             d                     n| j        d         r|                    | j                             d                     |d                             | j        d         d                    |                    | j        d                             d          g           n| j         d         r|                    | j                            d                     |d                             | j         d         d                    |                    | j         d                             d          g           nZ|                    | j                             d                     |                    | j                            d                     | j         r| j        -|| _        || _        dS )zlTruncates the longer path so that all subpaths in both paths have an equal
        number of bezier commandsr   N)r-   r.   r   popr  r  )r/   ses      r    truncate_subpathsz"PathInterpolator.truncate_subpaths  s    DD 	04> 	0" 0t~a'8 0"T-a044Q77888"T^A.221556666 " 0)--a00111"T^A.q1222$.+//2234444!!$ 0++A..///"T-a03444$*1-11!4456666 )--a00111++A..///)  	04> 	0* %&!"#r"   r   c           	         g }t          | j        | j                  D ]\  }}|s|s n|                    g            t          ||          D ]\  }}|s|s nz|d                             g            t          ||          D ]M\  }}|s|s nC|d         d                             t	          ||                              |                     N|d         s|d= t          |          S )Nr  )r   r  r  r   r$   r   r   )	r/   r   rc   ssubpathesubpathsbezierebezierr%   r&   s	            r    r   zPathInterpolator.interpolate  s8   "%%t'>#
 #
 	 	Hh   MM"$'($;$;    7 Er
!!"%%%&)'7&;&;  NFF" f 2JrN)))&&99EEdKK    bz 	r
f%%%r"   rL   )	rM   rN   rO   rP   r   r0   r  r   rw   rx   s   @r    r  r    sw        ++#'466TTVV ) ) ) ) ) )
$ $ $<& & & & & & & &r"   r  c                   t     e Zd ZdZed             Zed             Z e             e            f fd	Z xZ	S )EqualSubsegmentsInterpolatorz;Interpolates the path by rediscretizing the subpaths first.c                     t          |           \  }}d}g }|D ]$}|D ]}|||z  z  }|                    |            %|                                 |||fS )z!prepare lengths for interpolationr   )r   r   sort)r>   
sp_lenghtstotaltlenghtsspls          r    get_subpath_lenghtsz0EqualSubsegmentsInterpolator.get_subpath_lenghts  s     &dOO
E 	" 	"B " "QYq!!!!" 	5'))r"   c                 B   t                               |           \  }}}t                               |          \  }}}d}g g}|D ]Y}| d         s(|                    |                     d                     |d                             | d                             d                     |D ]}	|}
||	|z  z  }|r||d         k    r|r|d         |k     r|d         |
z
  ||
z
  z  }t	          |d         d         dd         | d         d         dd         |          }|dd         |d         dd<   |d         | d         d<   |                    d          }
|r|d         |k     |d                             | d                             d                     [|S )aZ  Rediscretize path so that all subpaths have an equal number of segments,
        so that there is a node at the path "times" where path or other have a node

        Args:
            path (Path): the first path
            other (Path): the second path

        Returns:
            Array: the prepared path description for the intermediate pathr   r  N   )r  r(  r   r  r   )r>   r   r"  r#  _r%  r$  r  r&  r'  ptntbezess                r    process_pathz)EqualSubsegmentsInterpolator.process_path  s     <OOPTUU
E14HHOO1gD 	- 	-B7 &!%%%bELLaQ((( 
- 
-QY ,q71:~~! ,gaj1nn%aj2o!b&9 3AbE"IaaaL$q'!*QQQ-QS T T%*2A2Y"bcc
%*1XQ
$[[^^ " ,gaj1nn "T!W[[^^,,,,
- r"   c                 D   t                                          ||           t          j        | j                  }t
                              | j        | j                  | _        t
                              | j        |          | _        |                                  d S r+   )	rY   r0   r   deepcopyr-   r  r/  r.   r  )r/   
start_pathend_path
start_copyrd   s       r    r0   z%EqualSubsegmentsInterpolator.__init__#  s    X...]4#344
7DDdn
 
 6BBNJ
 
 	     r"   )
rM   rN   rO   rP   rQ   r(  r/  r   r0   rw   rx   s   @r    r  r    s        EE
* 
* \
*   \> #'$&&4466 ! ! ! ! ! ! ! ! ! !r"   r  c                   H     e Zd ZdZ e             e            f fd	Z xZS )r=   zJInterpolates a path by discarding the trailing nodes of the longer subpathc           	          t                                          ||           t          | j                  t          | j                  z
  }|dk    r| j        | j        c| _        | _        t          t          |                    D ]}d}d}d}t          | j                  D ]q\  }}t          dt          | j        |                             D ]C}	t          | j        |         |	dz
           | j        |         |	                   }
|
|k    r|
}|}|	}Dr| j        |         |dz
  |dz            \  }}t          ||          | j        |         |dz
  |dz   <   |dk    r| j        | j        c| _        | _        | 
                                 d S )Nr   r   )rY   r0   r   r-   r.   rangeabs	enumerater   r   r  )r/   r2  r3  
lengthdiffr+  maxlensubpathsegmentr   zlengsp1sp2rd   s                r    r0   zFirstNodesInterpolator.__init__5  s   X...)**S-@-@@
>>/3~t?O,Ddns:'' 	Y 	YAFGG!$"233 $ $1q#d&6q&9":":;; $ $A&(+AE2D4DQ4G4J D f}}!%"#"#$ '01w{1JKHCCNsTWCXCXDW%gkGaK&?@@>>/3~t?O,Ddn     r"   )rM   rN   rO   rP   r   r0   rw   rx   s   @r    r=   r=   2  sT        TT"&$&&4466 ! ! ! ! ! ! ! ! ! !r"   r=   )9rP   bisectr   rR   r   rq   r   elements._filtersr   r   r   
transformsr	   colorsr
   unitsr   r   r   bezierr   r   r   r   pathsr   r   elementsr   utilsr   typingr   r   r   r   r   r   ImportErrorr!   r'   ABCr)   r;   ro   r   rg   r$   rA   rp   rn   r   r   r   r  r  r=   rJ   r"   r    <module>rN     s  ( 
       



        C C C C C C C C C C ! ! ! ! ! !       8 8 8 8 8 8 8 8 8 8 L L L L L L L L L L L L ' ' ' ' ' ' ' ' ( ( ( ( ( (            	%%%%%%%%GGEWXsE**FF 	 	 	D	A A& A A A A A
? ? ?D D D D DCG D D DN| | | | |- | | |~         /      O O O O O- O O O&
A 
A 
A 
A 
A- 
A 
A 
AK K K K K- K K K.4 4 4 4 4- 4 4 48+@ +@ +@ +@ +@) +@ +@ +@\`E `E `E `E `E0 `E `E `EF& & & & &!5 & & &"2 2 2 2 2!5 2 2 2&    ,   4B& B& B& B& B&, B& B& B&J<! <! <! <! <!#3 <! <! <!~! ! ! ! !- ! ! ! ! !s    A9 9B B