a
    w=icD                     @   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   p/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/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   _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   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 u 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   r2   r%   r5   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       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    rD   c                 C   s&   d}| D ]}|t |t | 7 }q|S r@   )absrA   r   r   r   _complex_vlen\   s    rF   c                    s   t  fddt|D S )Nc                 3   s   | ]\}} | | V  qd S r   r   )r6   ijGr   r   r9   d   r:   z!_matching_cost.<locals>.<genexpr>)sum	enumerate)rJ   matchingr   rI   r   _matching_costc   s    rN   c                 C   s  t | }zDddlm} || \}}|tt|k s:J t|t| |fW S  ty^   Y n0 zDddlm	} d g| }| 
| D ]\}}|||< q|t| |fW S  ty   Y n0 |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.optimizerO   listrangeallrN   ImportErrorZmunkresrP   Zcompute	Exception	itertoolspermutationsnext)rJ   r   rO   rowscolsrP   rowcolrX   bestZ	best_costpZcostr   r   r   #min_cost_perfect_bipartite_matchingg   s4    



r`   c           2         sN  |d u r| }|d u r | d   }g }t fdd}|D ]}zg }g }g }t| |D ]\}	}
||	vr~||d|
d qZ|	| }tt|	d}z|j|dd W n ty   || Y n0 |j}~g }g }g }|| || || t	|D ]:\}}t
d	d
 |jD }|| t|	d}z|| W nD ty } z*|||
|dd W Y d }~qW Y d }~n
d }~0 0 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sJ |d dv sJ t }t|d}|| d}|jD ]\}}|d> |B }q4t|j}d|> d }g }|| t|D ]D} || > |@ |||  ? B }||krx|tdd |jD |  qxt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qTt	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qT|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  qHq|d }#t	|dd  D ]\} t|#tkr~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 yF } z||d&|
|d' W Y d }~q:d }~0 0 q:S )(Nr   c                    s     | g | d S r   )
setdefaultr'   )Z	glyphname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   )r6   instructionr   r   r   r9      r:   ztest.<locals>.<genexpr>	open_path)rg   contourrf   g      ?   r.   r   r-   )r"   r%   F   c                 S   s   g | ]\}}t | qS r   complexr6   r4   blr   r   r   
<listcomp>   r:   ztest.<locals>.<listcomp>c                 S   s   g | ]\}}t | qS r   rm   ro   r   r   r   rq      r:   
path_count)rf   master_1master_2value_1value_2
node_count)rf   pathrs   rt   ru   rv   node_incompatibility)rf   rx   noders   rt   ru   rv   c                    s   g | ]  fd dD qS )c                    s   g | ]}t t |qS r   )rD   r?   )r6   r>   r=   r   r   rq   '  r:   z#test.<locals>.<listcomp>.<listcomp>r   )r6   )m1r{   r   rq   '  r:   c                 3   s   | ]} | | V  qd S r   r   )r6   rG   )costsr   r   r9   *  r:   gffffff?contour_orderc                 S   s   g | ]}|qS r   r   )r6   rB   r   r   r   rq   A  r:   c                 3   s   | ]}t t |V  qd S r   )rF   r?   )r6   c1)c0r   r   r9   A  r:   wrong_start_point)rf   rj   rs   rt   Z
math_error)rf   rg   error)!keysr   r<   r,   r   Zdraw	TypeErrorr   r'   rL   r;   r   Zreplayr   rE   ZareaintZmeanXZmeanYZstddevXZstddevYZcorrelationr/   r   r
   rS   r   rR   reversedr`   rK   min
ValueError)2	glyphsetsglyphsnameshistrd   Z
glyph_nameZ
allVectorsZallNodeTypesZallContourIsomorphismsr   nameglyphZperContourPenZcontourPensZcontourVectorsZcontourIsomorphismsZ	nodeTypesZixrj   ZnodeVecsstatsesizeZvectorZpoints	converterbitsr4   r8   r   maskZisomorphismsrG   mirroredZreversed_bitsZm0ZpathIxZnodes1Znodes2ZnodeIxZn1Zn2rM   Zmatching_costZidentity_matchingZidentity_costZcontour0Zcontour1Zmin_costZ
first_costr   )r   r}   r|   rc   r   test   sR   






"





 
"


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




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|v 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)metavarrf   nargsr   )basenamerl   z.designspace)DesignSpaceDocumentc                 S   s   g | ]
}|j qS r   )rx   )r6   rg   r   r   r   rq   w  r:   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   rq   }  r:   z.ttf)TTFontgvarz()c                 S   s   t | | fS r   r	   )rB   r   r   r   <lambda>  r:   zmain.<locals>.<lambda>)keyT)location
normalizedz.ufo)	UFOReader.getGlyphSetc                 S   s   g | ]}|  qS r   )r   )r6   fontr   r   r   rq     r:   )r   r   zGlyph z was not compatible: rf   re   z"    Glyph was missing in master %srg   ri   z'    Glyph has an open path in master %srr   z*    Path count differs: %i in %s, %i in %sru   rs   rv   rt   rw   z5    Node count differs in path %i: %i in %s, %i in %srx   ry   z7    Node %o incompatible in path %i: %s in %s, %s in %srz   r~   z-    Contour order differs: %s in %s, %s in %sr   z*    Contour %d start point differs: %s, %srj   )(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hasattrr   jsonprintdumps)argsr   parserr   r   Zfontsr   r   Zdesignspacer   r   Zgsfontr   r   r   locsr   varloctagvalZnew_locsr   filenamer   r   rc   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   rW   sysr   r   r,   r/   r?   rD   rF   rN   r`   r   r   r)   rc   exitr   boolr   r   r   r   <module>   s2   	"#
 N
 
