o
    l^UfP                     @   s|  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rddl3Z3e1 Z4e35e6e7e4 dS 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+   ?lib/python3.10/site-packages/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 u | _| jrd S tt|d}z	|j|dd W n ty,   || Y nw |j| _~t| jD ]\}}dd |jD }| j	
| t|d}t|d}z|| || | j
d W n ty }	 z| j
d | | W Y d }	~	q7d }	~	ww | j
| | j
| | j
t| | j
t| |d dkr| | q7|d d	ksJ |d
 dv sJ t }
t|
d}|| | j
|
j g }| j
| t|
j|d t|
j|d q7d S )Nr)   T)ZoutputImpliedClosingLinec                 S   s   g | ]\}}|qS r+   r+   ).0opargr+   r+   r,   
<listcomp>N       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   ZSimpleRecordingPointPenZSegmentToPointPenr    r   Zadd_isomorphisms)r'   r)   glyphZperContourPenr1   contourr   r   r   er    Z	converterr   r+   r+   r,   r&   ?   sZ   









zGlyph._populateNc                 C   s6   |d u r| j D ]}|| qd S | j | | d S r"   )r   r;   )r'   ZpenZcountor_idxrB   r+   r+   r,   r;   w   s
   
z
Glyph.drawr"   )__name__
__module____qualname__r$   r-   r2   r&   r;   r+   r+   r+   r,   r   '   s    8r   F)	locations	tolerance	kinkinessupemshow_allc          U      #   sB
   |dkr	|d9 }d|  krdksJ  J |dkr|d9 }d|ks%J |p-dd D }|d u r9dd D }t |\}	fd	d
}
|D ]ԉ td   fddD }tdd |D dkrgqItt||D ]6\}\}}}|jr|s tj||dfV  qod}t|j	D ]\}}|sqd} tj
|||dfV  q|rqoqod gt }|	D ]m}|| }|d u s|jsq|
| }|d u rq|| }|d u s|jsq|j|j}t|tkr tj|| || ||t|tdfV  q|kr`tt|D ]Z\}\}}||krqt|t|kr4 tj||| || ||t|t|dfV  qtt||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 urrfdd| D fdd| D fdd| D g }$t|#D ])\}%}&zt }'tt|%j|&j|'_|$|' W q ty   |$d  Y qw tt|!D ] \}\}(})|(d u s|)d u st|(dkst|(t|)krqt||||| \}}*}+||k rB tj||| || ||d|*|+|d
fV  |$| },|,r|"| d dk | d dk krtd d}-|,|- t|-}.|"| }/| }0|/d |/d  }1|0d |0d  }2|.d |.d  }3ttj tj!fD ]i\}4}5|4rt"|1|2}6qt#|1|2 }6t$d|5|3|6|1|2 |4s|6| |3d ks|4rd|6|  |3k rz|4r|6|3 }n|3|6 }W n t%y   d}Y nw t$d|  |5||| || |||dfV  qq|j&}|j&|| d urrfdd|| D d }7|t' t( | }8tt|D ]\}\}(})|(d u sI|)d u sIt|(dksIt|(t|)krKq(tt|(D ]}9|(|9 }:|)|9 };|:d rf|;d shqQ|(|9d  }<|)|9d  }=|(|9d t|(  }>|)|9d t|)  }?|<d r|=d rqQ|<d r|=d rqQt)|: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%y   Y qQw t,|D|7kst,|E|7krqQ|@j*|Aj* |@j+|Aj+  }F|Bj*|Cj* |Bj+|Cj+  }G|Fdk s@|Gdk rBqQt,|@t,|@t,|A  }Ht,|Bt,|Bt,|C  }It,|H|I }Jt,|J|7k riqQ|:|; d! }K|<|= d! }L|>|? d! }M|K|L }N|M|K }O|Nj*|Oj+ |Nj+|Oj*  }Pz|Pt,|Nt,|O  }PW n t%y   Y qQw t,|P||  |7krqQ|Pt,|N t,|O }Qt,|N|O }Rt,|Q|R }S|S|8k rѐqQ|S|R }T|T|7krܐqQ|7t,|P|  }t$d"|S|T|P|J t$d|  tj-||| || |||9|d#fV  qQq(|r tj.|| || ||d$fV  qqId S )%N
   g{Gz?r   r   c                 S   s   g | ]}t |qS r+   )repr)r4   gr+   r+   r,   r7      r8   ztest_gen.<locals>.<listcomp>c                 S   s   h | ]}|  D ]}|qqS r+   keys)r4   r)   rN   r+   r+   r,   	<setcomp>       ztest_gen.<locals>.<setcomp>c                    sd   | d u rd S |  } | d u rd S |  d ur0 |  | d u r0|  } |  d ur0 |  | d u s| 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          c                 S   s   g | ]}|d urdqS )Nr   r+   )r4   rA   r+   r+   r,   r7          )typemaster
master_idxFT)rZ   r[   r\   rB   )rZ   master_1master_2master_1_idxmaster_2_idxvalue_1value_2)rZ   pathr]   r^   r_   r`   ra   rb   )	rZ   rc   noder]   r^   r_   r`   ra   rb   )rZ   r]   r^   r_   r`   ra   rb   rH   c                       g | ]} | qS r+   r+   r4   rS   )m1Isomorphismsr+   r,   r7   6  r8   c                    re   r+   r+   rf   )	m1Vectorsr+   r,   r7   7  r8   c                    re   r+   r+   rf   )
recording1r+   r,   r7   8  r8   )
rZ   rB   r]   r^   r_   r`   ra   rb   reversedrH   r3   z;%s: actual size %g; threshold size %g, master sizes: %g, %ggh㈵>ztolerance %g)rZ   rB   r]   r^   r_   r`   rH   c                    re   r+   r+   rf   )m1r+   r,   r7     r8   g?   z=kink: deviation %g; deviation_ratio %g; sin_mid %g; r_diff %g)rZ   rB   r]   r^   r_   r`   r=   rH   )rZ   r]   r^   r_   r`   )/Zfind_parents_and_orderloginfor.   r>   zipr:   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_missingrG   rH   rI   rJ   rK   ZorderrV   Z	allGlyphsr\   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   rk   rg   rh   rU   ri   r,   test_gen   s  


	










(









t  r   c                  O   s2   t t}t| i |D ]\}}|| | q|S r"   )r   rw   r   r0   )argskwargsproblemsr(   problemr+   r+   r,   testF  s   r   c                 C   sB   | |v rd S ||  || < t ||  dg D ]
}t|j||| qd S )NZ
components)r/   recursivelyAddGlyphZ	glyphName)r(   r)   Z
ttGlyphSetglyfZ	componentr+   r+   r,   r   N  s   r   c                 C   s"   t j| }|rt j|dd | S )NT)exist_ok)osrc   dirnamemakedirs)rc   r   r+   r+   r,   ensure_parent_dirW  s   r   c           I         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rd/nd0d1 | jr|d2d1 | jr| j nd}dd3lm} g }g }g }	t}
t| j}t| jd4krd}| 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>rrd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 n5| jd dFrddGl"m#} || jd }|dH j$}
dI|v r|dJ }i |jD ]}|j%|j&|j'dK|j(< qdL}dM|v r|dM }t)|j*dNdrdOd; D dP}n$|j+ D ]\}}| , }| D ]\}}t-||| |< qېq|dI }|dQ }i }t.t/}|du rt0|j12 }|D ]J} |j1|  D ]A}!i }"g }#t0|!j D ]\}$}%|%d4 |"|$< |#3|$|%d4 f qt|#}&|&|vrD|j4|"dPdLdR||&< t5| ||& ||& | qqdSg}|4 g}i g}	dTd; t02 D t0|2 dUdV dWD ]-}&dXdY6fdZd[|&D  dX }'|r|'d\7 }'|3|' |3||&  |	3t/|& qsdP| _7g | _|	sd]d8 |D }	| jD ]E}(|(d^rdd_l8m9}) |)|(}t: }*|;|* |*j$}
|3| nddGl"m#} ||(}|dH j$}
|3| |3||(<d`d4d  qg }|D ]}t=|dar|4 n||3fdbd;2 D  q| j>rGt?| j>  fdcd8t@||D } fddd8t@||	D }	 fded8|D }|sUt0t?dfd8 |D }t?|}+|D ]t?2 },|+|, }-|-rt|-D ]}.d|.< qlq[fdgd8|	D }	| jApt}/| jBdur| jBnt}0z4tCDdht| tCDditE|	 tF||||	|
| j7|/|0| jGdj	}1t.tH}2| jIdu r|jJntKtL| jIdk}3| jMs}| jNrddlN}4|1D ]\} }5|2|  3|5 qtO|4P|2|3dl nd}6|1D ]\} }7|2|  3|7 | |6krtOdm|  dn|3dl | }6d}8do|7v r|7do n|7dp |7dq f}9|9|8krCdr|7v r.|7dr n|7ds |7dt f}:tOdudv6|: |3dl |9}8|7dw tQjRkrWtOdx|7dr  |3dl q|7dw tQjSkrktOdy|7dr  |3dl q|7dw tQjTkrtOdz|7d{ |7ds |7d| |7dt f |3dl q|7dw tQjUkrtOd}|7d~ |7d{ |7ds |7d| |7dt f |3dl q|7dw tQjVkrtOd|7d |7d~ |7d{ |7ds |7d| |7dt f |3dl q|7dw tQjWkrtOd|7d{ |7ds |7d| |7dt f |3dl q|7dw tQjXkrtOd|7d |7d{ |7ds |7d| |7dt |7d f |3dl q|7dw tQjYkr+tOd|7d |7ds |7dt f |3dl q|7dw tQjZkrFtOd|7d |7ds |7dt f |3dl q|7dw tQj[krdtOd|7d |7d |7ds |7dt f |3dl q|7dw tQj\krztOd|7ds |7dt f |3dl qn|1D ]\} }5|2|  3|5 qt]|2}2dD ]n}7t)| |7};|;du rqtCDd|7^ |; d4dl_m`}<ma}= |7dkr|<n|=}>|>tL|;||d3}?|?jb||/|0d |2r|?c|2 |?d|2 |2s| jMs|?e  |2r|?f  |?g  W d   n	1 sw   Y  q| jhrtCDd| jh d4dl_mi}@ g }Ai }B|@|A||d6}C|Cjb|dL|/|0d |2 D ]\}D}E|D|Bt|A< |Cjd|D|EidLdLd q+|2sL| jMsL|Ce  W d   n	1 sWw   Y  ddlj}FtKtL| jhdS}3|3kd |3kd |3kd tl|AD ]2\}G}C|G|Bv r|3kd|B|G  dmd |3kdmd |3k|Fn|C |3kd |3kd q||3kd W d   n	1 sw   Y  W n toy }H z|H jp|7  _ptCq|H  d}H~Hww |2r|2S 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   rZ   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inputsZFILE+zSInput a single variable font / DesignSpace / Glyphs file, or multiple TTF/UFO files)metavarrZ   nargsr   z--nameNAMEr0   zGName of the master to use in the report. If not provided, all are used.)r   rZ   r   r   z-vz	--verbosezRun verbosely.z--debugzRun with debug output.)configLoggerINFOZERROR)levelDEBUG)basenamer   z.designspace)DesignSpaceDocumentc                 S      g | ]}|j qS r+   )rc   r4   r[   r+   r+   r,   r7         zmain.<locals>.<listcomp>c                 S   r   r+   locationr   r+   r+   r,   r7     r   c                 S       i | ]}|j |j|j|jfqS r+   r#   ZminimumdefaultZmaximumr4   ar+   r+   r,   
<dictcomp>      zmain.<locals>.<dictcomp>c                 S      i | ]}|j |jqS r+   r#   mapr   r+   r+   r,   r     rX   c                    *   i | ]\ } t  fd d|D qS )c                 3   "    | ]}t |t  V  qd S r"   r   dictr4   vaxis_mappingskr+   r,   	<genexpr>       "main.<locals>.<dictcomp>.<genexpr>tupler4   Zvvr   r   r,   r         )z.glyphsz.glyphspackage)GSFontto_designspacec                 S   r   r+   )font)r4   sourcer+   r+   r,   r7     r   c                 S   s    g | ]}d |j j|j jf qS )z%s-%s)rn   Z
familyNameZ	styleName)r4   fr+   r+   r,   r7     s     c                 S   r   r+   r   r   r+   r+   r,   r7     r   c                 S   r   r+   r   r   r+   r+   r,   r     r   c                 S   r   r+   r   r   r+   r+   r,   r     rX   c                    r   )c                 3   r   r"   r   r   r   r+   r,   r     r   r   r   r   r   r   r,   r     r   z.ttf)TTFontheadgvarfvarr9   r   r   FavarZVarStorec                 S   s   i | ]	}|d dddqS )r9   r   r   r   r+   )r4   tagr+   r+   r,   r     s    Tr   )r   
normalizedZrecalcBoundsz''c                 S   s   i | ]}|d qS )r   r+   r   r+   r+   r,   r   #  r   c                 S   s   t | | fS r"   )r.   )r   r+   r+   r,   <lambda>$  s    zmain.<locals>.<lambda>)key' c                 3   s0    | ]\}}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>z (normalized)c                 S   s   g | ]}i qS r+   r+   )r4   _r+   r+   r,   r7   <  s    z.ufo)	UFOReader.getGlyphSetc                    s   i | ]}| | qS r+   r+   )r4   r   r3   r+   r,   r   V  rX   c                       g | ]
\}}| v r|qS r+   r+   )r4   r#   r)   accepted_namesr+   r,   r7   Z  
    c                    r   r+   r+   )r4   r#   r   r   r+   r,   r7   _  r   c                    s   g | ]}| v r|qS r+   r+   )r4   r#   r   r+   r,   r7   d  rY   c                 S   s   g | ]}|  D ]}|qqS r+   rO   )r4   r)   gnr+   r+   r,   r7   g  rR   c                    s   g | ]}t | qS r+   )r   )r4   loc)axis_triplesr+   r,   r7   r  rX   zRunning on %d glyphsetszLocations: %s)r   r   rG   rJ   r   rH   rI   rK   w)filezGlyph z was not compatible:r\   r_   r`   r[   r]   r^   z  Masters: %s:z, rZ   z"    Glyph was missing in master %sz'    Glyph has an open path in master %sz*    Path count differs: %i in %s, %i in %sra   rb   z5    Node count differs in path %i: %i in %s, %i in %src   z7    Node %o incompatible in path %i: %s in %s, %s in %srd   z-    Contour order differs: %s in %s, %s in %szD    Contour %d start point differs: %s in %s, %s in %s; reversed: %srB   rj   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   )rH   rI   zWriting HTML to %s)InterpolatableSVG)show_tolerancerH   rI   )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>
)r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fromfileZsourcesZaxesitemsZ	glyphsLibr   r   ZupmZfontTools.ttLibr   Z
unitsPerEmZminValueZdefaultValueZmaxValueaxisTagr/   tablesegmentscopyr   r   r   sortedZ
variationsrP   r0   r   r   joinr   ZfontTools.ufoLibr   r   ZreadInforsplithasattrr#   setro   rH   rI   rm   rn   r   r   rK   rw   outputstdoutr   r   quietjsonprintdumpsrp   rq   rr   rs   rt   ru   rv   rz   r{   r|   r   r   Zsort_problemsupperZinterpolatablePlotr   r   Zadd_title_pageZadd_summaryZadd_problemsZdraw_cupcakeZ	add_indexZadd_table_of_contentsZhtmlr   base64writer>   encodeZ	b64encode	Exceptionr   error)Ir   r   r   parserr   r   r   Zfontsr   rG   rJ   Zoriginal_args_inputsZdesignspacer   r   r   Zgsfontr   r   r   Zaxisr   r   r  r  ZfvarMappingr   r=   r   r   ZttGlyphSetsrT   r(   varZlocDictr   r   valZlocTupler#   filenamer   rn   Z	glyphsSetZglyphSetGlyphNamesZdiffr   rH   rI   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_startsZsvgrA   Zglyph_problemsr  rS   rC   r+   )r   r   r   r   r)   r,   r   ^  s  




















 












	


	

	
	

 










r   __main__)NNFr"   )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   Zpprintr   Zmathr   r   r   Zloggingr   Z	getLoggerrm   r   r   r   r   r   r   r   r   r   r   rD   r   r   exitintboolr+   r+   r+   r,   <module>   sf    
Z   J
	
    