o
    %e
f                     @   st  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" Z2d1d$d%Z3d&d' Z4d(d) Z5G d*d+ d+eZ6G d,d- d-e6Z7G d.d/ d/eZ8d0S )2    )
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 )Nfvarc                 S      g | ]}|j qS  )axisTag).0axisr   r   G/var/www/html/venv/lib/python3.10/site-packages/fontTools/varLib/cff.py
<listcomp>'       z"addCFFVarStore.<locals>.<listcomp>CFF2r   )
otVarStorePrivate)axesr   builderbuildVarRegionListbuildVarStorecfftopDictIndexr   VarStoreFDArrayvstorehasattrr(   )varFontvarModelvarDataListmasterSupports	fvarTableaxisKeysvarTupleListvarStoreCFFVtopDictfdArrayfontDictr   r   r#   addCFFVarStore%   s   

r>   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(   r0   Tr      )isCFF2)"otFontgetGlyphOrderr   r.   itemsr2   r(   r   r   ordercff2GetGlyphOrderr
   r0   stringsGlobalSubrsr<   CharStringscharStringsAreIndexedcharStringsIndexr   setCFF2appendr	   r   rawDictdelattrlistkeysr   majorr   compileseek	decompile)r-   rA   rE   topDictDatar;   privateDictopOrderr<   charStringsr=   privateOpOrderentrykeyfiler   r   r#   lib_convertCFFToCFF24   s   




















r]   c                 C   s6   | d }t |j|  td}|j|_|| d< | d= d S NzCFF r&   )r]   r-   r   )r3   cffTablenewCFF2r   r   r#   convertCFFtoCFF2   s   
ra   c                 C   s   t | tr|  rt| S | S N)
isinstancefloat
is_integerint)numr   r   r#   conv_to_int   s   rh   )
BlueValues
OtherBluesFamilyBluesFamilyOtherBlues	BlueScale	BlueShiftBlueFuzzStdHWStdVW	StemSnapH	StemSnapVc                 C   s6   | | }|| }||v r|| }|| j }|S d }|S rb   )r(   )regionFDArraysfd_indexrifd_mapregion_fdArrayregion_fd_mapregion_fdIndexprivater   r   r#   get_private   s   
r|   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 )a  
    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   Nr0   c                 S   r   r   )r0   r!   	fdTopDictr   r   r#   r$      r%   z&merge_PrivateDicts.<locals>.<listcomp>c                 S   s   g | ]}|gqS r   r   r}   r   r   r#   r$      r%   vsindexc                       g | ]}|j   qS r   rM   r!   pdr[   r   r#   r$          z\Warning: {key} in default font Private dict is missing from another font, and was discarded.r   Fc                    s   g | ]
\}}| |  qS r   r   )r!   ival)prev_val_listr   r#   r$          Tc                 S   s   g | ]}|d  qS r   r   )r!   datar   r   r#   r$     s    c                    r   r   r   r   r   r   r#   r$     r   )r2   	enumerater0   r(   getattr	locationsindexrL   r|   lenrM   rC   pd_blend_fieldsrc   rO   KeyErrorprintformatzip
IndexErrorr   r   	getDeltasrh   )	top_dictsvsindex_dict	var_modelrw   r;   region_top_dictsrt   ru   	font_dictprivate_dictr   	sub_model_master_indiceslocr   pdslast_pdrv   r   num_mastersvaluedataListvaluesany_points_differval_listrel_listdeltasitemjjtemr   )r[   r   r#   merge_PrivateDicts   s   




r   c                 C   s   d| v r| d S | d S r^   r   )fontr   r   r#   _cff_or_cff2!  s   r   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!   rv   r   r   r#   
<dictcomp>7  r%   zgetfd_map.<locals>.<dictcomp>)	r   r   r-   r.   r2   ranger   rB   r   )r3   
fonts_listrw   default_fontregion_fontsnum_regionsr;   gname_mappingdefault_fdSelect
glyphOrdergidfdIndexrv   region_fontregion_glyphOrderregion_topDictdefault_fdIndexregion_fdSelect
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   )r   r-   r.   )r!   ttFontr   r   r#   r$   W  r   z&merge_region_fonts.<locals>.<listcomp>r   )r-   r.   r   mappingmerge_charstringsr   r   r   r>   r5   r6   )	r3   modelordered_fonts_listr   r;   r   r   cvDatarw   r   r   r#   merge_region_fontsU  s   



r   Fc                 C   sv   || vrd S | | }|r9|   |jg krd S t|jdkr9|jd dkr9t|jdks7t|jd ttfv r9d S |S )Nr?   endcharr   r   )rT   programr   typerf   rd   )charstrings	glyphNamefilterEmptycsr   r   r#   _get_csa  s   
$r   c           
      C   sv   g }| j dd  D ]}||vr|| ||| q	tj|d d}t|}	|	||< | |gf||	< || |	S )Nr   F)supportsrL   r   r   r*   buildVarDatar   )
r   r[   r6   r   vsindex_by_keyr5   varTupleIndexessupportvar_datar   r   r   r#   _add_new_vsindext  s   

r   c                    sv  i }i }g }g }|d j }t| D ]\}	  fddt|D }
||
\}}|d }tg  |d}t|_|| |dd  }t|ddD ]\}}|| t|_|| qF|j|j	|j
|dd}|| < |sjq|jrrd|jvrsq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 |d kqS r   )r   rH   )r!   r   tdgnamer   r#   r$     s    z%merge_charstrings.<locals>.<listcomp>r   )startT)r{   globalSubrsr   optimizeblendc                 s   s    | ]}|d uV  qd S rb   r   )r!   vr   r   r#   	<genexpr>  s    z$merge_charstrings.<locals>.<genexpr>r   )T)r5   r6   r   )rH   r   getSubModelCFF2CharStringMergePenMergeOutlineExtractoroutlineExtractordrawrestartgetCharStringr{   r   seen_movetor   tupler   r   r   )r   r   r   masterModelr   r   r5   r6   default_charstringsr   all_csr   model_csdefault_charstringvar_pen	region_cs
region_idxregion_charstringnew_csr[   r   r   r   r   r#   r     sh   



r   c                   @   s   e Zd ZdZdddZdS )CFFToCFF2OutlineExtractorzThis 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 )Nr?   r   )popallgotWidthr   defaultWidthXwidth)selfevenOddargsr   r   r#   popallWidth  s   z%CFFToCFF2OutlineExtractor.popallWidthNr   )__name__
__module____qualname____doc__r  r   r   r   r#   r     s    r   c                       sn   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   zUsed 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 rb   )super__init__)r   pen
localSubrsr   nominalWidthXr   r{   blender	__class__r   r#   r    s   
zMergeOutlineExtractor.__init__c                 C   s    |   }| jt|d  | _|S )Nr?   )r  	hintCountr   )r   r   r   r   r#   
countHints  s   z MergeOutlineExtractor.countHintsc                 C   s   | j || d S rb   )r  add_hint)r   r   r   r   r   r#   _hint_op  s   zMergeOutlineExtractor._hint_opc                 C      |   }| d| d S )Nhstemr  r  r   r   r   r   r   r#   op_hstem     zMergeOutlineExtractor.op_hstemc                 C   r  )Nvstemr  r  r   r   r#   op_vstem  r  zMergeOutlineExtractor.op_vstemc                 C   r  )N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        r   )hintMaskBytesr  r  r  callingStackgetBytes)r   r   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   r   r   r   r   r#   op_hintmask     z!MergeOutlineExtractor.op_hintmaskc                 C   r$  )Ncntrmaskr&  r(  r   r   r#   op_cntrmask  r*  z!MergeOutlineExtractor.op_cntrmask)NN)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.{Gz?c                    sP   t  jd d d|d d| _|| _|| _|| _d| _d| _|| _t	|t
d| _
d S )NT)r   glyphSetr&   roundTolerancer   Fround)r  r  pt_index	_commandsm_indexr   prev_move_idxr   r   r   r2  )r   default_commandsr   r   
master_idxr0  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   )r5  r4  rL   r3  r   r   r   )r   
point_type	pt_coordscmdr   r   r#   	add_point5     
z CFF2CharStringMergePen.add_pointc                 C   r9  r:  r5  r4  rL   r3  r   r   r   )r   	hint_typer   r=  r   r   r#   r  A  r?  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   rA  abs_argsr=  r   r   r#   r'  M  s   
z#CFF2CharStringMergePen.add_hintmaskc                 C   s2   | j sd| _ | |}| d| | jd | _d S )NTrmovetor   )r   _pr>  r3  r6  r   ptr<  r   r   r#   _moveTo`  s
   
zCFF2CharStringMergePen._moveToc                 C   s   |  |}| d| d S )NrlinetorE  r>  rF  r   r   r#   _lineToi  s   
zCFF2CharStringMergePen._lineToc                 C   s.   | j }|||| || }| d| d S )N	rrcurvetorJ  )r   pt1pt2pt3rE  r<  r   r   r#   _curveToOnem  s   z"CFF2CharStringMergePen._curveToOnec                 C      d S rb   r   r   r   r   r#   
_closePathr     z!CFF2CharStringMergePen._closePathc                 C   rQ  rb   r   rR  r   r   r#   _endPathu  rT  zCFF2CharStringMergePen._endPathc                 C   s   d| _ || _d| _d S )Nr   )r   r   )r3  r5  _p0)r   r   r   r   r#   r   x  s   
zCFF2CharStringMergePen.restartc                 C   s   | j S rb   )r4  rR  r   r   r#   getCommands}  s   z"CFF2CharStringMergePen.getCommandsc                 C   s   |D ]}|d }t | }t||d< qd}|D ]X}|d }|dv r9t|d }t|s/td|d d g|d< n4|d }	g }
|	D ]'}t|rO|
|d  qA||dd }|d g| }|d |
| 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.)r   rO   r   r   rL   )r   commandsget_delta_funcr=  r   m_argslastOpopcoordcoords
new_coordsr   r   r   r#   reorder_blend_args  s4   
z)CFF2CharStringMergePen.reorder_blend_argsNTc                 C   sJ   | j }| |t|j| jd}|rt|dtd}t|}t|||d}|S )Nr1  F)generalizeFirstmaxstack)r   r{   r   )	r4  r`  r   r   r2  r   r   r   r   )r   r{   r   r   r   rX  r   
charStringr   r   r#   r     s   z$CFF2CharStringMergePen.getCharString)r.  )NNNT)r  r  r  r  r  r>  r  r'  rH  rK  rP  rS  rU  r   rW  r`  r   r-  r   r   r  r#   r   "  s"    	:r   N)F)9collectionsr   fontTools.cffLibr   r   r   r   r   r   r	   r
   r   r   ior   fontTools.cffLib.specializerr   r   fontTools.ttLibr   	fontToolsr   fontTools.varLib.modelsr   fontTools.misc.roundToolsr   fontTools.misc.psCharStringsr   r   fontTools.pens.t2CharStringPenr   	functoolsr   errorsr   r   r   r   MergeDictErrorMergeTypeErrorr>   r]   ra   rh   r   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   <module>   s>    0	O
t
+
P?