o
    aS                     @   sr  d dl mZ d dlmZmZmZmZmZmZm	Z	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 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!m"Z"m#Z#m$Z$m%Z% e"Z&e#Z'dd Z(dd Z)dd Z*dd Z+dZ,dd Z-dd Z.dd Z/dd Z0edd Z1d!d" Z2d#d$ Z3d%d& Z4d'd( Z5G d)d* d*eZ6G d+d, d,e6Z7G d-d. d.eZ8d/S )0    )
namedtuple)
maxStackLimitTopDictIndex
buildOrdertopDictOperatorstopDictOperators2privateDictOperatorsprivateDictOperators2FDArrayIndexFontDictVarStoreData)BytesIO)specializeCommandscommandsToProgram)newTable)varLib)allEqual)	roundFunc)T2CharStringT2OutlineExtractor)T2CharStringPen)partial   )VarLibCFFDictMergeErrorVarLibCFFPointTypeMergeErrorVarLibCFFHintTypeMergeErrorVarLibMergeErrorc                 C   s   | d }dd |j D }tj||}tj||}| d jjd }t|d|_|j	d j
d u rB|j	}	|	D ]}
t|
drA|j|
j_
q5d S d S )NZfvarc                 S      g | ]}|j qS  )ZaxisTag).0Zaxisr   r   6/usr/lib/python3/dist-packages/fontTools/varLib/cff.py
<listcomp>%       z"addCFFVarStore.<locals>.<listcomp>CFF2r   )Z
otVarStorePrivate)Zaxesr   builderZbuildVarRegionListZbuildVarStorecfftopDictIndexr   ZVarStoreFDArrayZvstorehasattrr$   )varFontZvarModelvarDataListmasterSupportsZ	fvarTableZaxisKeysZvarTupleListZvarStoreCFFVtopDictfdArrayfontDictr   r   r    addCFFVarStore#   s   

r0   c                 C   s,  | j j}td |d }| jj|_|| _|d }t|dr|j}nd }tt}||_	||_
t|dst  }|_d |_|j|_||j_|j}|jrL||j_n||_t }	|	d ||	 ||	_tt}
|d urtD ]}|d }||
vr||jv r||j|= t||rt|| qinQ|j}tt}
|D ]G}	|	d t|	j D ]}||	j	vr|	j|= t|	|rt|	| q|	j}tD ]}|d }||
vr||jv r|j|= t||rt|| qqtD ]}|d }||vr||jv r|j|= t||rt|| qd| _t }| j||dd | d | j!||dd d S )Nr   r$   r(   Tr      )ZisCFF2)"otFontgetGlyphOrderr   r'   itemsr)   r$   r   r   Zordercff2GetGlyphOrderr
   r(   stringsZGlobalSubrsr.   CharStringsZcharStringsAreIndexedZcharStringsIndexr   ZsetCFF2appendr	   r   rawDictdelattrlistkeysr   majorr   compileseekZ	decompile)r&   r2   r5   ZtopDictDatar-   ZprivateDictZopOrderr.   ZcharStringsr/   ZprivateOpOrderentrykeyfiler   r   r    lib_convertCFFToCFF22   s   




















rC   c                 C   s6   | d }t |j|  td}|j|_|| d< | d= d S NzCFF r#   )rC   r&   r   )r*   ZcffTableZnewCFF2r   r   r    convertCFFtoCFF2   s   
rE   c                 C   s   t | tr|  rt| S | S N)
isinstancefloat
is_integerint)Znumr   r   r    conv_to_int   s   rK   )Z
BlueValuesZ
OtherBluesZFamilyBluesZFamilyOtherBluesZ	BlueScaleZ	BlueShiftZBlueFuzzZStdHWZStdVWZ	StemSnapHZ	StemSnapVc                 C   s6   | | }|| }||v r|| }|| j }|S d }|S rF   )r$   )regionFDArraysfd_indexrifd_mapZregion_fdArrayZregion_fd_mapZregion_fdIndexprivater   r   r    get_private   s   
rQ   c              
      s  | d }| dd }t |d drdd |D }ndd |D }t|jD ]$\}}|j}	t|	dd}
||
 \}}g }|jdd D ]}|j|d }|| qB|	g}|	}|D ]}t||||}|du ri|}n|}|| qYt	|}|	j
 D ]\ }g } tvrqzt|trz fd	d|D }W n ty   td
j d Y qzw zt| }W n ty   t ||w 	 dg| d}|D ]'}fddt|D }|st|sd}|||}|d |d< || q|sdd |D }n fdd|D }t|s||}n|d }t|tr@t|D ]%\}}t|tr7t|D ]\}}t||| |< q'qt|||< qnt|}||	j
 < qzq%dS )aw  
	I step through the FontDicts in the FDArray of the varfont TopDict.
	For each varfont FontDict:
	
	* step through each key in FontDict.Private.
	* For each key, step through each relevant source font Private dict, and
		build a list of values to blend.

	The 'relevant' source fonts are selected by first getting the right
	submodel using ``vsindex_dict[vsindex]``. The indices of the
	``subModel.locations`` are mapped to source font list indices by
	assuming the latter order is the same as the order of the
	``var_model.locations``. I can then get the index of each subModel
	location in the list of ``var_model.locations``.
	r   r   Nr(   c                 S   r   r   )r(   r   Z	fdTopDictr   r   r    r!      r"   z&merge_PrivateDicts.<locals>.<listcomp>c                 S   s   g | ]}|gqS r   r   rR   r   r   r    r!      r"   vsindexc                       g | ]}|j   qS r   r9   r   pdrA   r   r    r!          z\Warning: {key} in default font Private dict is missing from another font, and was discarded.rX   Fc                    s   g | ]
\}}| |  qS r   r   )r   ival)prev_val_listr   r    r!      s    Tc                 S   s   g | ]}|d  qS r   r   )r   datar   r   r    r!      s    c                    rT   r   rU   rV   rX   r   r    r!      rY   )r)   	enumerater(   r$   getattrZ	locationsindexr8   rQ   lenr9   r4   pd_blend_fieldsrG   r;   KeyErrorprintformatzip
IndexErrorr   r   	getDeltasrK   )	top_dictsvsindex_dict	var_modelrO   r-   Zregion_top_dictsrL   rM   Z	font_dictZprivate_dictrS   Z	sub_model_Zmaster_indiceslocrZ   ZpdsZlast_pdrN   rW   num_mastersvalueZdataListvaluesZany_points_differZval_listrel_listdeltasitemjZjtemr   )rA   r\   r    merge_PrivateDicts   s   




rv   c                 C   s   d| v r| d S | d S rD   r   )Zfontr   r   r    _cff_or_cff2  s   rw   c                 C   s"  i }|d }|dd }t |}t|jjd }t|ds*dd t|D |d< |S i }|j}| }	t|D ]\}
}|||	|
 < ||vrIi ||< q7t|D ]@\}}| }t|jjd }t|dsp||d  }d|| |< qN|j}t|D ]\}
}|||
  }|| }||vr|||< qwqN|S )a   Since a subset source font may have fewer FontDicts in their
	FDArray than the default font, we have to match up the FontDicts in
	the different fonts . We do this with the FDSelect array, and by
	assuming that the same glyph will reference  matching FontDicts in
	each source font. We return a mapping from fdIndex in the default
	font to a dictionary which maps each master list index of each
	region font to the equivalent fdIndex in the region font.r   r   NFDSelectc                 S   s   i | ]}|d qS r]   r   )r   rN   r   r   r    
<dictcomp>*  r"   zgetfd_map.<locals>.<dictcomp>)	rb   rw   r&   r'   r)   rangerx   r3   r_   )r*   Z
fonts_listrO   Zdefault_fontZregion_fontsZnum_regionsr-   Zgname_mappingZdefault_fdSelect
glyphOrdergidZfdIndexrN   Zregion_fontZregion_glyphOrderZregion_topDictZdefault_fdIndexZregion_fdSelectZ
region_mapr   r   r    	getfd_map  s>   

r}   CVarDataz'varDataList masterSupports vsindex_dictc           	      C   st   | d j jd }|gdd |dd  D  }t|j}t||||}t| |}t||j|| t| ||j	|j
 d S )Nr#   r   c                 S   s   g | ]
}t |jjd  qS r]   )rw   r&   r'   )r   ZttFontr   r   r    r!   H  s    z&merge_region_fonts.<locals>.<listcomp>r   )r&   r'   rb   mappingmerge_charstringsr}   rv   rk   r0   r+   r,   )	r*   modelZordered_fonts_listr{   r-   rj   ro   cvDatarO   r   r   r    merge_region_fontsF  s   




r   c                 C   s   || vrd S | | S rF   r   )Zcharstrings	glyphNamer   r   r    _get_csT  s   r   c           
      C   sv   g }| j dd  D ]}||vr|| ||| q	tj|d d}t|}	|	||< | |gf||	< || |	S )Nr   F)Zsupportsr8   ra   r   r%   ZbuildVarDatarb   )
r   rA   r,   rk   vsindex_by_keyr+   ZvarTupleIndexesZsupportZvar_datarS   r   r   r    _add_new_vsindexY  s   

r   c                    s  i }i }g }g }|d j }t| D ]\}	  fdd|D }
tdd |
D dkr*q||
\}}|d }tg  |d}t|_|| |dd  }t|ddD ]\}}|| t|_|| qP|j	|j
|j|dd}|| < |jryd	|jvrzqtd
d |
D }z|| }W n ty   t||||||}Y nw |dkr|dg|jd d< q|sd| }t|||||| t|||d}|S )Nr   c                    s   g | ]}t |j qS r   )r   r7   )r   Ztdgnamer   r    r!   o  s    
z%merge_charstrings.<locals>.<listcomp>c                 S   s   g | ]}|d ur|qS rF   r   )r   Zgsr   r   r    r!   r  s    r   )startT)rP   globalSubrsrl   optimizeZblendc                 s   s    | ]}|d uV  qd S rF   r   )r   vr   r   r    	<genexpr>  s    z$merge_charstrings.<locals>.<genexpr>rS   )T)r+   r,   rk   )r7   r_   rb   ZgetSubModelCFF2CharStringMergePenMergeOutlineExtractorZoutlineExtractorZdrawrestartgetCharStringrP   r   seen_movetoprogramtuplerd   r   r~   )r{   ro   rj   ZmasterModelrk   r   r+   r,   Zdefault_charstringsr|   Zall_csr   Zmodel_csZdefault_charstringZvar_penZ	region_cs
region_idxZregion_charstringZnew_csrA   rS   r   r   r   r    r   g  sb   





r   c                   @   s   e Zd ZdZdddZdS )CFFToCFF2OutlineExtractorz This class is used to remove the initial width from the CFF
	charstring without trying to add the width to self.nominalWidthX,
	which is None. r   c                 C   s<   |   }| js|t|d A r|dd  }| j| _d| _|S )Nr1   r   )ZpopallZgotWidthrb   defaultWidthXwidth)selfZevenOddargsr   r   r    popallWidth  s   z%CFFToCFF2OutlineExtractor.popallWidthNr]   )__name__
__module____qualname____doc__r   r   r   r   r    r     s    r   c                       sl   e Zd ZdZ	d fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Z  ZS )r   z Used to extract the charstring commands - including hints - from a
	CFF charstring in order to merge it as another set of region data
	into a CFF2 variable font charstring.Nc                    s   t  |||||| d S rF   )super__init__)r   penZ
localSubrsr   ZnominalWidthXr   rP   	__class__r   r    r     s   
zMergeOutlineExtractor.__init__c                 C   s    |   }| jt|d  | _|S )Nr1   )r   	hintCountrb   )r   r   r   r   r    
countHints  s   z MergeOutlineExtractor.countHintsc                 C   s   | j || d S rF   )r   add_hint)r   typer   r   r   r    _hint_op  s   zMergeOutlineExtractor._hint_opc                 C      |   }| d| d S )NZhstemr   r   r   ra   r   r   r   r    op_hstem     zMergeOutlineExtractor.op_hstemc                 C   r   )NZvstemr   r   r   r   r    op_vstem  r   zMergeOutlineExtractor.op_vstemc                 C   r   )NZhstemhmr   r   r   r   r    
op_hstemhm  r   z MergeOutlineExtractor.op_hstemhmc                 C   r   )Nvstemhmr   r   r   r   r    
op_vstemhm  r   z MergeOutlineExtractor.op_vstemhmc                 C   sN   | j s|  }|r| d| | jd d | _ | jd || j \}}||fS )Nr         )hintMaskBytesr   r   r   ZcallingStackZgetBytes)r   ra   r   r   r   r   r    _get_hintmask  s   z#MergeOutlineExtractor._get_hintmaskc                 C   &   |  |\}}| jd|g ||fS )Nhintmaskr   r   add_hintmaskr   ra   r   r   r   r    op_hintmask     z!MergeOutlineExtractor.op_hintmaskc                 C   r   )Ncntrmaskr   r   r   r   r    op_cntrmask  r   z!MergeOutlineExtractor.op_cntrmaskrF   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r    r     s    
r   c                       s   e Zd ZdZ	d fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Z		d ddZ  ZS )!r   z"Pen to merge Type 2 CharStrings.
	      ?c                    sP   t  jd d d|d d| _|| _|| _|| _d| _d| _|| _t	|t
d| _
d S )NT)r   ZglyphSetr#   roundTolerancer   Fround)r   r   pt_index	_commandsm_indexro   prev_move_idxr   r   r   r   )r   Zdefault_commandsr   ro   Z
master_idxr   r   r   r    r     s   zCFF2CharStringMergePen.__init__c                 C   v   | j dkr| j||gg n#| j| j }|d |kr+t|| jt|d |d | j|d | |  jd7  _d S Nr   r   )r   r   r8   r   r   rb   r   )r   Z
point_type	pt_coordscmdr   r   r    	add_point  s   

z CFF2CharStringMergePen.add_pointc                 C   r   r   r   r   r8   r   r   rb   r   )r   	hint_typer   r   r   r   r    r     s   

zCFF2CharStringMergePen.add_hintc                 C   s   | j dkr| j|g g | jd|gg n0| j| j }|d |kr3t|| jt|d |d | j|  jd7  _| j| j }|d | |  jd7  _d S )Nr    r   r   )r   r   Zabs_argsr   r   r   r    r     s   

z#CFF2CharStringMergePen.add_hintmaskc                 C   s2   | j sd| _ | |}| d| | jd | _d S )NTZrmovetor   )r   _pr   r   r   r   ptr   r   r   r    _moveTo1  s
   
zCFF2CharStringMergePen._moveToc                 C   s   |  |}| d| d S )NZrlinetor   r   r   r   r   r    _lineTo:  s   
zCFF2CharStringMergePen._lineToc                 C   s.   | j }|||| || }| d| d S )NZ	rrcurvetor   )r   Zpt1Zpt2Zpt3r   r   r   r   r    _curveToOne>  s   z"CFF2CharStringMergePen._curveToOnec                 C      d S rF   r   r   r   r   r    
_closePathC     z!CFF2CharStringMergePen._closePathc                 C   r   rF   r   r   r   r   r    _endPathF  r   zCFF2CharStringMergePen._endPathc                 C   s   d| _ || _d| _d S )Nr   )r   r   )r   r   Z_p0)r   r   r   r   r    r   I  s   
zCFF2CharStringMergePen.restartc                 C   s   | j S rF   )r   r   r   r   r    getCommandsN  s   z"CFF2CharStringMergePen.getCommandsc                 C   s   |D ]}|d }t | }t||d< qd}|D ]S}|d }|dv r9t|d }t|s/td|d d g|d< n/|d }	g }
|	D ]"}t|rO|
|d  qA||dd }|d g| }|
| qA|
|d< |}q|S )a  
		We first re-order the master coordinate values.
		For a moveto to lineto, the args are now arranged as::

			[ [master_0 x,y], [master_1 x,y], [master_2 x,y] ]

		We re-arrange this to::

			[	[master_0 x, master_1 x, master_2 x],
				[master_0 y, master_1 y, master_2 y]
			]

		If the master values are all the same, we collapse the list to
		as single value instead of a list.

		We then convert this to::

			[ [master_0 x] + [x delta tuple] + [numBlends=1]
			  [master_0 y] + [y delta tuple] + [numBlends=1]
			]
		r   Nr   )r   r   z3Hintmask values cannot differ between source fonts.)rg   r;   r   r   r8   )r   commandsZget_delta_funcr   r   Zm_argsZlastOpopZcoordZcoordsZ
new_coordsrs   r   r   r    reorder_blend_argsQ  s.   z)CFF2CharStringMergePen.reorder_blend_argsNTc                 C   sJ   | j }| |t|j| jd}|rt|dtd}t|}t|||d}|S )Nr   F)ZgeneralizeFirstZmaxstack)r   rP   r   )	r   r   r   ri   r   r   r   r   r   )r   rP   r   rl   r   r   r   Z
charStringr   r   r    r     s   z$CFF2CharStringMergePen.getCharString)r   )NNNT)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r     s$    	7r   N)9collectionsr   ZfontTools.cffLibr   r   r   r   r   r   r	   r
   r   r   ior   ZfontTools.cffLib.specializerr   r   ZfontTools.ttLibr   Z	fontToolsr   ZfontTools.varLib.modelsr   ZfontTools.misc.roundToolsr   ZfontTools.misc.psCharStringsr   r   ZfontTools.pens.t2CharStringPenr   	functoolsr   errorsr   r   r   r   ZMergeDictErrorZMergeTypeErrorr0   rC   rE   rK   rc   rQ   rv   rw   r}   r~   r   r   r   r   r   r   r   r   r   r   r    <module>   s>    0O
r
+H7