o
    teU/                     @   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_quadraticgMbP?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   CD:\Projects\ConvertPro\env\Lib\site-packages\fontTools/cu2qu/ufo.py	<genexpr><       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 )GetSegmentsPenzPen 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v 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      |  d| d S )Nr"   r)   r    ptr   r   r   moveToQ      zGetSegmentsPen.moveToc                 C   r*   )Nr#   r+   r,   r   r   r   lineToT   r/   zGetSegmentsPen.lineToc                 G      | j d| jg|R   d S )Nr$   r)   r   r    Zpointsr   r   r   qCurveToW      zGetSegmentsPen.qCurveToc                 G   r1   )Nr%   r2   r3   r   r   r   curveToZ   r5   zGetSegmentsPen.curveToc                 C      |  d d S )Ncloser+   r   r   r   r   	closePath]      zGetSegmentsPen.closePathc                 C   r7   )Nendr+   r   r   r   r   endPath`   r:   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.   r0   r4   r6   r9   r<   r=   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   
rD   c                 C   s   |    |  }|rt|}|D ]K\}}|dkr|j|  q|dkr(|j|  q|dkr6|j|dd   q|dkrD|j|dd   q|dkrM|  q|dkrV|  qt	d	| dS )
z=Draw segments as extracted by GetSegmentsPen back to a glyph.r"   r#   r%   r   Nr$   r8   r;   zUnhandled segment type "%s")
ZclearContoursZgetPenr   r.   r0   r6   r4   r9   r<   AssertionError)rB   r   reverse_directionrC   r(   r   r   r   r   _set_segmentsz   s&   

rG   Tc                    s   t dd | D sJ dtdd | D ||}t|d  t  fdd|dd	 D s1J d
t d }||dd ||< |sG dkrNdd |D S dd |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          z)_segments_to_quadratic.<locals>.<genexpr>zNon-cubic given to convertc                 S      g | ]}|d  qS )r   r   rH   r   r   r   
<listcomp>       z*_segments_to_quadratic.<locals>.<listcomp>r   c                 3   s    | ]	}t | kV  qd S r   r   rH   nr   r   r      rJ   r   NzConverted incompatibly      c                 S      g | ]}d |fqS )r$   r   r   pr   r   r   rL      rM   c                 S   rR   )r%   r   rS   r   r   r   rL      rM   )allr   r   strget)r   max_errstatsall_quadraticZ
new_pointsZspline_lengthr   rN   r   _segments_to_quadratic   s   &r[   c                    s
  zt dd | D  }W n ty   t| w t|sdS |}g }i }t|D ]=\}	}
|
d d  t fdd|
dd D sJd	d |
D ||	< n d
kr_t|
|||}|s[||
kr]d}|}
||
 q'|r{t | }t | |D ]
\}}t||| qp|rt	| |d|S )zDo 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   )rD   )r   gr   r   r   rL      rM   z(_glyphs_to_quadratic.<locals>.<listcomp>Fr   c                 3   s    | ]	}|d   kV  qdS )r   Nr   rH   r(   r   r   r      rJ   z'_glyphs_to_quadratic.<locals>.<genexpr>r   Nc                 S   rK   )r   r   rH   r   r   r   rL      rM   r%   T)r   )
r   r   r   any	enumeraterU   r[   r'   rG   r	   )glyphsrX   rF   rY   rZ   Zsegments_by_locationZglyphs_modifiedZnew_segments_by_locationZincompatibleir   new_segmentsZnew_segments_by_glyphrB   r   r]   r   _glyphs_to_quadratic   s:   rc   Fc                 C   s^   |du ri }|st d }t|ttfr|}n|gt|  }t|t| ks'J 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   rc   )r`   rX   rF   rY   rZ   
max_errorsr   r   r   glyphs_to_quadratic   s   
rh   c                    sV  |r4dd | D }t |dkr)tt|}	|	dv r td dS |	dkr%nt|	t |dkr4td d	u r:i  rB|rBtd
 sH|sHt t	|t
tfr\t |t | ksYJ |}
n	|re|gt |  }
t	 t
tfrt | t  ksvJ dd t|  D }
n r fdd| D }
d}i }t jdd | D  D ]G}g }g }t| |
D ]\}}||v r|||  || qz|t||||O }W q ty } zt| |||< W Y d	}~qd	}~ww |rt||r|rt }tddfdd|D   |r)| D ]}|jtd}	|rd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)librW   CURVE_TYPE_LIB_KEYr   fr   r   r   	<setcomp>	  s    z%fonts_to_quadratic.<locals>.<setcomp>r   )	quadraticmixedz%Curves already converted to quadraticFri   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   rm   er   r   r   rL   '  s    z&fonts_to_quadratic.<locals>.<listcomp>c                    s   g | ]}|j j  qS r   rq   rl   )
max_err_emr   r   rL   )  s    c                 s   s    | ]}|  V  qd S r   )keysrl   r   r   r   r   -  r   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)rY   r   r   r   C  s    ro   rp   T)r   nextiterloggerrr   NotImplementedErrorwarning	TypeErrorrd   re   r   rf   r   r   unionr'   rc   r
   errorr   sortedru   joinrj   rW   rk   )Zfontsrt   rX   rF   rY   Z
dump_statsZremember_curve_typerZ   Zcurve_typesZ
curve_typerg   modifiedZglyph_errorsnamer`   Zcur_max_errorsfontr~   excZspline_lengthsZnew_curve_typer   )rt   rY   r   r      s   







c                 K      t | gfi |S )zConvenience wrapper around glyphs_to_quadratic, for just one glyph.
    Return True if the glyph was modified, else return False.
    )rh   )rB   kwargsr   r   r   glyph_to_quadraticP     r   c                 K   r   )zConvenience wrapper around fonts_to_quadratic, for just one font.
    Return True if the font was modified, else return False.
    )r   )r   r   r   r   r   r   X  r   )T)NFNT)NNFNFTT)!rA   loggingZfontTools.pens.basePenr   ZfontTools.pens.pointPenr   Z fontTools.pens.reverseContourPenr    r   errorsr   r   r	   r
   r   __all__rd   rk   	getLoggerr>   ry   r   r   r   rD   rG   r[   rc   rh   r   r   r   r   r   r   r   <module>   s<   
	

&

+
!
c