B
    Sce                 @   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	   5lib/python3.7/site-packages/fontTools/cffLib/width.py__init__   s    zmissingdict.__init__c             C   s
   |  |S )N)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|}}x"|D ]}	||| |	 }|||	< qW |S )Nr   c                s   |  krS S )Nr	   )x)maxxstarttotalr	   r
   <lambda>       zcumSum.<locals>.<lambda>   c                s   |  k rS S )Nr	   )r   )minxr   r   r	   r
   r   !   r   )sortedkeysr   valuesranger   )
fopr   
decreasingr   Zmissingdomainoutr   r   r	   )r   r   r   r   r
   cumSum   s    
r#   c             C   s   t | ds4tt}x| D ]}||  d7  < qW |} d}x^|  D ]R\}}||krTqBt|| }|dkrr||7 }qB|dkr||d 7 }qB||d 7 }qBW |S )Nitemsr   r   k   ik        )hasattrr   intr$   abs)widthsdefaultnominaldwcostZfreqZdiffr	   r	   r
   byteCost-   s     

 
r1   c                s   t t}x D ]}||  d7  < qW dt|  }t t  }}tt||d }t fdd|D }t d d }xP|D ]H}	t d|	|| krqx,|D ]$}
t |
|	}||k r|}|
}|	}qW qW ||fS )zSBruteforce version.  Veeeeeeeeeeeeeeeeery slow.  Only works for smallests of fonts.r   r'   c             3   s   | ]}t  d |V  qd S )N)r1   ).0r-   )r+   r	   r
   	<genexpr>O   s    z+optimizeWidthsBruteforce.<locals>.<genexpr>N)	r   r)   maxr   minlistr   lenr1   )r+   r.   r/   ZmaxDefaultAdvantageminwmaxwr!   ZbestCostWithoutDefaultbestCostr-   r,   r0   ZbestDefaultZbestNominalr	   )r+   r
   optimizeWidthsBruteforceB   s$    


r;   c                s&  t ds4tt}xD ]}||  d7  < qW |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}
x|
D ]@}x.| r| |d  kr|d8 }qlW |	| qfW n\d d g}
xH|
D ]@}x.| r| |d  kr|d7 }qW |	| qW t|	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   il     r	   )r   )cumFrqUr	   r
   r   v   r   z optimizeWidths.<locals>.<lambda>c                s$    |   | d    | d  d  S )Nr<   il  r=   r	   )r   )cumFrqDr	   r
   r   w   r   c                s   |   |   |   S )Nr	   )r   )	nomnCostD	nomnCostUr+   r	   r
   r   x   r   c                s(   t  |   | d  d  | d  d S )Nr<   r&   il  r'   )r4   )r   )cumMaxUr	   r
   r   {   r   c                s(   t  |   | d  d  | d  d S )Nr<   r&   il  r'   )r4   )r   )cumMaxDr	   r
   r   |   r   c                s   t |   |  S )N)r4   )r   )	dfltCostD	dfltCostUr	   r
   r   }   r   c                s   |   |   S )Nr	   )r   )dfltCostnomnCostr	   r
   r      r   c                s    |  S )Nr	   )r   )r:   r	   r
   r      r   )keyr<   il  c                s   t |  S )N)r1   )r,   )r-   r+   r	   r
   r      r   )r(   r   r)   r   r   r6   r   r#   r   r4   r   r5   append)r+   r.   r/   r   r8   r9   r!   ZbestCZdfltCZendsZstartsr   r,   r	   )r:   r?   r>   rC   rB   rF   rD   rE   r-   rG   r@   rA   r+   r
   optimizeWidths_   sH    


"
"rJ   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 || } xr| jD ]h}t|}|d }dd |j	
 D }| jrt|\}}nt|\}}tdt|||t|||f  qRW dS )z4Calculate optimum defaultWidthX/nominalWidthX valuesr   Nzfonttools cffLib.width)ZdescriptioninputsZFILE+zInput TTF files)metavartypenargshelpz-bz--brute-forcebrute
store_truez$Use brute-force approach (VERY slow))destactionrP   hmtxc             S   s   g | ]}|d  qS )r   r	   )r2   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_argsrK   r   Zmetricsr   rQ   r;   rJ   printr7   r1   )	argsrX   parserZfontfileZfontrU   r+   r,   r-   r	   r	   r
   rZ      s"    

rZ   __main__r   )N)r[   ZfontTools.ttLibr   collectionsr   operatorr   	functoolsr   dictr   r#   r1   r;   rJ   rZ   r   sysr7   argvZdoctestexitZtestmodZfailedr	   r	   r	   r
   <module>   s    :
