U
    6cD                     @   s  d Z ddlmZm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 ddlZddlZd	d
 ZG dd deZG dd deZG dd deZdd Zdd Zdd Zdd Zdd Zd ddZd!ddZedk rddlZe Zeeee dS )"z
Tool to find wrong contour order between different masters, and
other interpolatability (or lack thereof) issues.

Call as:
$ fonttools varLib.interpolatable font1 font2 ...
    )AbstractPenBasePen)SegmentToPointPen)RecordingPen)StatisticsPen)OpenContourError)OrderedDictNc                 C   s8   t | }||; }|s| S | || d | d||   S )z{Rotate list by k items forward.  Ie. item at position 0 will be
    at position k in returned list.  Negative k is allowed.Nlen)lkn r   C/tmp/pip-unpacked-wheel-n2hbwplv/fontTools/varLib/interpolatable.py	_rot_list   s
     r   c                   @   sN   e Zd Zd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 )PerContourPenNc                 C   s(   t | | || _|| _d | _g | _d S N)r   __init__Z	_glyphset_Pen_penvalue)selfZPenglyphsetr   r   r   r      s
    zPerContourPen.__init__c                 C   s   |    | j| d S r   )_newItemr   moveTo)r   Zp0r   r   r   _moveTo#   s    zPerContourPen._moveToc                 C   s   | j | d S r   )r   ZlineTo)r   p1r   r   r   _lineTo'   s    zPerContourPen._lineToc                 C   s   | j || d S r   )r   ZqCurveTo)r   r   p2r   r   r   _qCurveToOne*   s    zPerContourPen._qCurveToOnec                 C   s   | j ||| d S r   )r   ZcurveTo)r   r   r   Zp3r   r   r   _curveToOne-   s    zPerContourPen._curveToOnec                 C   s   | j   d | _ d S r   )r   	closePathr   r   r   r   
_closePath0   s    
zPerContourPen._closePathc                 C   s   | j   d | _ d S r   )r   endPathr"   r   r   r   _endPath4   s    
zPerContourPen._endPathc                 C   s   |    | _}| j| d S r   )r   r   r   append)r   Zpenr   r   r   r   8   s    zPerContourPen._newItem)N)__name__
__module____qualname__r   r   r   r   r    r#   r%   r   r   r   r   r   r      s   
r   c                   @   s   e Zd Zdd ZdS )PerContourOrComponentPenc                 C   s   |    | jd || d S )N)r   r   addComponent)r   Z	glyphNameZtransformationr   r   r   r,   >   s    z%PerContourOrComponentPen.addComponentN)r'   r(   r)   r,   r   r   r   r   r*   =   s   r*   c                   @   s6   e Zd Zdd ZdddZddddZdd	d
ZdS )RecordingPointPenc                 C   s
   g | _ d S r   )r   r"   r   r   r   r   E   s    zRecordingPointPen.__init__Nc                 K   s   d S r   r   )r   
identifierkwargsr   r   r   	beginPathH   s    zRecordingPointPen.beginPath)returnc                 C   s   d S r   r   r"   r   r   r   r$   K   s    zRecordingPointPen.endPathc                 C   s    | j ||d krdndf d S )NFT)r   r&   )r   ptZsegmentTyper   r   r   addPointN   s    zRecordingPointPen.addPoint)N)N)r'   r(   r)   r   r0   r$   r3   r   r   r   r   r-   C   s   
r-   c                 C   s   t dd t| |D S )Nc                 s   s   | ]\}}|| V  qd S r   r   ).0abr   r   r   	<genexpr>S   s     z_vdiff.<locals>.<genexpr>)tuplezip)v0v1r   r   r   _vdiffR   s    r<   c                 C   s   d}| D ]}||| 7 }q|S Nr   r   Zvecvxr   r   r   _vlenV   s    rA   c                 C   s&   d}| D ]}|t |t | 7 }q|S r=   )absr>   r   r   r   _complex_vlen\   s    rC   c                    s   t  fddt|D S )Nc                 3   s   | ]\}} | | V  qd S r   r   )r4   ijGr   r   r7   d   s     z!_matching_cost.<locals>.<genexpr>)sum	enumerate)rG   matchingr   rF   r   _matching_costc   s    rK   c                 C   s"  t | }zDddlm} || \}}|tt|k s:tt|t| |fW S  tk
r`   Y nX zDddl	m
} d g| }| | D ]\}}|||< q|t| |fW S  tk
r   Y nX |dkrtdtt|}tt|}	t| |	}
|D ]$}t| |}||
k rt|| }	}
q|	|
fS )Nr   )linear_sum_assignment)Munkres   z4Install Python module 'munkres' or 'scipy >= 0.17.0')r
   Zscipy.optimizerL   listrangeallAssertionErrorrK   ImportErrorZmunkresrM   Zcompute	Exception	itertoolspermutationsnext)rG   r   rL   ZrowscolsrM   rowcolrV   bestZ	best_costpZcostr   r   r   #min_cost_perfect_bipartite_matchingg   s4    



r]   c           2         sH  |d kr| }|d kr | d   }g }t fdd}|D ]}zg }g }g }t| |D ]\}	}
||	kr~||d|
d qZ|	| }tt|	d}z|j|dd W n tk
r   || Y nX |j}~g }g }g }|| || || t	|D ]4\}}t
d	d
 |jD }|| t|	d}z|| W n> tk
r| } z|||
|dd W Y qW 5 d }~X Y nX t|jd d }t|t|jt|jt|jd t|jd t|j| f}|| |d dkrq|d dkst|d dkstt }t|d}|| d}|jD ]\}}|d> |B }q0t|j}d|> d }g }|| t|D ]D} || > |@ |||  ? B }||krt|tdd |jD |  qttt|j}!d}"|!D ]\}}|"d> |B }"qt|D ]B} |"| > |@ |"||  ? B }||kr|tdd |!D |  qqqZ|d }#t	|dd  D ]\} t|#tkr||d|d || d  t|#td |#krqPt	t|#D ]\}$\}%}&|%|&kr̐qt|%t|&kr||d|$|d || d  t|%t|&d qt	t|%|&D ]B\}'\}(})|(|)kr||d|$|'|d || d  |(|)d qqqqP|d }#t	|dd  D ]\} t|#tkrq|#sqfdd|#D t\}*}+ttt|#},tfdd
tt|#D }-|*|,kr|+|-d  k r||d!|d || d  ttt|#|*d  qDq|d }#t	|dd  D ]\} t|#tkrzq\|#sq\t	t|#D ]p\}\}.}/|.d  d"d  fd#d
|/D D t }0d }1|0|1d  k r||d$||d || d  d% qq\W q: t!k
r@ } z||d&|
|d' W 5 d }~X Y q:X q:S )(Nr   c                    s     | g | d S r   )
setdefaultr&   )Z	glyphnameZproblem)problemsr   r   add_problem   s    ztest.<locals>.add_problemmissing)typemaster)r   T)ZoutputImpliedClosingLinec                 s   s   | ]}|d  V  qdS )r   Nr   )r4   Zinstructionr   r   r   r7      s     ztest.<locals>.<genexpr>	open_path)rc   contourrb   g      ?   r,   r   r+   )r!   r$   F   c                 S   s   g | ]\}}t | qS r   complexr4   r2   blr   r   r   
<listcomp>   s     ztest.<locals>.<listcomp>c                 S   s   g | ]\}}t | qS r   rh   rj   r   r   r   rl      s     
path_count)rb   master_1master_2value_1value_2
node_count)rb   pathrn   ro   rp   rq   node_incompatibility)rb   rs   nodern   ro   rp   rq   c                    s   g | ]  fd dD qS )c                    s   g | ]}t t |qS r   )rA   r<   )r4   r;   r:   r   r   rl   '  s     z#test.<locals>.<listcomp>.<listcomp>r   )r4   )m1rv   r   rl   '  s     c                 3   s   | ]} | | V  qd S r   r   )r4   rD   )costsr   r   r7   *  s     gffffff?contour_orderc                 S   s   g | ]}|qS r   r   )r4   r?   r   r   r   rl   A  s     c                 3   s   | ]}t t |V  qd S r   )rC   r<   )r4   Zc1)c0r   r   r7   A  s     wrong_start_point)rb   re   rn   ro   Z
math_error)rb   rc   error)"keysr   r9   r*   r   Zdraw	TypeErrorr   r&   rI   r8   r   Zreplayr   rB   areaintZmeanXZmeanYZstddevXZstddevYZcorrelationrR   r-   r   r
   rP   r   rO   reversedr]   rH   min
ValueError)2	glyphsetsglyphsnameshistr`   Z
glyph_nameZ
allVectorsZallNodeTypesZallContourIsomorphismsr   nameglyphZperContourPenZcontourPensZcontourVectorsZcontourIsomorphismsZ	nodeTypesixre   ZnodeVecsstatsesizeZvectorZpoints	converterbitsr2   r6   r   maskZisomorphismsrD   mirroredZreversed_bitsZm0ZpathIxZnodes1Znodes2ZnodeIxZn1Zn2rJ   Zmatching_costZidentity_matchingZidentity_costZcontour0Zcontour1Zmin_costZ
first_costr   )rz   rx   rw   r_   r   test   sT   
 











 
"












r   c                 C   sp  ddl }|jdtjd}|jdddd |jd	d
tddd || } d}ddlm} g }g }t	| j
dkr.| j
d drddlm} || j
d }dd |jD | _
n~| j
d drddlm}	m}
 |	| j
d }||
| dd |D }g | _
n(| j
d dr.ddlm} || j
d }d|kr.|d }t }|j D ]P}|D ]D}g }t|j D ]\}}|||d f qr|t| q\qTi g}|d t|dd dD ]:}|t| i }|D ]\}}|||< q|| q|}~|D ]}||j|dd qg | _
| j
D ]b}|d r`dd!l m!} ||| nddlm} ||| |||"d"dd  q4t#|d d#rd$d |D }n|}t$|||d%}| j%rddl%}t&|'| nv| D ]j\}}t&d&| d' |D ]H}|d( d)kr6t&d*|d+   |d( d,krTt&d-|d+   |d( d.krt&d/|d0 |d1 |d2 |d3 f  |d( d4krt&d5|d6 |d0 |d1 |d2 |d3 f  |d( d7krt&d8|d9 |d6 |d0 |d1 |d2 |d3 f  |d( d:kr.t&d;|d0 |d1 |d2 |d3 f  |d( d<krt&d=|d> |d1 |d3 f  qq|rl|S dS )?z/Test for interpolatability issues between fontsr   Nzfonttools varLib.interpolatable)descriptionz--json
store_truezOutput report in JSON format)actionhelpinputsFILE+zInput TTF/UFO files)metavarrb   nargsr   )basenamerg   z.designspace)DesignSpaceDocumentc                 S   s   g | ]
}|j qS r   )rs   )r4   rc   r   r   r   rl   w  s     zmain.<locals>.<listcomp>z.glyphs)GSFontto_ufosc                 S   s    g | ]}d |j j|j jf qS )z%s-%s)infoZ
familyNameZ	styleName)r4   fr   r   r   rl   }  s     z.ttf)TTFontgvarz()c                 S   s   t | | fS r   r	   )r?   r   r   r   <lambda>      zmain.<locals>.<lambda>)keyT)location
normalizedz.ufo)	UFOReader.getGlyphSetc                 S   s   g | ]}|  qS r   )r   )r4   fontr   r   r   rl     s     )r   r   zGlyph z was not compatible: rb   ra   z"    Glyph was missing in master %src   rd   z'    Glyph has an open path in master %srm   z*    Path count differs: %i in %s, %i in %srp   rn   rq   ro   rr   z5    Node count differs in path %i: %i in %s, %i in %srs   rt   z7    Node %o incompatible in path %i: %s in %s, %s in %sru   ry   z-    Contour order differs: %s in %s, %s in %sr{   z*    Contour %d start point differs: %s, %sre   )(argparseArgumentParsermain__doc__add_argumentstr
parse_argsos.pathr   r
   r   endswithZfontTools.designspaceLibr   ZfromfilesourcesZ	glyphsLibr   r   extendZfontTools.ttLibr   set
variationsvaluessortedZaxesitemsr&   addr8   r   ZfontTools.ufoLibr   rsplithasattrr   jsonprintdumps)argsr   parserr   r   Zfontsr   r   Zdesignspacer   r   Zgsfontr   r   r   Zlocsr   varloctagvalZnew_locsr   filenamer   r   r_   r   r   Zglyph_problemsr\   r   r   r   r   W  s       






	r   __main__)NN)N) r   ZfontTools.pens.basePenr   r   ZfontTools.pens.pointPenr   ZfontTools.pens.recordingPenr   ZfontTools.pens.statisticsPenr   ZfontTools.pens.momentsPenr   collectionsr   rU   sysr   r   r*   r-   r<   rA   rC   rK   r]   r   r   r'   r_   exitr   boolr   r   r   r   <module>   s2   	"#
 N
 
