U
    »mœdø-  ã                   @   sÚ   d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZmZ d	d
gZdZdZe e¡ZeZdd„ ZG dd„ deƒZdd„ Zdd„ Zd!dd„Zd"dd„Zd#dd„Zd$dd	„Zdd„ Zd d
„ Z dS )%a—  Converts cubic bezier curves to quadratic splines.

Conversion is performed such that the quadratic splines keep the same end-curve
tangents as the original cubics. The approach is iterative, increasing the
number of segments for a spline until the error gets below a bound.

Respective curves from multiple fonts will be converted at once to ensure that
the resulting splines are interpolation-compatible.
é    N)ÚAbstractPen)ÚPointToSegmentPen)ÚReverseContourPené   )Úcurves_to_quadratic)ÚUnequalZipLengthsErrorÚIncompatibleSegmentNumberErrorÚIncompatibleSegmentTypesErrorÚIncompatibleGlyphsErrorÚIncompatibleFontsErrorÚfonts_to_quadraticÚfont_to_quadraticgü©ñÒMbP?z&com.github.googlei18n.cu2qu.curve_typec                  G   s.   t tdd„ | D ƒƒƒdkr"t| Ž ‚tt| Ž ƒS )zyEnsure each argument to zip has the same length. Also make sure a list is
    returned for python 2/3 compatibility.
    c                 s   s   | ]}t |ƒV  qd S ©N©Úlen)Ú.0Úa© r   úL/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/fontTools/cu2qu/ufo.pyÚ	<genexpr><   s     zzip.<locals>.<genexpr>r   )r   Úsetr   ÚlistÚ_zip)Úargsr   r   r   Úzip7   s    r   c                   @   sX   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚGetSegmentsPenz®Pen to collect segments into lists of points for conversion.

    Curves always include their initial on-curve point, so some points are
    duplicated between segments.
    c                 C   s   d | _ g | _d S r   )Ú_last_ptÚsegments©Úselfr   r   r   Ú__init__H   s    zGetSegmentsPen.__init__c                 G   s&   |dkr|d | _ | j ||f¡ d S )N)ÚmoveÚlineÚqcurveÚcurveéÿÿÿÿ)r   r   Úappend)r   Útagr   r   r   r   Ú_add_segmentL   s    
zGetSegmentsPen._add_segmentc                 C   s   |   d|¡ d S )Nr!   ©r(   ©r   Úptr   r   r   ÚmoveToQ   s    zGetSegmentsPen.moveToc                 C   s   |   d|¡ d S )Nr"   r)   r*   r   r   r   ÚlineToT   s    zGetSegmentsPen.lineToc                 G   s   | j d| jf|žŽ  d S )Nr#   ©r(   r   ©r   Zpointsr   r   r   ÚqCurveToW   s    zGetSegmentsPen.qCurveToc                 G   s   | j d| jf|žŽ  d S )Nr$   r.   r/   r   r   r   ÚcurveToZ   s    zGetSegmentsPen.curveToc                 C   s   |   d¡ d S )NÚcloser)   r   r   r   r   Ú	closePath]   s    zGetSegmentsPen.closePathc                 C   s   |   d¡ d S )NÚendr)   r   r   r   r   ÚendPath`   s    zGetSegmentsPen.endPathc                 C   s   d S r   r   )r   Z	glyphNameZtransformationr   r   r   ÚaddComponentc   s    zGetSegmentsPen.addComponentN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r    r(   r,   r-   r0   r1   r3   r5   r6   r   r   r   r   r   A   s   r   c                 C   s"   t ƒ }t|dd�}|  |¡ |jS )z6Get a glyph's segments as extracted by GetSegmentsPen.T)ZoutputImpliedClosingLine)r   r   Z
drawPointsr   )ÚglyphÚpenZpointPenr   r   r   Ú_get_segmentsg   s    
r=   c                 C   s¾   |   ¡  |  ¡ }|rt|ƒ}|D ]˜\}}|dkr<|j|Ž  q |dkrP|j|Ž  q |dkrl|j|dd… Ž  q |dkrˆ|j|dd… Ž  q |dkrš| ¡  q |dkr¬| ¡  q t	d	| ƒ‚q dS )
z=Draw segments as extracted by GetSegmentsPen back to a glyph.r!   r"   r$   r   Nr#   r2   r4   zUnhandled segment type "%s")
ZclearContoursZgetPenr   r,   r-   r1   r0   r3   r5   ÚAssertionError)r;   r   Úreverse_directionr<   r'   r   r   r   r   Ú_set_segmentsz   s$    

r@   Tc                    s®   t dd„ | D ƒƒstdƒ‚tdd„ | D ƒ||ƒ}t|d ƒ‰ t ‡ fdd„|dd	… D ƒƒsbtd
ƒ‚tˆ d ƒ}| |d¡d ||< |sŽˆ dkrœdd„ |D ƒS dd„ |D ƒS d	S )z2Return quadratic approximations of cubic segments.c                 s   s   | ]}|d  dkV  qdS )r   r$   Nr   ©r   Úsr   r   r   r   •   s     z)_segments_to_quadratic.<locals>.<genexpr>zNon-cubic given to convertc                 S   s   g | ]}|d  ‘qS )r   r   rA   r   r   r   Ú
<listcomp>—   s     z*_segments_to_quadratic.<locals>.<listcomp>r   c                 3   s   | ]}t |ƒˆ kV  qd S r   r   rA   ©Únr   r   r   ™   s     r   NzConverted incompatiblyé   é   c                 S   s   g | ]}d |f‘qS )r#   r   ©r   Úpr   r   r   rC   Ÿ   s     c                 S   s   g | ]}d |f‘qS )r$   r   rH   r   r   r   rC   ¡   s     )Úallr>   r   r   ÚstrÚget)r   Úmax_errÚstatsÚall_quadraticZ
new_pointsZspline_lengthr   rD   r   Ú_segments_to_quadratic’   s    &rP   c                    s  zt dd„ | D ƒŽ }W n tk
r2   t| ƒ‚Y nX t|ƒs@dS |}g }i }t|ƒD ]z\}	}
|
d d ‰ t‡ fdd„|
dd… D ƒƒsšd	d„ |
D ƒ||	< n*ˆ d
krÄt|
|||ƒ}|s¼||
krÀd}|}
| |
¡ qT|rüt |Ž }t | |ƒD ]\}}t|||ƒ qæ|�rt	| |d�‚|S )z£Do the actual conversion of a set of compatible glyphs, after arguments
    have been set up.

    Return True if the glyphs were modified, else return False.
    c                 S   s   g | ]}t |ƒ‘qS r   )r=   )r   Úgr   r   r   rC   ¬   s     z(_glyphs_to_quadratic.<locals>.<listcomp>Fr   c                 3   s   | ]}|d  ˆ kV  qdS )r   Nr   rA   ©r'   r   r   r   ¹   s     z'_glyphs_to_quadratic.<locals>.<genexpr>r   Nc                 S   s   g | ]}|d  ‘qS )r   r   rA   r   r   r   rC   º   s     r$   T)r   )
r   r   r   ÚanyÚ	enumeraterJ   rP   r&   r@   r	   )ÚglyphsrM   r?   rN   rO   Zsegments_by_locationZglyphs_modifiedZnew_segments_by_locationZincompatibleÚir   Únew_segmentsZnew_segments_by_glyphr;   r   rR   r   Ú_glyphs_to_quadratic¤   s>       ÿrX   Fc                 C   s^   |dkri }|st d }t|ttfƒr,|}n|gt| ƒ }t|ƒt| ƒksNt‚t| ||||ƒS )a²  Convert the curves of a set of compatible of glyphs to quadratic.

    All curves will be converted to quadratic at once, ensuring interpolation
    compatibility. If this is not required, calling glyphs_to_quadratic with one
    glyph at a time may yield slightly more optimized results.

    Return True if glyphs were modified, else return False.

    Raises IncompatibleGlyphsError if glyphs have non-interpolatable outlines.
    Niè  )ÚDEFAULT_MAX_ERRÚ
isinstancer   Útupler   r>   rX   )rU   rM   r?   rN   rO   Ú
max_errorsr   r   r   Úglyphs_to_quadraticÎ   s        ÿr]   c                    sf  |rjdd„ | D ƒ}t |ƒdkrTtt|ƒƒ}	|	dkr@t d¡ dS |	dkrJqjt|	ƒ‚nt |ƒdkrjt d¡ ˆd	krvi ‰ˆ r†|r†td
ƒ‚ˆ s’|s’t‰ t	|t
tfƒrºt |ƒt | ƒks´t‚|}
n|rÌ|gt | ƒ }
t	ˆ t
tfƒ�rt | ƒt ˆ ƒksðt‚dd„ t| ˆ ƒD ƒ}
nˆ �r‡ fdd„| D ƒ}
d}i }tƒ jdd„ | D ƒŽ D ]–}g }g }t| |
ƒD ],\}}||k�rR| || ¡ | |¡ �qRz|t|||ˆ|ƒO }W n6 tk
�rÎ } zt |¡ |||< W 5 d	}~X Y nX �q<|�rât|ƒ‚|�r|�rtˆ ¡ ƒ}t dd ‡fdd„|D ƒ¡ ¡ |�rb| D ]:}|j td¡}	|�rBdnd}|	|k�r&||jt< d}�q&|S )aï  Convert the curves of a collection of fonts to quadratic.

    All curves will be converted to quadratic at once, ensuring interpolation
    compatibility. If this is not required, calling fonts_to_quadratic with one
    font at a time may yield slightly more optimized results.

    Return True if fonts were modified, else return False.

    By default, cu2qu stores the curve type in the fonts' lib, under a private
    key "com.github.googlei18n.cu2qu.curve_type", and will not try to convert
    them again if the curve type is already set to "quadratic".
    Setting 'remember_curve_type' to False disables this optimization.

    Raises IncompatibleFontsError if same-named glyphs from different fonts
    have non-interpolatable outlines.
    c                 S   s   h | ]}|j  td ¡’qS )Úcubic)ÚlibrL   ÚCURVE_TYPE_LIB_KEY©r   Úfr   r   r   Ú	<setcomp>	  s     z%fonts_to_quadratic.<locals>.<setcomp>r   )Ú	quadraticÚmixedz%Curves already converted to quadraticFr^   z'fonts may contain different curve typesNz4Only one of max_err and max_err_em can be specified.c                 S   s   g | ]\}}|j j| ‘qS r   ©ÚinfoZ
unitsPerEm)r   rb   Úer   r   r   rC   '  s     z&fonts_to_quadratic.<locals>.<listcomp>c                    s   g | ]}|j jˆ  ‘qS r   rf   ra   )Ú
max_err_emr   r   rC   )  s     c                 s   s   | ]}|  ¡ V  qd S r   )Úkeysra   r   r   r   r   -  s     z%fonts_to_quadratic.<locals>.<genexpr>zNew spline lengths: %sz, c                 3   s   | ]}d |ˆ | f V  qdS )z%s: %dNr   )r   Úl)rN   r   r   r   C  s     rd   re   T)r   ÚnextÚiterÚloggerrg   ÚNotImplementedErrorÚwarningÚ	TypeErrorrY   rZ   r   r[   r>   r   r   Úunionr&   rX   r
   Úerrorr   Úsortedrj   Újoinr_   rL   r`   )Zfontsri   rM   r?   rN   Z
dump_statsZremember_curve_typerO   Zcurve_typesZ
curve_typer\   ÚmodifiedZglyph_errorsÚnamerU   Zcur_max_errorsÚfontrs   ÚexcZspline_lengthsZnew_curve_typer   )ri   rN   r   r   í   s‚    



    ÿ

ÿÿ

c                 K   s   t | gf|ŽS )z†Convenience wrapper around glyphs_to_quadratic, for just one glyph.
    Return True if the glyph was modified, else return False.
    )r]   )r;   Úkwargsr   r   r   Úglyph_to_quadraticP  s    r{   c                 K   s   t | gf|ŽS )zƒConvenience wrapper around fonts_to_quadratic, for just one font.
    Return True if the font was modified, else return False.
    )r   )rx   rz   r   r   r   r   X  s    )T)T)NFNT)NNFNFTT)!r:   ÚloggingZfontTools.pens.basePenr   ZfontTools.pens.pointPenr   Z fontTools.pens.reverseContourPenr   Ú r   Úerrorsr   r   r	   r
   r   Ú__all__rY   r`   Ú	getLoggerr7   rn   r   r   r   r=   r@   rP   rX   r]   r   r{   r   r   r   r   r   Ú<module>   s@   
	

&

+       ÿ
!       ø
c