U
    Dvf                     @   st  d Z ddlT ddlmZ ddlmZ ddlmZmZm	Z	 ddl
mZ ddlmZmZ dd	lm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mZ ddl m!Z!m"Z"m#Z# ddl$Z$ddl%Z%e$&dZ'dZ(dZ)dZ*dZ+G dd dZ,d'de(e)e+ddddZ-ee-dd Z.d d! Z/d"d# Z0d(d$d%Z1e2d&krpddl3Z3e1 Z4e35e6e7e4 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 ...
   )*)test_contour_order)test_starting_point    )RecordingPenDecomposingRecordingPenlerpRecordings)TransformPen)StatisticsPenStatisticsControlPen)OpenContourError)piecewiseLinearMapnormalizeLocation)floatToFixedToStr)	Transform)defaultdict)SimpleNamespace)wraps)pformat)sqrtatan2piNzfontTools.varLib.interpolatablegffffff?g      ?gMb`?i  c                   @   s2   e Zd ZdZdd Zdd Zdd Zdd	d
ZdS )Glyph)	
recordings
greenStatscontrolStatsgreenVectorscontrolVectors	nodeTypesisomorphismspointsopenContoursc                 C   s,   || _ | jD ]}t| |g  q| | d S N)nameITEMSsetattr	_populate)self	glyphnameglyphsetitem r+   C/tmp/pip-unpacked-wheel-qlge9rch/fontTools/varLib/interpolatable.py__init__4   s    
zGlyph.__init__c                 C   s2   | j D ]&}tt| ||krt| |d  qd S r"   )r$   lengetattrappend)r'   ixr*   r+   r+   r,   _fill_in:   s    
zGlyph._fill_inc                 C   s  || j  }|d k| _| jrd S tt|d}z|j|dd W n tk
rZ   || Y nX |j| _~t| jD ]j\}}dd |jD }| j	
| t|d}t|d}z$|| || | j
d W nB tk
r }	 z"| j
d | | W Y qpW 5 d }	~	X Y nX | j
| | j
| | j
t| | j
t| |d dkrd| | qp|d d	ksvt|d
 dkstt }
t|
d}|| | j
|
j g }| j
| t|
j|d t|
j|d qpd S )Nr)   T)ZoutputImpliedClosingLinec                 S   s   g | ]\}}|qS r+   r+   ).0opargr+   r+   r,   
<listcomp>N   s     z#Glyph._populate.<locals>.<listcomp>Fr   ZaddComponentZmoveTo)Z	closePathZendPath)r#   doesnt_existZPerContourOrComponentPenr   draw	TypeErrorvaluer   	enumerater   r0   r
   r   replayr!   r   r2   r   r   r   contour_vector_from_statsr   AssertionErrorZSimpleRecordingPointPenZSegmentToPointPenr    r   Zadd_isomorphisms)r'   r)   glyphZperContourPenr1   contourr   r   r   er    	converterr   r+   r+   r,   r&   ?   sR    









zGlyph._populateNc                 C   s4   |d kr | j D ]}|| qn| j | | d S r"   )r   r:   )r'   ZpenZcountor_idxrB   r+   r+   r,   r:   w   s    
z
Glyph.draw)N)__name__
__module____qualname__r$   r-   r2   r&   r:   r+   r+   r+   r,   r   '   s
   8r   F)	locations	tolerance	kinkinessupemshow_allc          U      #   sn
  |dkr|d9 }d|  kr$dks*n t |dkr:|d9 }d|ksFt |pVdd D }|d krndd D }t|\}	fd	d
}
|D 	]؉ td   fddD }tdd |D dkrqtt||D ]t\}\}}}|jr
|sڈ tj	||dfV  qd}t|j
D ].\}}|s*qd} tj|||dfV  q|rqqd gt }|	D 	]}|| }|d ksb|jsqb|
| }|d krqb|| }|d ksb|jsqb|j|j}t|tkr
 tj|| || ||t|tdfV  qb|krtt|D ]\}\}}||kr<q"t|t|kr tj||| || ||t|t|dfV  q"tt||D ]D\}\}}||kr tj|||| || ||||d	fV  qqq"t||\}} ||k r* tj|| || ||ttt| | |dfV  | ||< |j}!|j|j}"|j|j}#|j|| } | d k	rrfdd| D fdd| D fdd| D g }$t|#D ]T\}%}&z(t }'tt|%j|&j|'_|$|' W n  tk
r   |$d  Y nX qtt|!D ]\}\}(})|(d ks|)d kst|(dkst|(t|)krTqt||||| \}}*}+||k r tj||| || ||d|*|+|d
fV  |$| },|,r|"| d dk | d dk krtd d}-|,|- t |-}.|"| }/| }0|/d |/d  }1|0d |0d  }2|.d |.d  }3ttj!tj"fD ]\}4}5|4rXt#|1|2}6q:nt$|1|2 }6t%d|5|3|6|1|2 |4s|6| |3d ks|4r:d|6|  |3k r:z|4r|6|3 }n|3|6 }W n t&k
r   d}Y nX t%d|  |5||| || |||dfV  q:q|j'}|j'|| d k	rLrLfdd|| D d }7|t( t) | }8tt|D ]\}\}(})|(d ksn|)d ksnt|(dksnt|(t|)krqntt|(D ]v}9|(|9 }:|)|9 };|:d r|;d sq|(|9d  }<|)|9d  }=|(|9d t|(  }>|)|9d t|)  }?|<d rF|=d rFq|<d r^|=d r^qt*|:d  }:t*|;d  };t*|<d  }<t*|=d  }=t*|>d  }>t*|?d  }?|:|< }@|>|: }A|;|= }B|?|; }C|@j+|Aj, |@j,|Aj+  }D|Bj+|Cj, |Bj,|Cj+  }Ez,|Dt-|@t-|A  }D|Et-|Bt-|C  }EW n t&k
r>   Y qY nX t-|D|7kst-|E|7kr`q|@j+|Aj+ |@j,|Aj,  }F|Bj+|Cj+ |Bj,|Cj,  }G|Fdk s|Gdk rqt-|@t-|@t-|A  }Ht-|Bt-|Bt-|C  }It-|H|I }Jt-|J|7k rq|:|; d! }K|<|= d! }L|>|? d! }M|K|L }N|M|K }O|Nj+|Oj, |Nj,|Oj+  }Pz|Pt-|Nt-|O  }PW n t&k
	rv   Y qY nX t-|P||  |7k	rq|Pt-|N t-|O }Qt-|N|O }Rt-|Q|R }S|S|8k 	r̐q|S|R }T|T|7k	rq|7t-|P|  }t%d"|S|T|P|J t%d|  tj.||| || |||9|d#fV  qqn|rb tj/|| || ||d$fV  qbqd S )%N
   g{Gz?r   r   c                 S   s   g | ]}t |qS r+   )repr)r4   gr+   r+   r,   r7      s     ztest_gen.<locals>.<listcomp>c                 S   s   h | ]}|  D ]}|qqS r+   keys)r4   r)   rO   r+   r+   r,   	<setcomp>   s     
  ztest_gen.<locals>.<setcomp>c                    sJ   | d krd S |  } | d kr d S |  d k	rF |  | d krF|  } q | S r"   r+   )ir(   )	glyphsetsparentsr+   r,   grand_parent   s    
ztest_gen.<locals>.grand_parentzTesting glyph %sc                    s   g | ]}t  |qS r+   )r   )r4   r)   )
glyph_namer+   r,   r7      s     c                 S   s   g | ]}|d k	rdqS )Nr   r+   )r4   rA   r+   r+   r,   r7      s      )typemaster
master_idxFT)rX   rY   rZ   rB   )rX   master_1master_2master_1_idxmaster_2_idxvalue_1value_2)rX   pathr[   r\   r]   r^   r_   r`   )	rX   ra   noder[   r\   r]   r^   r_   r`   )rX   r[   r\   r]   r^   r_   r`   rI   c                    s   g | ]} | qS r+   r+   r4   rS   )m1Isomorphismsr+   r,   r7   6  s     c                    s   g | ]} | qS r+   r+   rc   )	m1Vectorsr+   r,   r7   7  s     c                    s   g | ]} | qS r+   r+   rc   )
recording1r+   r,   r7   8  s     )
rX   rB   r[   r\   r]   r^   r_   r`   reversedrI   r3   z;%s: actual size %g; threshold size %g, master sizes: %g, %ggh㈵>ztolerance %g)rX   rB   r[   r\   r]   r^   rI   c                    s   g | ]} | qS r+   r+   rc   )m1r+   r,   r7     s     g?   z=kink: deviation %g; deviation_ratio %g; sin_mid %g; r_diff %g)rX   rB   r[   r\   r]   r^   r<   rI   )rX   r[   r\   r]   r^   )0r@   Zfind_parents_and_orderloginfor.   r=   zipr9   InterpolatableProblemMISSINGr!   	OPEN_PATHr   
PATH_COUNT
NODE_COUNTNODE_INCOMPATIBILITYr   CONTOUR_ORDERlistranger   r   r   r   r   r<   r0   
ValueErrorr   WRONG_START_POINTr
   r>   r?   UNDERWEIGHT
OVERWEIGHTmaxr   debugZeroDivisionErrorr    DEFAULT_KINKINESS_LENGTHDEFAULT_KINKINESScomplexrealimagabsKINKNOTHING)UrT   glyphsnamesignore_missingrH   rI   rJ   rK   rL   orderrV   Z	allGlyphsrZ   rA   r)   r#   Zhas_openr1   openZ	matchingsZm1idxZglyph1Zm0idxZglyph0Zm0ZpathIxZnodes1Znodes2ZnodeIxZn1Zn2Zthis_toleranceZmatchingZm0IsomorphismsZ	m0VectorsZ
recording0ZmidRecordingZc0Zc1rZcontour0Zcontour1Zproposed_pointreverserB   ZmidStatsZ	midVectorZm0VecZm1VecZsize0Zsize1ZmidSizeZ
overweightZproblem_typeZexpectedSizetZdeviation_thresholdrS   Zpt0Zpt1Zpt0_prevZpt1_prevZpt0_nextZpt1_nextZd0_prevZd0_nextZd1_prevZd1_nextZsin0Zsin1Zdot0Zdot1Zr0Zr1Zr_diffZmidZmid_prevZmid_nextZmid_d0Zmid_d1Zsin_midZcrossZarc_lenZ	deviationZdeviation_ratior+   )rW   rT   rh   rd   re   rU   rf   r,   test_gen   s   



	







    

(








r   c                  O   s.   t t}t| |D ]\}}|| | q|S r"   )r   rt   r   r0   )argskwargsproblemsr(   problemr+   r+   r,   testF  s    r   c                 C   sB   | |krd S ||  || < t ||  dg D ]}t|j||| q(d S )N
components)r/   recursivelyAddGlyphZ	glyphName)r(   r)   Z
ttGlyphSetglyf	componentr+   r+   r,   r   N  s
    r   c                 C   s"   t j| }|rt j|dd | S )NT)exist_ok)osra   dirnamemakedirs)ra   r   r+   r+   r,   ensure_parent_dirW  s    r   c           H         s^  ddl }ddl}|jdtjd}|jdddd |jd	d
dd |jddtdt d |jddtdt d |jdd
dd |jdddd |jdddd |jdddd |jdd
dd |jdddd |jdd
dd |jdd t	d!d"d# |jd$d%t	d&d'd( |jd)d*d
d+d |jd,d
d-d |
| } dd.lm} || jrJd/nd0d1 | jrd|d2d1 | jrv| j nd}dd3lm} g }g }g }	t}
t| j}t| jd4krd}| jd d5r>dd6lm} || jd }d7d8 |jD | _d9d8 |jD }	d:d; |jD d<d; |jD fd=d; D n| jd d>rdd?lm}m } || jd }|j!}
||}d@d8 |jD }dAd8 |D }g | _dBd8 |jD }	dCd; |jD dDd; |jD fdEd; D n4| jd dFrddGl"m#} || jd }|dH j$}
dI|kri |dJ }|jD ]}|j%|j&|j'dK|j(< q<dL|kr|dL }|j) D ]<\}}| * }| D ]\}}t+||| |< qqx|dI }|dM }i }t,t-}|dkrt.|j/0 }|D ]}|j/| D ]} i }!g }"t.| j D ](\}#}$|$d4 |!|#< |"1|#|$d4 f qt|"}%|%|krf|j2|!dNdOdP||%< t3|||% ||% | qqdQg}|2 g}i g}	dRd; t.0 D t.|0 dSdT dUD ]L}%dVdW4fdXdY|%D  dV }&|1|& |1||%  |	1t-|% qdN| _5g | _|	s2dZd8 |D }	| jD ]}'|'d[r~dd\l6m7}( |(|'}t8 })|9|) |)j$}
|1| n(ddGl"m#} ||'}|dH j$}
|1| |1||':d]d4d  q8g }|D ]<}t;|d^r|2 n||1fd_d;0 D  q| j<r^t=| j<  fd`d8t>||D } fdad8t>||	D }	 fdbd8|D }|szt.t=dcd8 |D }t=|}*|D ]4t=0 }+|*|+ },|,r|,D ]}-d|-< qqfddd8|	D }	| j?pt}.| j@dk	r| j@nt}/ztABdet| tABdftC|	 tD||||	|
| j5|.|/| jEdg	}0t,tF}1| jGdkrL|jHntItJ| jGdh}2| jK
s| jLrddlL}3|0D ]\}}4|1| 1|4 qxtM|3N|1|2di 
qd}5|0D ]\}}6|1| 1|6 ||5krtMdj| dk|2di |}5d}7dl|6kr |6dl n|6dm |6dn f}8|8|7krVdo|6kr,|6do n|6dp |6dq f}9tMdrds4|9 |2di |8}7|6dt tOjPkr~tMdu|6do  |2di q|6dt tOjQkrtMdv|6do  |2di q|6dt tOjRkrtMdw|6dx |6dp |6dy |6dq f |2di q|6dt tOjSk	r$tMdz|6d{ |6dx |6dp |6dy |6dq f |2di q|6dt tOjTk	rltMd||6d} |6d{ |6dx |6dp |6dy |6dq f |2di q|6dt tOjUk	rtMd~|6dx |6dp |6dy |6dq f |2di q|6dt tOjVk	rtMd|6d |6dx |6dp |6dy |6dq |6d f |2di n|6dt tOjWk
r"tMd|6d |6dp |6dq f |2di n|6dt tOjXk
rVtMd|6d |6dp |6dq f |2di nf|6dt tOjYk
rtMd|6d |6d |6dp |6dq f |2di n,|6dt tOjZkrtMd|6dp |6dq f |2di qn|0D ]\}}4|1| 1|4 
qt[|1}1dD ]}6t\| |6}:|:dkr
qtABd|6] |: d4dl^m_};m`}< |6dkr8|;n|<}=|=tJ|:||d\}>|>ja||.|/d |1rp|>b|1 |>c|1 |1s| jKs|>d  |1r|>e  |>f  W 5 Q R X 
q| jgrtABd| jg d4dl^mh}? g }@i }A|?|@||db}B|Bja|dO|.|/d |1 D ]*\}C}D|C|At|@< |Bjc|C|DidOdOd q|1sJ| jKsJ|Bd  W 5 Q R X ddli}EtItJ| jgd}2|2jd |2jd |2jd tk|@D ]d\}F}B|F|Akr|2jd|A|F  dld |2jdld |2j|Em|B |2jd |2jd q|2jd W 5 Q R X W n> tnk
rN }G z|G jo|7  _otAp|G  W 5 d}G~GX Y nX |1rZ|1S dS )z/Test for interpolatability issues between fontsr   Nzfonttools varLib.interpolatable)descriptionz--glyphsstorez&Space-separate name of glyphs to check)actionhelpz
--show-all
store_truez3Show all glyph pairs, even if no problems are foundz--tolerancez,Error tolerance. Between 0 and 1. Default %s)r   rX   r   z--kinkinessz)How aggressively report kinks. Default %sz--jsonzOutput report in JSON formatz--pdfzOutput report in PDF formatz--psz"Output report in PostScript formatz--htmlzOutput report in HTML formatz--quietz%Only exit with code 1 or 0, no outputz--outputz3Output file for the problem report; Default: stdoutz--ignore-missingz<Will not report glyphs missing from sparse masters as errorsinputsFILE+zSInput a single variable font / DesignSpace / Glyphs file, or multiple TTF/UFO files)metavarrX   nargsr   z--nameNAMEr0   zGName of the master to use in the report. If not provided, all are used.)r   rX   r   r   z-vz	--verbosezRun verbosely.z--debugzRun with debug output.)configLoggerINFOERROR)levelDEBUG)basenamer   z.designspace)DesignSpaceDocumentc                 S   s   g | ]
}|j qS r+   )ra   r4   rY   r+   r+   r,   r7     s     zmain.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r+   locationr   r+   r+   r,   r7     s     c                 S   s    i | ]}|j |j|j|jfqS r+   r#   Zminimumdefaultmaximumr4   ar+   r+   r,   
<dictcomp>  s     zmain.<locals>.<dictcomp>c                 S   s   i | ]}|j |jqS r+   r#   mapr   r+   r+   r,   r     s      c                    s*   i | ]"\ } t  fd d|D qS )c                 3   s    | ]}t |t  V  qd S r"   r   dictr4   vaxis_mappingskr+   r,   	<genexpr>  s     "main.<locals>.<dictcomp>.<genexpr>tupler4   vvr   r   r,   r     s    )z.glyphsz.glyphspackage)GSFontto_designspacec                 S   s   g | ]
}|j qS r+   )font)r4   sourcer+   r+   r,   r7     s     c                 S   s    g | ]}d |j j|j jf qS )z%s-%s)rk   Z
familyNameZ	styleName)r4   fr+   r+   r,   r7     s     c                 S   s   g | ]
}|j qS r+   r   r   r+   r+   r,   r7     s     c                 S   s    i | ]}|j |j|j|jfqS r+   r   r   r+   r+   r,   r     s     c                 S   s   i | ]}|j |jqS r+   r   r   r+   r+   r,   r     s      c                    s*   i | ]"\ } t  fd d|D qS )c                 3   s    | ]}t |t  V  qd S r"   r   r   r   r+   r,   r     s     r   r   r   r   r   r,   r     s    z.ttf)TTFontheadgvarfvarr8   r   r   avarr   TF)r   
normalizedZrecalcBoundsz''c                 S   s   i | ]
}|d qS )r   r+   r   r+   r+   r,   r     s      c                 S   s   t | | fS r"   )r.   )r   r+   r+   r,   <lambda>      zmain.<locals>.<lambda>)key' c                 3   s.   | ]&\}}d |t t| | df V  qdS )z%s=%s   N)r   r   )r4   r   r   )axisMappingr+   r,   r   "  s    zmain.<locals>.<genexpr>c                 S   s   g | ]}i qS r+   r+   )r4   _r+   r+   r,   r7   5  s     z.ufo)	UFOReader.getGlyphSetc                    s   i | ]}| | qS r+   r+   )r4   r   r3   r+   r,   r   O  s      c                    s   g | ]\}}| kr|qS r+   r+   )r4   r#   r)   accepted_namesr+   r,   r7   S  s   c                    s   g | ]\}}| kr|qS r+   r+   )r4   r#   r   r   r+   r,   r7   X  s   c                    s   g | ]}| kr|qS r+   r+   )r4   r#   r   r+   r,   r7   ]  s      c                 S   s   g | ]}|  D ]}|qqS r+   rP   )r4   r)   gnr+   r+   r,   r7   `  s     
  c                    s   g | ]}t | qS r+   )r   )r4   loc)axis_triplesr+   r,   r7   k  s     zRunning on %d glyphsetszLocations: %s)r   r   rH   rK   r   rI   rJ   rL   w)filezGlyph z was not compatible:rZ   r]   r^   rY   r[   r\   z  Masters: %s:z, rX   z"    Glyph was missing in master %sz'    Glyph has an open path in master %sz*    Path count differs: %i in %s, %i in %sr_   r`   z5    Node count differs in path %i: %i in %s, %i in %sra   z7    Node %o incompatible in path %i: %s in %s, %s in %srb   z-    Contour order differs: %s in %s, %s in %szD    Contour %d start point differs: %s in %s, %s in %s; reversed: %srB   rg   z3    Contour %d interpolation is underweight: %s, %sz2    Contour %d interpolation is overweight: %s, %sz'    Contour %d has a kink at %s: %s, %sr<   z    Showing %s and %s)psZpdfzWriting %s to %s)InterpolatablePSInterpolatablePDFr   )rT   r   )rI   rJ   zWriting HTML to %s)InterpolatableSVG)show_tolerancerI   rJ   )r   Zshow_page_numberwbs   <!DOCTYPE html>
sN   <html><body align="center" style="font-family: sans-serif; text-color: #222">
s6   <title>fonttools varLib.interpolatable report</title>
z
<h1>Glyph z</h1>
zutf-8z$<img src='data:image/svg+xml;base64,s   ' />
s   <hr>
s   </body></html>
)qargparsesysArgumentParsermain__doc__add_argumentfloatDEFAULT_TOLERANCEr~   str
parse_argsZ	fontToolsr   verboser{   r   splitos.pathr   DEFAULT_UPEMr   r   r.   endswithZfontTools.designspaceLibr   ZfromfilesourcesZaxesitemsZ	glyphsLibr   r   ZupmZfontTools.ttLibr   Z
unitsPerEmZminValuedefaultValueZmaxValueaxisTagsegmentscopyr   r   r   sortedZ
variationsrQ   r0   r   r   joinr   ZfontTools.ufoLibr   r   ZreadInforsplithasattrr#   setrl   rI   rJ   rj   rk   r   r   rL   rt   outputstdoutr   r   quietjsonprintdumpsrm   rn   ro   rp   rq   rr   rs   rw   rx   ry   r   r   Zsort_problemsr/   upperZinterpolatablePlotr   r   Zadd_title_pageZadd_summaryZadd_problemsZdraw_cupcakeZ	add_indexZadd_table_of_contentshtmlr   base64writer=   encode	b64encode	Exceptionr   error)Hr   r   r   parserr   r   r   Zfontsr   rH   rK   Zoriginal_args_inputsZdesignspacer   r   r   Zgsfontr   r   r   Zaxisr   r   r   ZfvarMappingr   r<   r   r   ZttGlyphSetsrT   r(   varZlocDictr   tagvalZlocTupler#   filenamer   rk   Z	glyphsSetZglyphSetGlyphNamesZdiffr   rI   rJ   Zproblems_genr   r   r	  r   Zlast_glyphnamepZlast_master_idxsZmaster_idxsZmaster_namesr6   r   r   ZPlotterClassdocr   ZsvgsZglyph_startssvgrA   Zglyph_problemsr  rS   rC   r+   )r   r   r   r   r)   r,   r   ^  s   










 

  
   






 






 





	


			
	

    







r   __main__)NNF)N)8r   ZinterpolatableHelpersZinterpolatableTestContourOrderr   ZinterpolatableTestStartingPointr   ZfontTools.pens.recordingPenr   r   r   ZfontTools.pens.transformPenr	   ZfontTools.pens.statisticsPenr
   r   ZfontTools.pens.momentsPenr   ZfontTools.varLib.modelsr   r   ZfontTools.misc.fixedToolsr   ZfontTools.misc.transformr   collectionsr   typesr   	functoolsr   pprintr   mathr   r   r   loggingr   	getLoggerrj   r   r~   r}   r   r   r   r   r   r   r   rE   r   r   exitintboolr+   r+   r+   r,   <module>   sb   
Z      J
	
    
