U
    Dvf                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ G dd de	Z
eddfd	d
Zdd Zdd Zdd ZdddZedkrddlZeejdkrddlZee j e  dS )aF  T2CharString glyph width optimizer.

CFF glyphs whose width equals the CFF Private dictionary's ``defaultWidthX``
value do not need to specify their width in their charstring, saving bytes.
This module determines the optimum ``defaultWidthX`` and ``nominalWidthX``
values for a font, when provided with a list of glyph widths.    )TTFont)defaultdict)add)reducec                   @   s   e Zd Zdd Zdd ZdS )missingdictc                 C   s
   || _ d S Nmissing_func)selfr	    r   :/tmp/pip-unpacked-wheel-qlge9rch/fontTools/cffLib/width.py__init__   s    zmissingdict.__init__c                 C   s
   |  |S r   r   )r
   vr   r   r   __missing__   s    zmissingdict.__missing__N)__name__
__module____qualname__r   r   r   r   r   r   r      s   r   Fc           
         s   t |  }|d |d   t||  |rT fdd}t d d}nfdd}t d }t|}}|D ]}	||| |	 }|||	< q|S )Nr   c                    s   |  krS S r   r   x)maxxstarttotalr   r   <lambda>       zcumSum.<locals>.<lambda>   c                    s   |  k rS S r   r   r   )minxr   r   r   r   r   "   r   )sortedkeysr   valuesranger   )
fopr   
decreasingr   missingdomainoutr   r   r   )r   r   r   r   r   cumSum   s    
r'   c                 C   s   t | ds0tt}| D ]}||  d7  < q|} d}|  D ]R\}}||krNq<t|| }|dkrl||7 }q<|dkr||d 7 }q<||d 7 }q<|S )Nitemsr   r   k   ik        )hasattrr   intr(   abs)widthsdefaultnominaldwcostfreqZdiffr   r   r   byteCost/   s     

r6   c                    s   t t} D ]}||  d7  < qdt|  }t t  }}tt||d }t fdd|D }t d d }|D ]D}	t d|	|| krq|D ]$}
t |
|	}||k r|}|
}|	}qq||fS )zSBruteforce version.  Veeeeeeeeeeeeeeeeery slow.  Only works for smallests of fonts.r   r+   c                 3   s   | ]}t  d |V  qd S r   r6   ).0r1   r/   r   r   	<genexpr>Q   s     z+optimizeWidthsBruteforce.<locals>.<genexpr>N)	r   r-   maxr   minlistr    lenr6   )r/   r2   r3   ZmaxDefaultAdvantageminwmaxwr%   ZbestCostWithoutDefaultbestCostr1   r0   r4   ZbestDefaultZbestNominalr   r9   r   optimizeWidthsBruteforceD   s$    rB   c                    s  t ds0tt}D ]}||  d7  < q|t }|d |d  }}tt||d }ttdtt	dttddtt	ddt
fdd	t
fd
d	
t

fdd		t
fdd	t
fdd	t
fdd	t
	fdd	 t| fdd	d  }	    }g }	| krd d g}
|
D ]<}| r| |d  kr|d8 }qd|	| q`nTd d g}
|
D ]<}| r| |d  kr|d7 }q|	| qt|	fdd	d}|fS )zGiven a list of glyph widths, or dictionary mapping glyph width to number of
    glyphs having that, returns a tuple of best CFF default and nominal glyph widths.

    This algorithm is linear in UPEM+numGlyphs.r(   r   r   r   )r"   T)r"   r#   c                    s$    |   | d    | d  d  S Nl   l     r   r   )cumFrqUr   r   r   y   r   z optimizeWidths.<locals>.<lambda>c                    s$    |   | d    | d  d  S rC   r   r   )cumFrqDr   r   r   |   r   c                    s   |   |   |   S r   r   r   )	nomnCostD	nomnCostUr/   r   r   r   ~   r   c                    s(   t  |   | d  d  | d  d S NrD   r*   rE   r+   r;   r   )cumMaxUr   r   r      r   c                    s(   t  |   | d  d  | d  d S rK   rL   r   )cumMaxDr   r   r      r   c                    s   t |   |  S r   rL   r   )	dfltCostD	dfltCostUr   r   r      r   c                    s   |   |   S r   r   r   )dfltCostnomnCostr   r   r      r   c                    s    |  S r   r   r   )rA   r   r   r      r   )keyrD   rE   c                    s   t |  S r   r7   )r0   )r1   r/   r   r   r      r   )r,   r   r-   r   r   r=   r    r'   r   r;   r   r<   append)r/   r2   r3   r   r?   r@   r%   ZbestCZdfltCZendsZstartsr   r0   r   )rA   rH   rG   rN   rM   rQ   rO   rP   r1   rR   rI   rJ   r/   r   optimizeWidthsa   sX    




  rU   Nc           	   
   C   s   ddl }|jdtjd}|jddtddd	 |jd
ddddd || } | jD ]h}t|}|d }dd |j	
 D }| jrt|\}}nt|\}}tdt|||t|||f  qPdS )z4Calculate optimum defaultWidthX/nominalWidthX valuesr   Nzfonttools cffLib.width)descriptioninputsFILE+zInput TTF files)metavartypenargshelpz-bz--brute-forcebrute
store_truez$Use brute-force approach (VERY slow))destactionr]   hmtxc                 S   s   g | ]}|d  qS )r   r   )r8   mr   r   r   
<listcomp>   s     zmain.<locals>.<listcomp>z+glyphs=%d default=%d nominal=%d byteCost=%d)argparseArgumentParsermain__doc__add_argumentstr
parse_argsrW   r   Zmetricsr   r^   rB   rU   printr>   r6   )	argsre   parserZfontfilefontrb   r/   r0   r1   r   r   r   rg      s@        

rg   __main__r   )N)rh   ZfontTools.ttLibr   collectionsr   operatorr   	functoolsr   dictr   r'   r6   rB   rU   rg   r   sysr>   argvdoctestexittestmodfailedr   r   r   r   <module>   s    C
$