
    jke-                         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j&                  e      ZeZd Z G d de      Zd Zd ZddZddZ	 ddZ	 	 	 	 	 	 	 ddZd Zd Z y)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                  p    t        t        d | D                    dk7  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              3   2   K   | ]  }t        |        y wNlen).0as     5/usr/lib/python3/dist-packages/fontTools/cu2qu/ufo.py	<genexpr>zzip.<locals>.<genexpr><   s     $!s1v$s   r   )r   setr   list_zip)argss    r   zipr   7   s6    
 3$t$$%*$d++d    c                   F    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zy)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                      d | _         g | _        y r   )_last_ptsegmentsselfs    r   __init__zGetSegmentsPen.__init__H   s    r   c                 Z    |dv r
|d   | _         | j                  j                  ||f       y )N)movelineqcurvecurve)r!   r"   append)r$   tagr   s      r   _add_segmentzGetSegmentsPen._add_segmentL   s,    55 HDMc4[)r   c                 (    | j                  d|       y )Nr'   r.   r$   pts     r   moveTozGetSegmentsPen.moveToQ       &"%r   c                 (    | j                  d|       y )Nr(   r0   r1   s     r   lineTozGetSegmentsPen.lineToT   r4   r   c                 @     | j                   d| j                  g|  y )Nr)   r.   r!   r$   pointss     r   qCurveTozGetSegmentsPen.qCurveToW   s    (DMM;F;r   c                 @     | j                   d| j                  g|  y )Nr*   r8   r9   s     r   curveTozGetSegmentsPen.curveToZ   s    '4==:6:r   c                 &    | j                  d       y )Ncloser0   r#   s    r   	closePathzGetSegmentsPen.closePath]   s    '"r   c                 &    | j                  d       y )Nendr0   r#   s    r   endPathzGetSegmentsPen.endPath`   s    % r   c                      y r    )r$   	glyphNametransformations      r   addComponentzGetSegmentsPen.addComponentc   s    r   N)__name__
__module____qualname____doc__r%   r.   r3   r6   r;   r=   r@   rC   rH   rE   r   r   r   r   A   s4    *
&&<;#!r   r   c                 j    t               }t        |d      }| j                  |       |j                  S )z6Get a glyph's segments as extracted by GetSegmentsPen.T)outputImpliedClosingLine)r   r   
drawPointsr"   )glyphpenpointPens      r   _get_segmentsrS   g   s2     
C !tDH	X<<r   c                    | j                          | j                         }|rt        |      }|D ]  \  }}|dk(  r |j                  |  |dk(  r |j                  |  0|dk(  r |j
                  |dd   H|dk(  r |j                  |dd   `|dk(  r|j                          v|dk(  r|j                          t        d	|z         y)
z=Draw segments as extracted by GetSegmentsPen back to a glyph.r'   r(   r*   r   Nr)   r?   rB   zUnhandled segment type "%s")
clearContoursgetPenr   r3   r6   r=   r;   r@   rC   AssertionError)rP   r"   reverse_directionrQ   r-   r   s         r   _set_segmentsrY   z   s     

,,.C$ F	T&=CJJF]CJJG^CKKab"H_CLL$qr(#G^MMOE\KKM !>!DEEFr   c                    t        d | D              sJ d       t        | D cg c]  }|d   	 c}||      }t        |d         t        fd|dd D              sJ d       t        dz
        }|j	                  |d      dz   ||<   |sd	k(  r|D cg c]  }d
|f c}S |D cg c]  }d|f c}S c c}w c c}w c c}w )z2Return quadratic approximations of cubic segments.c              3   ,   K   | ]  }|d    dk(    yw)r   r*   NrE   )r   ss     r   r   z)_segments_to_quadratic.<locals>.<genexpr>   s     11qtw1s   zNon-cubic given to convertr   r   c              3   :   K   | ]  }t        |      k(    y wr   r   )r   r\   ns     r   r   z)_segments_to_quadratic.<locals>.<genexpr>   s     3qs1v{3s   NzConverted incompatibly      r)   r*   )allr   r   strget)	r"   max_errstatsall_quadraticr\   
new_pointsspline_lengthpr^   s	           @r   _segments_to_quadraticrj      s     111O3OO1$H%=qad%=wVJJqMA3JqrN33M5MM3AJM 99]A6:E-Q'12!122&01!11 &> 31s   B6B;(C c                    	 t        | D cg c]  }t        |       c} }t	        |      sy|}g }i }	t        |      D ]j  \  }
}|d   d   t        fd|dd D              s|D cg c]  }|d   	 c}|	|
<   ndk(  rt        ||||      }|s||k7  rd}|}|j                  |       l |r)t        | }t        | |      D ]  \  }}t        |||        |	rt        | |	      |S c c}w # t        $ r t        |       w xY wc c}w )	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.
    Fr   c              3   .   K   | ]  }|d    k(    yw)r   NrE   )r   r\   r-   s     r   r   z'_glyphs_to_quadratic.<locals>.<genexpr>   s     511Q43;5s   r   Nr*   T)r"   )r   rS   r   r	   any	enumeratera   rj   r,   rY   r
   )glyphsrd   rX   re   rf   gsegments_by_locationglyphs_modifiednew_segments_by_locationincompatibleir"   r\   new_segmentsnew_segments_by_glyphrP   r-   s                   @r   _glyphs_to_quadraticrx      sK   5"v$F!]1%5$FG #$ (O!L !56 28qk!n555-56qt6LOG^1'5-L  8"&#H ''12  #%= >#&v/D#E 	BE<%/@A	B +F\JJ? %G! 5,V445 7s!   	C- C(C- (D(C- -Dc                     |i }|s	t         dz  }t        |t        t        f      r|}n|gt	        |       z  }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.
    i  )DEFAULT_MAX_ERR
isinstancer   tupler   rx   )ro   rd   rX   re   rf   
max_errorss         r   glyphs_to_quadraticr~      sm     }!D('D%=)
YV,
z?c&k)))
-um r   c           	         |r| D ch c]"  }|j                   j                  t        d      $ }	}t        |	      dk(  r?t	        t        |	            }
|
dv rt        j                  d       y|
dk(  rn.t        |
      t        |	      dkD  rt        j                  d       i |r|rt        d      |s|st        }t        |t        t        f      rt        |      t        |       k(  sJ |}n|r|gt        |       z  }t        |t        t        f      rOt        |       t        |      k(  sJ t        | |      D cg c]  \  }}|j                  j                   |z    }}}n(|r&| D cg c]  }|j                  j                   |z   }}d}i } t#               j$                  d	 | D         D ]W  }g }g }t        |       D ]/  \  }}||v s|j'                  ||          |j'                  |       1 	 |t)        ||||      z  }Y |rt/        |      |rK|rIt1        j3                               }t        j                  d
dj5                  fd|D              z         |rH| D ]C  }|j                   j                  t        d      }
|rdnd}|
|k7  s/||j                   t        <   d}E |S c c}w c c}}w c c}w # t*        $ r%}t        j-                  |       |||<   Y d}~9d}~ww xY w)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.
    cubicr   )	quadraticmixedz%Curves already converted to quadraticFz'fonts may contain different curve typesNz4Only one of max_err and max_err_em can be specified.c              3   <   K   | ]  }|j                           y wr   )keys)r   fs     r   r   z%fonts_to_quadratic.<locals>.<genexpr>-  s     61affh6s   zNew spline lengths: %sz, c              3   2   K   | ]  }d ||   fz    yw)z%s: %dNrE   )r   lre   s     r   r   z%fonts_to_quadratic.<locals>.<genexpr>C  s     JaQaM1Js   r   r   T)librc   CURVE_TYPE_LIB_KEYr   nextiterloggerinfoNotImplementedErrorwarning	TypeErrorrz   r{   r   r|   r   
unitsPerEmr   unionr,   rx   r   errorr   sortedr   join)fonts
max_err_emrd   rX   re   
dump_statsremember_curve_typerf   r   curve_types
curve_typer}   emodifiedglyph_errorsnamero   cur_max_errorsfontr   excspline_lengthsnew_curve_types       `                  r   r   r      s   6 GLM!quuyy!3W=MM{q d;/0J33CDw&)*55!NNDE}gNOO'$
'D%=)7|s5z)))
	YU+
*tUm,5zS_,,,8;E:8NO1aff''!+O
O	>CDaff''*4D
DHL667 %uj1 	-KD%t|d4j)%%e,	-	%,(95- H% $\22J

-$yyJ>JJL	

  	 D&8'BJ,9[wN^+/=+,	  OI N< PD ' 	%LL!$L	%s)   'J0?#J5, J;6K  	K.	K))K.c                     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.
    )r~   )rP   kwargss     r   glyph_to_quadraticr   P  s    
 w1&11r   c                     t        | gfi |S )zConvenience wrapper around fonts_to_quadratic, for just one font.
    Return True if the font was modified, else return False.
    )r   )r   r   s     r   r   r   X  s    
 tf///r   )T)NFNT)NNFNFTT)!rL   loggingfontTools.pens.basePenr   fontTools.pens.pointPenr    fontTools.pens.reverseContourPenr    r   errorsr   r	   r
   r   r   __all__rz   r   	getLoggerrI   r   r   r   r   rS   rY   rj   rx   r~   r   r   r   rE   r   r   <module>r      s      . 5 > !   !4
5
 = 			8	$ #[ #L&F02$'V NRB 
`F20r   