U
    #vhD1                  	   @   sH  d Z ddlZddlZddlmZmZ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mZ dd
lmZ ddlmZ ddlZdgZG dd deZedZeeejf Z ee ej!dddZ"ej#e dddZ$ej%e e&dddZ'ej!ej%dddZ(ej!eedddZ)efej!ee*ge*f ej!dd d!Z+ed"ej!eee*ge*f ej!d#d$d%Z,ej!ej!e&d&d'd(Z-d=ee ej.ej/e&e&d*d+d,Z0ej1ee e e&e&dd-d.d/Z2ee e	e&d0d1d2Z3d)d3ej1ee e e&e&e&dd4d5d6Z4d>d)d3ej1eee  e&e&e&dd8d9dZ5d?d:d;Z6e7d<krDe6  dS )@zz Simplify TrueType glyphs by merging overlapping contours/components.

Requires https://github.com/fonttools/skia-pathops
    N)CallableIterableOptionalMapping)
CFFFontSet)ttFont)_g_l_y_f)_h_m_t_x)T2CharString)otRoundnoRound)
TTGlyphPen)T2CharStringPenremoveOverlapsc                   @   s   e Zd ZdS )RemoveOverlapsErrorN)__name__
__module____qualname__ r   r   B/tmp/pip-unpacked-wheel-1ufboor8/fontTools/ttLib/removeOverlaps.pyr      s   r   zfontTools.ttLib.removeOverlaps)	glyphNameglyphSetreturnc                 C   s&   t  }|j|d}||  | |S )Nr   )pathopsPathZgetPendraw)r   r   pathZpathPenr   r   r   skPathFromGlyph"   s    r   )	componentr   c                 C   s    |   \}}t||}|j| S N)ZgetComponentInfor   Z	transform)r   r   ZbaseGlyphNameZtransformationr   r   r   r   skPathFromGlyphComponent)   s    
r!   )glyphr   r   c                    sh     stdtjdk r"dS i ttjdfdd t fddt	t
tjdD S )	Nz5This method only works with TrueType composite glyphs   F)indexr   c                    s$   |  krt j|   | <  |  S r    )r!   
components)r$   )component_pathsr"   r   r   r   _get_nth_component_path9   s     z2componentsOverlap.<locals>._get_nth_component_pathc                 3   s2   | ]*\}}t j | |t jjd d dV  qdS )F)Zfix_windingZkeep_starting_pointsN)r   opZPathOpZINTERSECTION).0ij)r'   r   r   	<genexpr>@   s   z$componentsOverlap.<locals>.<genexpr>)isComposite
ValueErrorlenr%   intr   r   any	itertoolscombinationsrange)r"   r   r   )r'   r&   r"   r   r   componentsOverlap1   s    r5   )r   r   c                 C   s8   t d d}| | | }| r(t|jd d |S )Nr   	glyfTable)r   r   r"   r-   AssertionErrorZrecalcBounds)r   ZttPenr"   r   r   r   ttfGlyphFromSkPathL   s    

r9   )r   
charStringr   c                 C   sH   |j |jjkrd }n|j |jj }t|d d}| | ||j|jS )N)widthr   )r;   privateZdefaultWidthXZnominalWidthXr   r   ZgetCharStringZglobalSubrs)r   r:   r;   Zt2Penr   r   r   _charString_from_SkPathW   s    
r=   )r   roundr   c                    s8   t  }| D ]&\}}|j|f fdd|D   q|S )Nc                 3   s&   | ]} |d   |d fV  qdS )r      Nr   )r)   pr>   r   r   r,   h   s     z_round_path.<locals>.<genexpr>)r   r   add)r   r>   Zrounded_pathZverbZpointsr   rA   r   _round_pathc   s     rC   rA   )r   debugGlyphNamer>   r   c             
   C   s   zt j| | jdW S  t jk
r(   Y nX t| |d} z"t j| | jd} td| | W S  t jk
r } z(ttj	r| 
  td||W 5 d }~X Y nX tdd S )N)	clockwiserA   zkskia-pathops failed to simplify '%s' with float coordinates, but succeded using rounded integer coordinatesz%Failed to remove overlaps from glyph ZUnreachable)r   ZsimplifyrE   ZPathOpsErrorrC   logdebugisEnabledForloggingDEBUGdumpr   r8   )r   rD   r>   er   r   r   	_simplifyl   s*    rM   )path1path2r   c                 C   s    dd | j D dd |j D kS )Nc                 S   s   h | ]}t |qS r   )tuple)r)   cr   r   r   	<setcomp>   s     z_same_path.<locals>.<setcomp>)Zcontours)rN   rO   r   r   r   
_same_path   s    rS   T)r   r   r7   	hmtxTableremoveHintingr   c           
      C   s   ||  }|j dks$| rt||rt| |}t|| }t||st| || < }|jr\t||  \}}	|	|j	kr||j	f|| < dS |r|
  dS )Nr   TF)ZnumberOfContoursr-   r5   r   rM   rS   r9   programr8   ZxMinrU   )
r   r   r7   rT   rU   r"   r   rO   r;   Zlsbr   r   r   removeTTGlyphOverlaps   s&    




rW   )font
glyphNamesr   rU   ignoreErrorsr   c              	      s   | d  | d }t | fddd}t }|D ]J}zt|| ||rN|| W q. tk
rv   |sf td| Y q.X q.tdt|d	| d S )	NglyfZhmtxc                    s$    |    r |   jnd| fS )Nr   )r-   ZgetCompositeMaxpValuesZmaxComponentDepth)namer6   r   r   <lambda>   s
    
z'_remove_glyf_overlaps.<locals>.<lambda>)key"Failed to remove overlaps for '%s'"Removed overlaps for %s glyphs:
%s )
sortedsetrW   rB   r   rF   errorrG   r/   join)rX   rY   r   rU   rZ   rT   modifiedr   r   r6   r   _remove_glyf_overlaps   s,    
    rg   )r   r   
cffFontSetr   c                 C   sF   t | |}t|| td}t||sB|d j}t|||  || < dS dS )NrA   r   TF)r   rM   r   rS   ZCharStringsr=   )r   r   rh   r   rO   ZcharStringsr   r   r   _remove_charstring_overlaps   s    


ri   )removeUnusedSubroutines)rX   rY   r   rU   rZ   rj   r   c           	   	   C   s   | d j }t }|D ]H}zt|||dr2|| W q tk
rZ   |sJ td| Y qX q|sptd d S |r||  |r|	  tdt
|d| d S )NCFF )r   r   rh   r_   z-No overlaps found in the specified CFF glyphsr`   ra   )Zcffrc   ri   rB   r   rF   rd   rG   Zremove_hintsZremove_unused_subroutinesr/   re   )	rX   rY   r   rU   rZ   rj   rh   rf   r   r   r   r   _remove_cff_overlaps   s,    	

rl   F)rX   rY   rU   rZ   rj   r   c                C   sj   d| krd| krt d|dkr(|  }|  }d| krJt| ||||d d| krft| |||||d dS )a  Simplify glyphs in TTFont by merging overlapping contours.

    Overlapping components are first decomposed to simple contours, then merged.

    Currently this only works for fonts with 'glyf' or 'CFF ' tables.
    Raises NotImplementedError if 'glyf' or 'CFF ' tables are absent.

    Note that removing overlaps invalidates the hinting. By default we drop hinting
    from all glyphs whether or not overlaps are removed from a given one, as it would
    look weird if only some glyphs are left (un)hinted.

    Args:
        font: input TTFont object, modified in place.
        glyphNames: optional iterable of glyph names (str) to remove overlaps from.
            By default, all glyphs in the font are processed.
        removeHinting (bool): set to False to keep hinting for unmodified glyphs.
        ignoreErrors (bool): set to True to ignore errors while removing overlaps,
            thus keeping the tricky glyphs unchanged (fonttools/fonttools#2363).
        removeUnusedSubroutines (bool): set to False to keep unused subroutines
            in CFF table after removing overlaps. Default is to remove them if
            any glyphs are modified.
    r[   rk   zANo outline data found in the font: missing 'glyf' or 'CFF ' tableN)rX   rY   r   rU   rZ   )rX   rY   r   rU   rZ   rj   )NotImplementedErrorZgetGlyphOrderZgetGlyphSetrg   rl   )rX   rY   rU   rZ   rj   r   r   r   r   r     s0    c              	   C   s   ddl }|jdtd}|jdddd |jd	d
dd |jddddd |jdddd |jdddd |jdddd || } t| j4}t|| j	pd| j
 | j| j d || j W 5 Q R X dS )z:Simplify glyphs in TTFont by merging overlapping contours.r   Nzfonttools ttLib.removeOverlaps)descriptioninputz	INPUT.ttfzInput font file)metavarhelpoutputz
OUTPUT.ttfzOutput font fileglyphsZGLYPHS*z4Optional list of glyph names to remove overlaps from)rp   nargsrq   z--keep-hinting
store_truez>Keep hinting for unmodified glyphs, default is to drop hinting)actionrq   z--ignore-errorszOignore errors while removing overlaps, thus keeping the tricky glyphs unchangedz--keep-unused-subroutineszrKeep unused subroutines in CFF table after removing overlaps, default is to remove them if any glyphs are modified)rX   rY   rU   rZ   rj   )argparseArgumentParser__doc__add_argument
parse_argsr   TTFontro   r   rs   Zkeep_hintingignore_errorsZkeep_unused_subroutinessaverr   )argsrx   parserrX   r   r   r   mainY  sL     
r   __main__)T)NTF)N)8rz   r2   rI   typingr   r   r   r   ZfontTools.cffLibr   ZfontTools.ttLibr   ZfontTools.ttLib.tablesr   r	   ZfontTools.misc.psCharStringsr
   ZfontTools.misc.roundToolsr   r   ZfontTools.pens.ttGlyphPenr   ZfontTools.pens.t2CharStringPenr   r   __all__	Exceptionr   	getLoggerrF   strZ_TTGlyphZ_TTGlyphMappingr   r   ZGlyphComponentr!   ZGlyphboolr5   r9   r=   floatrC   rM   rS   Ztable__g_l_y_fZtable__h_m_t_xrW   r}   rg   ri   rl   r   r   r   r   r   r   r   <module>   s   
   '	 %*'   
>
/
