o
    aA                     @   s  d dl mZmZ d dlmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlmZ d dlmZ dd ZG d	d
 d
eZedddZeej_dd Zeej_G dd deZdde fddZeej_dd Z e ej_!dd Z"dd Z#dd Z$e$ej%_&e$ej'_&dd Z(d d! Z)e)ej%_*e)ej'_*G d"d# d#eZ+G d$d% d%e,Z-d&d' Z.e.ej_/d-d)d*Z0e1d+krd d(l2Z2e3e2j4d,kre25e0  d d(l6Z6e25e67 j8 d(S d(S ).    )noRoundotRound)otTables)supportScalar)buildVarRegionListbuildVarStorebuildVarRegionbuildVarData)partial)defaultdictc                 C   s   t t|  dd dS )Nc                 S   s   | d S Nr    )Zkvr   r   ;/usr/lib/python3/dist-packages/fontTools/varLib/varStore.py<lambda>   s    z!_getLocationKey.<locals>.<lambda>key)tuplesorteditems)locr   r   r   _getLocationKey
   s   r   c                   @   sL   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Ze	dddZ
dS )OnlineVarStoreBuilderc                 C   sN   || _ i | _tg || _t| jg | _d | _d | _d | _i | _	i | _
i | _d S N)	_axisTags
_regionMapr   _regionListr   _store_data_model	_supports_varDataIndices_varDataCaches_cache)selfZaxisTagsr   r   r   __init__   s   
zOnlineVarStoreBuilder.__init__c                 C   s   |  |j || _d S r   )setSupportssupportsr   )r#   Zmodelr   r   r   setModel   s   
zOnlineVarStoreBuilder.setModelc                 C   s2   d | _ t|| _| jd s| jd= i | _d | _d S r   )r   listr   r"   r   )r#   r&   r   r   r   r%       s   


z!OnlineVarStoreBuilder.setSupportsTc                 C   sL   t | jj| j_t | jj| j_| jjD ]}t |j|_|j	|d q| jS )Noptimize)
lenr   RegionRegionCountr   VarDataVarDataCountItem	ItemCountcalculateNumShorts)r#   r*   datar   r   r   finish(   s   zOnlineVarStoreBuilder.finishc           
      C   s(  | j }| j}| j}g }|D ])}t|}||}|d u r1t|| j}t|j }||< |j	| |	| qt
|}| j|}	|	d ur_|	| _| jj|	 | _| j| | _t| jjdkr_d }	|	d u rt|g dd| _t| jj| _| jj	| j | j| j|< || jvri | j|< | j| | _d S d S )N  Fr)   )r   r   r   r   getr   r   r+   r,   appendr   r    _outerr   r.   r   r!   r"   r0   r	   )
r#   	regionMap
regionListregionsregionIndicesZregionr   idxZ	varRegionZ
varDataIdxr   r   r   _add_VarData0   s:   


z"OnlineVarStoreBuilder._add_VarDatac                 C   s,   | j j|td}|d}|| j|tdfS )Nroundr   )r   Z	getDeltasr@   popstoreDeltasr   )r#   Zmaster_valuesdeltasbaser   r   r   storeMastersT   s   
z"OnlineVarStoreBuilder.storeMastersr?   c                   s    fdd|D }t |t | jd krt|dd  }nt |t | jks(J t|}| j|}|d ur8|S | js?|   t | jj}|dkrR|   | |S | jj	|t
d | jd> | }|| j|< |S )Nc                       g | ]} |qS r   r   .0dr?   r   r   
<listcomp>Z       z5OnlineVarStoreBuilder.storeDeltas.<locals>.<listcomp>   r5   r?      )r+   r   r   r"   r6   r   r>   r0   rB   addItemr   r8   )r#   rC   r@   varIdxinnerr   r?   r   rB   Y   s$   

z!OnlineVarStoreBuilder.storeDeltasN)T)__name__
__module____qualname__r$   r'   r%   r4   r>   rE   r@   rB   r   r   r   r   r      s    
$r   r?   c                   sz    fdd|D }| j }t|}|d |krt|dd  }n||ks)J ||ft|}| jt| t| j| _d S )Nc                    rF   r   r   rG   r?   r   r   rJ   s   rK   z#VarData_addItem.<locals>.<listcomp>rL   )VarRegionCountr+   r   r0   r7   r(   r1   )r#   rC   r@   ZcountUsZ	countThemr   r?   r   VarData_addItemr   s   rU   c                    s    fddt | jD S )Nc                    s2   i | ]\}}|j d kr | j|j|j |jfqS )r   )Z	PeakCoordZaxisTagZ
StartCoordZEndCoord)rH   iZreg	fvar_axesr   r   
<dictcomp>   s    z)VarRegion_get_support.<locals>.<dictcomp>)	enumerateZVarRegionAxis)r#   rX   r   rW   r   VarRegion_get_support   s   
r[   c                   @   sL   e Zd Zi fddZdd Zdd Zdd Zed	d
 Zdd Z	dd Z
dS )VarStoreInstancerc                 C   sL   || _ |d u s|jdksJ |r|jng | _|r|jjng | _| | d S NrL   )rX   ZFormatr.   _varDataVarRegionListr,   _regionssetLocation)r#   ZvarstorerX   locationr   r   r   r$      s
   zVarStoreInstancer.__init__c                 C   s   t || _|   d S r   )dictrb   _clearCaches)r#   rb   r   r   r   ra      s   
zVarStoreInstancer.setLocationc                 C   s
   i | _ d S r   )_scalarsr#   r   r   r   rd         
zVarStoreInstancer._clearCachesc                 C   s@   | j |}|d u r| j| | j}t| j|}|| j |< |S r   )re   r6   r`   get_supportrX   r   rb   )r#   	regionIdxZscalarZsupportr   r   r   
_getScalar   s   
zVarStoreInstancer._getScalarc                 C   s.   d}t | |D ]\}}|sq||| 7 }q|S )Ng        )zip)rC   scalarsZdeltarI   sr   r   r   interpolateFromDeltasAndScalars   s
   z1VarStoreInstancer.interpolateFromDeltasAndScalarsc                    sJ   |d? |d@ }} j } fdd|| jD }|| j| } ||S )NrM   r5   c                       g | ]}  |qS r   rj   rH   Zrirf   r   r   rJ          z1VarStoreInstancer.__getitem__.<locals>.<listcomp>)r^   VarRegionIndexr0   rn   )r#   ZvaridxmajorminorvarDatarl   rC   r   rf   r   __getitem__   s
   zVarStoreInstancer.__getitem__c                    s*    j } fdd|| jD } ||S )Nc                    ro   r   rp   rq   rf   r   r   rJ      rr   z;VarStoreInstancer.interpolateFromDeltas.<locals>.<listcomp>)r^   rs   rn   )r#   ZvarDataIndexrC   rv   rl   r   rf   r   interpolateFromDeltas   s
   
z'VarStoreInstancer.interpolateFromDeltasN)rQ   rR   rS   r$   ra   rd   rj   staticmethodrn   rw   rx   r   r   r   r   r\      s    
r\   TFc                 C   s  i }|D ]}|d? }|d@ }| |}	|	d u rt  }	||< |	| q~| j}
g }i }t|
D ]\}}| |}|d u r>q0t|}|| |j}g }|dkrt|rttt|D ]}|||v rd|| ndgt||   |||< qXn/|dkrt	|t	||  }nt	|}|D ]}t|}|||  |d> | ||d> | < q||_t|j|_
|j|d q0|| _t| j| _|   |S )NrM   r5   r   r)   )r6   setaddr.   rZ   r+   r7   r0   ranger   r1   r2   r/   prune_regions)r#   ZvarIdxesr*   ZretainFirstMapZadvIdxesusedrO   rt   ru   rI   rv   Z
newVarDataZ
varDataMapr3   Z
usedMinorsZnewMajorr   ZnewItemsZminorsZnewMinorr   r   r   VarStore_subset_varidxes   sN   


(
r   c                    s   t  }| jD ]}||j q| j}|j}g }i  t|D ]}t| |< |||  q||_t|j|_	| jD ]} fdd|jD |_q9dS )zRemove unused VarRegions.c                    s   g | ]} | qS r   r   )rH   rV   r9   r   r   rJ     rK   z*VarStore_prune_regions.<locals>.<listcomp>N)
rz   r.   updaters   r_   r,   r   r+   r7   r-   )r#   ZusedRegionsr3   r:   r;   Z
newRegionsrV   r   r   r   VarStore_prune_regions   s   

r   c                 C   s   t | tjkr||  dS t| tr| D ]}t|| qdS t| drAt| dsA|  D ]}t| |j	d}|dur>t|| q,dS t| tj
rT| j D ]	}t|| qLdS dS )znRecurse down from self, if type of an object is ot.Device,
	call func() on it.  Works on otData-style classes.getConvertersZpostReadN)typeotZDevice
isinstancer(   _visithasattrr   getattrnameZValueRecord__dict__values)r#   functhatconvr   r   r   r     s$   

r   c                 C   s(   | j dkr|| jd> | j  dS dS )z6Add VarIdx in this Device table (if any) to the set s.   rM   N)DeltaFormatr{   	StartSizeEndSize)r#   rm   r   r   r   _Device_recordVarIdx'  s   
r   c                 C   s   t t|d}t| | d S )N)rm   )r
   r   r   )r#   ZvaridxesZadderr   r   r   Object_collect_device_varidxes,  s   r   c                 C   sX   t | |v rdS |t |  | jdkr*|| jd> | j  }|d? | _|d@ | _dS dS )z9Map VarIdx in this Device table (if any) through mapping.Nr   rM   r5   )idr{   r   r   r   )r#   mappingdonerO   r   r   r   _Device_mapVarIdx3  s   

r   c                 C   s   t t|t d}t| | d S )N)r   r   )r
   r   rz   r   )r#   Zvaridxes_mapZmapperr   r   r   Object_remap_device_varidxes=  s   r   c                   @   s   e Zd Zdd Zdd Zdd Zdd ZeeZed	d
 Z	dd Z
dd Zdd Zdd Zedd Zedd Zdd ZdS )	_Encodingc                 C   s*   || _ | || _| || _t | _d S r   )chars	_popcountwidth_characteristic_overheadoverheadrz   r   r#   r   r   r   r   r$   G  s   z_Encoding.__init__c                 C      | j | d S r   )r   r{   )r#   rowr   r   r   r7   M     z_Encoding.appendc                 C   r   r   )r   r   )r#   Zlstr   r   r   extendP  r   z_Encoding.extendc                 C   s$   t | j}td| jd | | j S )zxMaximum number of bytes that can be added to characteristic
		while still being beneficial to merge it into another one.r   rL   r+   r   maxr   r   r#   countr   r   r   get_roomS  s   
z_Encoding.get_roomc                 C   s$   t | j}td| j|| jd   S )zKMaximum possible byte gain from merging this into another
		characteristic.r   rL   r   r   r   r   r   gainZ  s   
z_Encoding.gainc                 C   s   | j | jfS r   )r   r   rf   r   r   r   sort_keya  s   z_Encoding.sort_keyc                 C   s
   t | jS r   )r+   r   rf   r   r   r   __len__d  rg   z_Encoding.__len__c                 C   s   || j  @  S r   )r   r   r   r   r   
can_encodeg  s   z_Encoding.can_encodec                 C   s   |  | j|j @ S r   )r   r   )r#   otherr   r   r   __sub__j  s   z_Encoding.__sub__c                 C   s   t | dS )N1)binr   )nr   r   r   r   m  s   z_Encoding._popcountc                 C   s(   d}| r| d@ r|d7 }| dL } | s|S )zIReturns overhead in bytes of encoding this characteristic
		as a VarData.            r   )r   cr   r   r   r   s  s   z"_Encoding._characteristic_overheadc                 C   sT   d | _ t| jd | j| j d D ]}|| D ]
}|| jr! nqd }|| _ qd S r]   )best_new_encodingr|   r   roomr   r   )r#   done_by_widthZ	new_widthZnew_encodingr   r   r    _find_yourself_best_new_encoding~  s    z*_Encoding._find_yourself_best_new_encodingN)rQ   rR   rS   r$   r7   r   r   propertyr   r   r   r   r   r   ry   r   r   r   r   r   r   r   r   E  s"    



r   c                   @   s(   e Zd Zdd Zdd Zedd ZdS )_EncodingDictc                 C   s   t | }| |< |S r   )r   )r#   r   rr   r   r   __missing__  s   z_EncodingDict.__missing__c                 C   s   |  |}| | | d S r   )_row_characteristicsr7   )r#   r   r   r   r   r   add_row  s   
z_EncodingDict.add_rowc                 C   s   d}d}d}| D ],}|r||7 }d|  krdks!n ||d 7 }d|  kr+dks0n d	} n|d
K }q|r]d}d}| D ]}|rG||d 7 }d|  krQdksXn ||d 7 }|d
K }q=|S )z+Returns encoding characteristics for a row.Fr   rL   i   r   i i  Tr         r   )r   Z	longWordsr   rV   vr   r   r   r     s,   

z"_EncodingDict._row_characteristicsN)rQ   rR   rS   r   r   ry   r   r   r   r   r   r     s
    r   c                 C   sn  t | jj}dg| }i }t }t| jD ]8\}}|j}t|jD ]+\}}	t|}
t	||	D ]\}}|
|  |7  < q.t
|
}
||
 |
||d> | < q!qt| tjdd}tt}g }|D ]}|jsn||j | q`|| q`|jtjd |D ]}|| q}|r5| }d}d}t|D ]i\}}|j|jB }t|}t|}|j
 |j | ||j t |  ||j t |  }|jdu rdn|j
 |jj|j t |  }|jdu rdn|j
 |jj|j t |  }|| }||kr|}|| }q|du r||j | n'|| }|j|jB }t|}||j ||j || ||= || |si }t| g }|jtj d g | _t|D ]3\}}t! }| j| t"||_t |j|_#t|j|_t|jD ]\}}	|d> | ||	< qpqLi }| D ]\}}|| ||< q| $  t | jj| j_%t | j| _&| jD ]}t |j|_'|(  q|S )z@Optimize storage. Returns mapping from old VarIdxes to new ones.r   rM   T)r   reverser   N))r+   r_   r,   r   rZ   r.   rs   r0   r(   rk   r   r   r   r   r   r   r   r   r   r7   sortr   r   rA   r   r   r   r   r   r   r   sumr   r   r|   rT   r}   r-   r/   r1   r*   )r#   r   ZzeroesZfront_mapping	encodingsrt   r3   r<   ru   itemr   ri   r   r   ZtodoencodingZbest_idxZ	best_gainrV   Zother_encodingZcombined_charsZcombined_widthZcombined_overheadZcombined_gainZ	this_gainZ
other_gainZseparate_gainZcombined_encodingZback_mapping
varidx_mapkr   r   r   VarStore_optimize  s   






+

r   Nc                 C   s(  ddl m} ddlm} ddlm} ddlm} |dtj	d}|
d |j
d	d
d || }|dd |j}|j}||}	|	d }
|
jj}| }|||	 t| }td|  | }|
j| d|	v rr|	d j| | }|||	 t| }td|  |dur|	| dS dS )z&Optimize a font's GDEF variation storer   )ArgumentParser)configLogger)TTFont)OTTableWriterzvarLib.varStore)progdescriptionfontfileoutfile?)nargsINFO)levelGDEFzBefore: %7d bytesGPOSzAfter:  %7d bytesN)argparser   Z	fontToolsr   ZfontTools.ttLibr   ZfontTools.ttLib.tables.otBaser   main__doc__add_argument
parse_argsr   r   tableVarStorecompiler+   Z
getAllDataprintr*   remap_device_varidxesZsave)argsr   r   r   r   parseroptionsr   r   ZfontZgdefstorewritersizer   r   r   r   r   /  s:   


r   __main__rL   r   )9ZfontTools.misc.roundToolsr   r   ZfontTools.ttLib.tablesr   r   ZfontTools.varLib.modelsr   ZfontTools.varLib.builderr   r   r   r	   	functoolsr
   collectionsr   r   objectr   r@   rU   r.   rN   r[   Z	VarRegionrh   r\   rz   r   r   Zsubset_varidxesr   r}   r   r   r   r   Zcollect_device_varidxesr   r   r   r   r   rc   r   r   r*   r   rQ   sysr+   argvexitZdoctestZtestmodZfailedr   r   r   r   <module>   sL    d47
D)z
*