U
    »mœdKR  ã                   @   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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�rd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   úX/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/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   Ú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   Ú_curveToOne0   s    zPerContourPen._curveToOnec                 C   s   | j  ¡  d | _ d S r   )r   Ú	closePath©r   r   r   r   Ú
_closePath3   s    
zPerContourPen._closePathc                 C   s   | j  ¡  d | _ d S r   )r   ÚendPathr#   r   r   r   Ú_endPath7   s    
zPerContourPen._endPathc                 C   s   |   ¡  | _}| j |¡ d S r   )r   r   r   Úappend)r   Úpenr   r   r   r   ;   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.   A   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   G   s    zRecordingPointPen.__init__Nc                 K   s   d S r   r   )r   Ú
identifierÚkwargsr   r   r   Ú	beginPathJ   s    zRecordingPointPen.beginPath)Úreturnc                 C   s   d S r   r   r#   r   r   r   r%   M   s    zRecordingPointPen.endPathc                 C   s    | j  ||d krdndf¡ d S )NFT)r   r'   )r   ÚptZsegmentTyper   r   r   ÚaddPointP   s    zRecordingPointPen.addPoint)N)N)r)   r*   r+   r   r2   r%   r5   r   r   r   r   r/   F   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>U   s     z_vdiff.<locals>.<genexpr>)ÚtupleÚzip)Úv0Úv1r   r   r   Ú_vdiffT   s    r>   c                 C   s   d}| D ]}||| 7 }q|S ©Nr   r   ©ZvecÚvÚxr   r   r   Ú_vlenX   s    rC   c                 C   s&   d}| D ]}|t |ƒt |ƒ 7 }q|S r?   )Úabsr@   r   r   r   Ú_complex_vlen_   s    rE   c                    s   t ‡ fdd„t|ƒD ƒƒS )Nc                 3   s   | ]\}}ˆ | | V  qd S r   r   )r6   ÚiÚj©ÚGr   r   r9   g   s     z!_matching_cost.<locals>.<genexpr>)ÚsumÚ	enumerate)rI   Úmatchingr   rH   r   Ú_matching_costf   s    rM   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rÌtdƒ‚t t|ƒ¡}tt|ƒƒ}	t| |	ƒ}
|D ]$}t| |ƒ}||
k rôt|ƒ| }	}
qô|	|
fS )Nr   )Úlinear_sum_assignment)ÚMunkresé   z4Install Python module 'munkres' or 'scipy >= 0.17.0')r
   Zscipy.optimizerN   ÚlistÚrangeÚallÚAssertionErrorrM   ÚImportErrorZmunkresrO   ZcomputeÚ	ExceptionÚ	itertoolsÚpermutationsÚnext)rI   r   rN   ÚrowsÚcolsrO   ÚrowÚcolrX   ÚbestZ	best_costÚpZcostr   r   r   Ú#min_cost_perfect_bipartite_matchingj   s4    



r`   Fc           4         s  |d kr| }|d kr"dd„ | D ƒ}g }t ƒ ‰‡fdd„}|D �]Ì}�zŽd}g }g }	g }
t| |ƒD �]\}}|| }|d kr®|sŽ||d|dœƒ |	 d ¡ | d ¡ |
 d ¡ q`tt|d�}z|j|d	d
� W n tk
rê   | |¡ Y nX |j}~g }g }g }|	 |¡ | |¡ |
 |¡ t|ƒD �]<\}}t	dd„ |jD ƒƒ}| |¡ t
|d�}z| |¡ W n@ tk
�r¦ } z ||||ddœƒ W Y ¢�q&W 5 d }~X Y nX t t|jƒ¡d }t|ƒt|jƒt|jƒt|jd ƒt|jd ƒt|j| ƒf}| |¡ |d dk�r�q&|d dk�s(t‚|d dk�s:t‚tƒ }t|dƒ}| |¡ d}|jD ]\}}|d> |B }�q^t|jƒ}d|> d } g }!| |!¡ t|ƒD ]D}"||"> | @ |||" ? B }||k�r¢|! tdd„ |jD ƒ|"ƒ¡ �q¢tt|jƒƒ}#d}$|#D ]\}}|$d> |B }$�qþt|ƒD ]B}"|$|"> | @ |$||" ? B }||k�r|! tdd„ |#D ƒ|"ƒ¡ �q�q&q`|	 t dd„ |	D ƒd ƒ¡}|	| }%t|	|d d … ƒD �].\}"‰ˆd k�r¶�qžt|%ƒtˆƒk�rö||d|| |||" d  t|%ƒtˆƒdœƒ |%ˆk�r�qžtt|%ˆƒƒD ]¸\}&\}'}(|'|(k�r,�qt|'ƒt|(ƒk�rr||d|&|| |||" d  t|'ƒt|(ƒdœƒ �qtt|'|(ƒƒD ]F\})\}*}+|*|+k�r€||d|&|)|| |||" d  |*|+d œƒ �q€�q€�q�qž| t d!d„ |D ƒd ƒ¡}|| }%t||d d … ƒD ]Ô\}"‰ˆd k�r�qt|%ƒtˆƒk�r2�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  ttt|%ƒƒƒ|,dœƒ  �qÜ�q|
 t d&d„ |
D ƒd ƒ¡}|
| }%t|
|d d … ƒD ]¼\}"‰ˆd k�r(�qt|%ƒtˆƒk�r>�q|%�sH�qtt|%ˆƒƒD ]t\}\}0}1|0d ‰ d'd„ ‡ fd(d„|1D ƒD ƒ‰t#ˆƒ}2ˆd }3|2|3d$ k �rV||d)||| |||" d  d*œƒ �qV�qW q< t$k
�r } z||d+||d,œƒ W 5 d }~X Y q<X q<ˆS )-Nc                 S   s   h | ]}|  ¡ D ]}|’qqS r   ©Úkeys)r6   r   Úgr   r   r   Ú	<setcomp>“   s     
  ztest.<locals>.<setcomp>c                    s   ˆ   | g ¡ |¡ d S r   )Ú
setdefaultr'   )Z	glyphnameÚproblem)Úproblemsr   r   Úadd_problem˜   s    ztest.<locals>.add_problemr   Úmissing)ÚtypeÚmaster©r   T)ZoutputImpliedClosingLinec                 s   s   | ]}|d  V  qdS )r   Nr   )r6   Zinstructionr   r   r   r9   ½   s     ztest.<locals>.<genexpr>Ú	open_path)rk   Úcontourrj   g      à?é   r.   r   r-   )r"   r%   Fé   c                 S   s   g | ]\}}t |Ž ‘qS r   ©Úcomplex©r6   r4   Úblr   r   r   Ú
<listcomp>ë   s     ztest.<locals>.<listcomp>c                 S   s   g | ]\}}t |Ž ‘qS r   rq   rs   r   r   r   ru   ö   s     c                 s   s   | ]}|d k	r|V  qd S r   r   ©r6   rB   r   r   r   r9   ü   s      Ú
path_count)rj   Úmaster_1Úmaster_2Úvalue_1Úvalue_2Ú
node_count)rj   Úpathrx   ry   rz   r{   Únode_incompatibility)rj   r}   Únoderx   ry   rz   r{   c                 s   s   | ]}|d k	r|V  qd S r   r   rv   r   r   r   r9   3  s      c                    s   g | ]‰ ‡ fd d„ˆD ƒ‘qS )c                    s   g | ]}t tˆ |ƒƒ‘qS r   )rC   r>   )r6   r=   ©r<   r   r   ru   ?  s     z#test.<locals>.<listcomp>.<listcomp>r   )r6   )Úm1r€   r   ru   ?  s     c                 3   s   | ]}ˆ | | V  qd S r   r   )r6   rF   )Úcostsr   r   r9   B  s     gffffffî?Úcontour_orderc                 s   s   | ]}|d k	r|V  qd S r   r   rv   r   r   r   r9   V  s      c                 S   s   g | ]}|‘qS r   r   )r6   rA   r   r   r   ru   d  s    c                 3   s   | ]}t tˆ |ƒƒV  qd S r   )rE   r>   )r6   Úc1)Úc0r   r   r9   e  s     Úwrong_start_point)rj   rn   rx   ry   Ú
math_error)rj   rk   Úerror)%r   r;   r'   r,   r   ZdrawÚ	TypeErrorr   rK   r:   r   Zreplayr   ÚmathÚsqrtrD   ZareaÚintZmeanXZmeanYZstddevXZstddevYZcorrelationrT   r/   r   r
   rR   r   rQ   ÚreversedÚindexrY   r`   rJ   ÚminÚ
ValueError)4Ú	glyphsetsÚglyphsÚnamesÚignore_missingÚhistrh   Z
glyph_nameZm0idxZ
allVectorsZallNodeTypesZallContourIsomorphismsr   ÚnameÚglyphZperContourPenZcontourPensZcontourVectorsZcontourIsomorphismsZ	nodeTypesZixrn   ZnodeVecsÚstatsÚeÚsizeZvectorZpointsÚ	converterÚbitsr4   r8   r   ÚmaskZisomorphismsrF   ÚmirroredZreversed_bitsZm0ZpathIxZnodes1Znodes2ZnodeIxZn1Zn2rL   Zmatching_costZidentity_matchingZidentity_costZcontour0Zcontour1Zmin_costZ
first_costr   )r…   r‚   r�   rg   r   Útest�   sŽ   



 ÿ





þú





ÿ
ÿÿ
ûþ


úþ
ùþÿ
ÿ
þûþ

ÿ
ÿüþ

þrŸ   c           "         s6  ddl }|jdtjd�}|jdddd� |jd	dd
d� |jdddd� |jddtddd� | | ¡} d}ddlm} g }g }t	| j
ƒdk�rN| j
d  d¡rÐd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¡�rNddlm} || j
d ƒ}d|k�rN|d }tƒ }|j ¡ D ]P}|D ]D}g }t|j ¡ ƒD ]\}}| ||d f¡ �q’| 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 ¡ �qTg }|D ]<}t#|d'ƒ�rÚ| ¡ ‰ n|‰ | ‡ fd(d)„ˆ  $¡ D ƒ¡ �qÀ|�std*d„ |D ƒƒ}|D ]4‰ tˆ  $¡ ƒ}|| }|�r|D ]}dˆ |< �q<�qt%|||| j&d+�}| j'�s(| j(�rŒddl(}t)| *|¡ƒ �nœ| ¡ D �]�\}} t)d,|› d-�ƒ | D �]n}!|!d. d/k�rÖt)d0|!d1  ƒ |!d. d2k�rôt)d3|!d1  ƒ |!d. d4k�r&t)d5|!d6 |!d7 |!d8 |!d9 f ƒ |!d. d:k�r^t)d;|!d< |!d6 |!d7 |!d8 |!d9 f ƒ |!d. d=k�rœt)d>|!d? |!d< |!d6 |!d7 |!d8 |!d9 f ƒ |!d. d@k�rÎt)dA|!d6 |!d7 |!d8 |!d9 f ƒ |!d. dBk�rút)dC|!dD |!d7 |!d9 f ƒ |!d. dEk�r²t)dF|!d1 |!dG f ƒ �q²�q”|�r2|S dS )Hz/Test for interpolatability issues between fontsr   Nzfonttools varLib.interpolatable)Údescriptionz--jsonÚ
store_truezOutput report in JSON format)ÚactionÚhelpz--quietz%Only exit with code 1 or 0, no outputz--ignore-missingz<Will not report glyphs missing from sparse masters as errorsÚinputsÚFILEú+zAInput a single DesignSpace/Glyphs file, or multiple TTF/UFO files)Úmetavarrj   Únargsr£   )Úbasenamerp   z.designspace)ÚDesignSpaceDocumentc                 S   s   g | ]
}|j ‘qS r   )r}   )r6   rk   r   r   r   ru   «  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)r6   Úfr   r   r   ru   ²  s     z.ttf)ÚTTFontÚgvarz()c                 S   s   t | ƒ| fS r   r	   )rA   r   r   r   Ú<lambda>Ç  ó    zmain.<locals>.<lambda>)ÚkeyT)ÚlocationÚ
normalizedz.ufo)Ú	UFOReaderÚ.ÚgetGlyphSetc                    s   i | ]}|ˆ | “qS r   r   )r6   r   rl   r   r   Ú
<dictcomp>è  s      zmain.<locals>.<dictcomp>c                 S   s   g | ]}|  ¡ D ]}|‘qqS r   ra   )r6   r   Úgnr   r   r   ru   ë  s     
  )r’   r“   r”   zGlyph z was not compatible: rj   ri   z"    Glyph was missing in master %srk   rm   z'    Glyph has an open path in master %srw   z*    Path count differs: %i in %s, %i in %srz   rx   r{   ry   r|   z5    Node count differs in path %i: %i in %s, %i in %sr}   r~   z7    Node %o incompatible in path %i: %s in %s, %s in %sr   rƒ   z-    Contour order differs: %s in %s, %s in %sr†   z*    Contour %d start point differs: %s, %srn   r‡   z!    Miscellaneous error in %s: %srˆ   )+ÚargparseÚArgumentParserÚmainÚ__doc__Úadd_argumentÚstrÚ
parse_argsÚos.pathr©   r
   r¤   ÚendswithZfontTools.designspaceLibrª   ÚfromfileÚsourcesZ	glyphsLibr«   r¬   ÚextendZfontTools.ttLibr¯   ÚsetÚ
variationsÚvaluesÚsortedZaxesÚitemsr'   Úaddr:   r¸   ZfontTools.ufoLibr¶   ÚrsplitÚhasattrrb   rŸ   r”   ÚquietÚjsonÚprintÚdumps)"Úargsr»   Úparserr’   r©   Zfontsr“   rª   Zdesignspacer«   r¬   Zgsfontr¯   Zfontr°   ZlocsrÈ   ÚvarÚlocÚtagÚvalZnew_locsr   Úfilenamer¶   r‘   ZglyphSetGlyphNamesÚdiffrº   rg   rÐ   r—   Zglyph_problemsr_   r   rl   r   r½   |  sH   þýýýû





    ÿ
ÿÿûÿÿ
úÿÿüÿÿ	ýÿÿþÿÿr½   Ú__main__)NNF)N)!r¾   ZfontTools.pens.basePenr   r   ZfontTools.pens.pointPenr   ZfontTools.pens.recordingPenr   ZfontTools.pens.statisticsPenr   ZfontTools.pens.momentsPenr   Úcollectionsr   rŠ   rW   Úsysr   r   r,   r/   r>   rC   rE   rM   r`   rŸ   r½   r)   rg   ÚexitrŒ   Úboolr   r   r   r   Ú<module>   s4   
"#
 p
 E
