o
    aW                    @   s  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
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 d d
lmZmZ d dlmZ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(m)Z)m*Z*m+Z+m,Z,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:Z:d dl;m<Z< d dl=Z=d dl>Z>d dl?Z?e=@eAZBdddZC	dddZDG dd deEZFdS )    )sstruct)Tagtostr
binary2numsafeEval)FeatureLibError)LookupDebugInfoLOOKUP_DEBUG_INFO_KEYLOOKUP_DEBUG_ENV_VAR)Parser)FeatureFile)VariableScalar)builder)
maxCtxFont)newTablegetTableModule)otBaseotTables)AlternateSubstBuilderChainContextPosBuilderChainContextSubstBuilderLigatureSubstBuilderMultipleSubstBuilderCursivePosBuilderMarkBasePosBuilderMarkLigPosBuilderMarkMarkPosBuilderReverseChainSingleSubstBuilderSingleSubstBuilderClassPairPosSubtableBuilderPairPosBuilderSinglePosBuilderChainContextualRule)OpenTypeLibError)OnlineVarStoreBuilder)buildVarDevTable)addFeatureVariationsRawnormalizeValue)defaultdictN)StringIOFc                 C   s   t | |}|j||d dS )a  Add features from a file to a font. Note that this replaces any features
    currently present.

    Args:
        font (feaLib.ttLib.TTFont): The font object.
        featurefile: Either a path or file object (in which case we
            parse it into an AST), or a pre-parsed AST instance.
        tables: If passed, restrict the set of affected tables to those in the
            list.
        debug: Whether to add source debugging information to the font in the
            ``Debg`` table

    tablesdebugN)Builderbuild)fontfeaturefiler,   r-   r    r2   :/usr/lib/python3/dist-packages/fontTools/feaLib/builder.pyaddOpenTypeFeatures1   s   
r4   c                 C   s*   t t|}|r||_t| |||d dS )ae  Add features from a string to a font. Note that this replaces any
    features currently present.

    Args:
        font (feaLib.ttLib.TTFont): The font object.
        features: A string containing feature code.
        filename: The directory containing ``filename`` is used as the root of
            relative ``include()`` paths; if ``None`` is provided, the current
            directory is assumed.
        tables: If passed, restrict the set of affected tables to those in the
            list.
        debug: Whether to add source debugging information to the font in the
            ``Debg`` table

    r+   N)r*   r   namer4   )r0   Zfeaturesfilenamer,   r-   r1   r2   r2   r3   addOpenTypeFeaturesFromStringC   s   r7   c                   @   s  e Zd Zedd dD Zdd Zdd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! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Z d>d? Z!d@dA Z"dBdC Z#dDdE Z$dFdG Z%dHdI Z&dJdK Z'dLdM Z(dNdO Z)dPdQ Z*dRdS Z+dTdU Z,dVdW Z-dXdY Z.dZd[ Z/d\d] Z0d^d_ Z1d`da Z2dbdc Z3ddde Z4dfdg Z5dhdi Z6djdk Z7dldm Z8dndo Z9	ddpdqZ:drds Z;dtdu Z<dvdw Z=dxdy Z>dzd{ Z?d|d} Z@d~d ZAdd ZBdd ZCdd ZDdd ZEdd ZFdd ZGdd ZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNdd ZOdd ZPdd ZQdd ZRdd ZSdd ZTdd eUjVD ZWdd ZXdS )r.   c                 c   s    | ]}t |V  qd S N)r   .0tagr2   r2   r3   	<genexpr>^   s
    
zBuilder.<genexpr>)
BASEGDEFGPOSGSUBOS/2headhhear5   vheaSTATc                 C   st  || _ t|tr|d | _| _nd || _| _| | _d | _d|v r4|d j| _t	dd | jD | _t
 | _d | _d| _d | _t
 | _d| _i | _d | _d | _d | _g | _i i d| _i | _i | _i | _g | _d | _i | _t
 | _i | _t
 | _i | _ i | _!t"t#| _$d | _%d | _&g | _'d | _(d | _)i | _*i | _+i | _,i | _-i | _.i | _/i | _0i | _1i | _2i | _3i | _4i | _5d S )Nfvarc                 S      g | ]}|j qS r2   )axisTag)r:   Zaxr2   r2   r3   
<listcomp>{       z$Builder.__init__.<locals>.<listcomp>r   F)r@   r?   )6r0   
isinstancer   	parseTreefileZgetReverseGlyphMapglyphMapvarstorebuilderaxesr$   setdefault_language_systems_script_lookupflag_lookupflag_markFilterSet_language_systemsseen_non_DFLT_script_named_lookups_cur_lookup_cur_lookup_name_cur_feature_name_lookups_lookup_locations	features_required_features_feature_variations_aalt_features_aalt_location_aalt_alternates_featureNames_featureNames_ids_cv_parameters_cv_parameters_ids_cv_num_named_params_r)   listcv_characters_size_parameters_fontRevision_names_base_horiz_axis_base_vert_axis_attachPoints_ligCaretCoords_ligCaretPoints_glyphClassDefs_markAttach_markAttachClassID_markFilterSets_os2_hhea_vhea_stat_conditionsets_)selfr0   r1   r2   r2   r3   __init__n   sh   



zBuilder.__init__NFc           
         s,   j d u rt j j  _  j   |d u r j}nt|}| j }|r7dt	|}t
d| dd|v r?   d|v rG   d|v rO   d|v rW   d|v r_   d	|v rg   d
|v ro   dD ]=}||vrxqq |} jr || |jjdks|jjdks|jjdkrt| } j|< ||_qq| jv r j|= qqt fdddD rd	 jv rt j jd	 _ d|v r ! }|r| jd< nd jv r jd= n j"rt#dd|v r $ }	|	r|	 jd< n
d jv r jd= |st%j&'t(r )  d S d S )Nz, z9The following tables were requested but are unsupported: .r@   rB   rC   rD   r5   rA   rE   r?   r@   r   c                 3   s    | ]}| j v V  qd S r8   )r0   r9   r|   r2   r3   r<          z Builder.build.<locals>.<genexpr>r>   z-Must save GDEF when compiling a variable fontr=   )*rL   r   rM   rN   parser/   supportedTables	frozensetjoinsortedNotImplementedErrorbuild_feature_aalt_
build_head
build_hhea
build_vhea
build_name
build_OS_2
build_STAT	makeTabler`   makeFeatureVariations
ScriptListScriptCountFeatureListFeatureCount
LookupListLookupCountr   r0   tableanyr   usMaxContext	buildGDEFrO   r   	buildBASEosenvirongetr
   	buildDebg)
r|   r,   r-   ZunsupportedZunsupported_stringr;   r   Z	fontTablegdefbaser2   r   r3   r/      s   






 

zBuilder.buildc                 C   s,   || j |}| j|_| j|_| j| |S r8   )r0   rT   
lookupflagrU   markFilterSetr\   append)r|   locationbuilder_classresultr2   r2   r3   get_chained_lookup_   s
   zBuilder.get_chained_lookup_c                 C   s2   | j D ]\}}|||f}| j|g | qd S r8   )rV   r^   
setdefaultr   )r|   lookupZfeature_namescriptlangkeyr2   r2   r3   add_lookup_to_feature_   s   
zBuilder.add_lookup_to_feature_c                 C   s   | j rt| j |kr| j j| jkr| j j| jkr| j S | jr&| j r&td||| j|| _ | j| j _| j| j _| j	
| j  | jrH| j | j| j< | jrS| | j | j | j S )NzOWithin a named lookup block, all rules must be of the same lookup type and flag)rY   typer   rT   r   rU   rZ   r   r0   r\   r   rX   r[   r   )r|   r   r   r2   r2   r3   get_lookup_   s.   

zBuilder.get_lookup_c              	      st  j sjsd S dd j D }j dg D ]M\}  fddj D }|s5 dkr5td  ||D ]-\}}}}|D ]$}t|tsI|g}|D ]}|  D ]\}	}
||	t	 
|
 qSqKq?q7qdd | D }fd	d| D }|s|sd S d
d j D _j}g _jd |r|t}||_|r|t}||_  j| d S )Nc                 S   s   i | ]	\}}|t |qS r2   )rQ   )r:   gar2   r2   r3   
<dictcomp>      z/Builder.build_feature_aalt_.<locals>.<dictcomp>)Naaltc                    s*   g | ]\\}}}}| kr||||fqS r2   r2   r:   r   r   featurelookups)r5   r2   r3   rI          
z/Builder.build_feature_aalt_.<locals>.<listcomp>r   zFeature %s has not been definedc                 S   s*   i | ]\}}t |d kr|t|d qS )   r   )lenri   r:   glyphreplr2   r2   r3   r   1  s
    c                    s.   i | ]\}}t |d kr|t| jjdqS )r   r   )r   r   r0   Z
getGlyphIDr   r   r2   r3   r   6  s    
c                 S   s*   i | ]\\}}}}|d kr|||f|qS )r   r2   r   r2   r2   r3   r   =  r   )ra   rc   itemsr^   r   rK   ri   ZgetAlternateGlyphsr   rQ   updater\   start_featurerb   r   r   mappingr   
alternatesend_featureextend)r|   r   r   r   r   r   r   
lookuplistr   r   altsZsingleZmultiZold_lookupsZsingle_lookupZmulti_lookupr2   )r5   r|   r3   r     sX   


zBuilder.build_feature_aalt_c                 C   sX   | j sd S | jd}|s&td }| jd< |d| j d|_d |_|_| j |_d S )NrB   s6                                                         g      ?l   e )	rl   r0   r   r   	decompiletableVersionZcreatedZmodifiedZfontRevisionr|   r   r2   r2   r3   r   N  s   zBuilder.build_headc                 C   s   | j sd S | jd}|s td }| jd< |d| j d|_d| j v r+| j d |_d| j v r6| j d |_d| j v rA| j d |_d| j v rN| j d |_	d S d S )NrC   $                                          ZcaretoffsetZascenderZ	descenderZlinegap)
rx   r0   r   r   r   r   ZcaretOffsetascentdescentlineGapr   r2   r2   r3   r   Y  s    



zBuilder.build_hheac                 C   s   | j sd S | jd}|s td }| jd< |d| j d|_d| j v r+| j d |_d| j v r6| j d |_d| j v rC| j d |_d S d S )NrD   r   i  ZverttypoascenderZverttypodescenderZverttypolinegap)	ry   r0   r   r   r   r   r   r   r   r   r2   r2   r3   r   j  s   


zBuilder.build_vheac                 C   s4   dd |j D }tddD ]
}||vr|  S qd S )Nc                 S   rG   r2   )nameID)r:   r5   r2   r2   r3   rI   {  rJ   z,Builder.get_user_name_id.<locals>.<listcomp>   i  )namesrange)r|   r   ZnameIDsZuser_name_idr2   r2   r3   get_user_name_idy  s   zBuilder.get_user_name_idc                 C   s(  d }|dkr't  }| j\|_|_|_|_|| jv r"| j| |_|S d|_|S || j	v rH| js2	 |S || jv s9J t 
 }d|_| j| |_|S || jv rt  }d|_| j|dfd|_| j|dfd|_| j|dfd|_| j|d|_| j|dfd|_t| j| |_| j| |_|S )Nsizer   FeatUILabelNameIDFeatUITooltipTextNameIDSampleTextNameIDZParamUILabelNameID_0)r   ZFeatureParamsSizerk   
DesignSizeSubfamilyID
RangeStartRangeEndre   ZSubfamilyNameIDrd   ZFeatureParamsStylisticSetVersionZUINameIDrf   ZFeatureParamsCharacterVariantsFormatrg   r   r   r   r   rh   ZNumNamedParametersZFirstParamUILabelNameIDr   rj   Z	CharCountZ	Character)r|   r;   paramsr2   r2   r3   buildFeatureParams  sT   


zBuilder.buildFeatureParamsc           	      C   s   | j sd S | jd}|std }| jd< g |_| j D ]\}|\}}}}}t|tso|}|| jv rM|| jvrG| 	|| j|< | j| d usGJ | j| }n"|d | j
v ro|| jvrj| 	|| j|< | j| d usjJ | j| }|||||| qd S )Nr5   r   )rm   r0   r   r   r   rK   intrd   re   r   rf   rg   ZsetName)	r|   r   r5   r   
platformID	platEncIDlangIDstringr;   r2   r2   r3   r     s,   





zBuilder.build_namec                 C   s|  | j sd S | jd}|s'td }| jd< dttdj }||| j d}d| j v r4| j d |_	d| j v r[td
 }| j d \
|_|_|_|_|_|_|_|_|_|_||_d| j v rf| j d |_d| j v rq| j d |_d| j v r|| j d |_d	| j v r| j d	 |_d
| j v r| j d
 |_d| j v rtd| j d  d |_d| j v r| j d |_d| j v r| j d |_d| j v r|| j d  d| j v r|  | j d }|\|_!|_"d}d| j v r| j d |_#d}d| j v r| j d |_$d}d| j v r| j d |_%d}d| j v r| j d |_&d}dd }t'||j(|_(|dkr&||d |dkr0||d |dkr<||d d S d S )NrA       r   ZfstypepanoseZtypoascenderZtypodescenderZtypolinegapZ	winascentZ
windescentZvendorz'''ZweightclassZ
widthclassZunicoderangeZcodepageranger   Zxheight   Z	capheightZloweropsize   Zupperopsizec                 S   s$   |D ]}t | |st| |d qd S Nr   )hasattrsetattr)r   Zattrsattrr2   r2   r3   	checkattr  s
   
z%Builder.build_OS_2.<locals>.checkattr)ulCodePageRange1ulCodePageRange2)sxHeight
sCapHeightZusDefaultCharZusBreakCharr   )usLowerOpticalPointSizeusUpperOpticalPointSize))rw   r0   r   r   r   Zcalcsizer   ZOS2_format_0r   ZfsTypeZPanoseZbFamilyTypeZbSerifStyleZbWeightZbProportionZ	bContrastZbStrokeVariationZ	bArmStyleZbLetterFormZbMidlineZbXHeightr   ZsTypoAscenderZsTypoDescenderZsTypoLineGapZusWinAscentZusWinDescentr   Z	achVendIDZusWeightClassZusWidthClassZsetUnicodeRangesbuild_codepages_r   r   r   r   r   r   maxversion)r|   r   datar   r   pagesr   r2   r2   r3   r     s   


















zBuilder.build_OS_2c                 C   s\   dD ]}|| j v rt| d|qt|tr|| j d< d S t|tr*|| j d< d S t|)N)ElidedFallbackNameElidedFallbackNameIDz is already set.r   r   )rz   r   rK   r   ri   AssertionError)r|   valuer   tokenr2   r2   r3   setElidedFallbackName  s   


zBuilder.setElidedFallbackNamec                 C   s   d| j vr
g | j d< |jdd | j d D v r!td|j d||jdd | j d D v r8td|j d|| j d | d S )	N
DesignAxesc                 s       | ]}|j V  qd S r8   )r;   r:   rr2   r2   r3   r<   +      z(Builder.addDesignAxis.<locals>.<genexpr>z$DesignAxis already defined for tag "z".c                 s   r  r8   )	axisOrderr  r2   r2   r3   r<   0  r  z+DesignAxis already defined for axis number r~   )rz   r;   r   r  r   )r|   Z
designAxisr   r2   r2   r3   addDesignAxis(  s   

zBuilder.addDesignAxisc                 C   s   d| j vr
g | j d< | j d D ]-}dd |jD dd |jD kr<dd |jD dd |jD kr<|j|jkr<td|q| j d | d S )NAxisValueRecordsc                 S      h | ]}|  qS r2   ZasFear:   nr2   r2   r3   	<setcomp>=      z-Builder.addAxisValueRecord.<locals>.<setcomp>c                 S   r	  r2   r
  r  r2   r2   r3   r  >  r  c                 S   r	  r2   r
  r  r2   r2   r3   r  ?  r  c                 S   r	  r2   r
  r  r2   r2   r3   r  @  r  z8An AxisValueRecord with these values is already defined.)rz   r   	locationsflagsr   r   )r|   ZaxisValueRecordr   Zrecord_r2   r2   r3   addAxisValueRecord7  s&   


zBuilder.addAxisValueRecordc                    s  | j sd S | j d}|stdd | j d}i  g }|D ]}g  |j< q|d ur|D ]u}i }|jdkr:|j|d< t|jdkr|jd }|j}t|dkrZ||d |j	d t|dkrn||d |d |j	d	 t|d
kr|\}	}
}||	|
||j	d  |j 
| q,|dd |jD |j	d |
| q, fdd|D }| jd}|std }| jd< g |_	d| j v r| j d }||}|std| dd n
d| j v r| j d }tj| j|||d d S )Nr  zDesignAxes not definedr  r   r  r   )r   r5   r   )r   ZlinkedValuer5      )ZnominalValueZrangeMinValueZrangeMaxValuer5   c                 S   s   i | ]	}|j |jd  qS )r   )r;   valuesr:   ir2   r2   r3   r   u  r   z&Builder.build_STAT.<locals>.<dictcomp>)r   r5   c                    s&   g | ]}|j |j|j |j d qS ))Zorderingr;   r5   r  )r  r;   r   )r:   r   Z
axisValuesr2   r3   rI   {  s    z&Builder.build_STAT.<locals>.<listcomp>r5   r   zElidedFallbackNameID z; points to a nameID that does not exist in the "name" tabler   )r  ZelidedFallbackName)rz   r   r   r;   r  r   r  r  r   r   r   r0   r   ZgetDebugNameotlZbuildStatTable)r|   rP   ZaxisValueRecordsZformat4_locationsr;   ZavrZ
valuesDictr   r  ZnominalZminValZmaxValZ
designAxesZ	nameTabler   r5   r2   r  r3   r   I  s   













zBuilder.build_STATc                    s  i ddddddddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1  fd2d3|D }g }t dD ]*}|d4 t |d5 |d d5 D ]}||v rv||  d67  < qg||  d77  < qgqUd8d3 |D S )9Ni  r   i  r   i  r   i  r  i     i  r   i     i     i     ij     i     i     i     i     iQ     ie  0   ib  1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?   )ia  i`  i_  i^  i]  i\  iY  iW  iT  i  i  i  iR  i  c                    s   g | ]
}| v r | qS r2   r2   r:   pZ
pages2bitsr2   r3   rI         z,Builder.build_codepages_.<locals>.<listcomp>     10c                 S   s   g | ]}t |d d d qS )N)r   r2  r2   r2   r3   rI     s    )r   r   )r|   r   bitsr  jr2   r4  r3   r     sx   	
!
zBuilder.build_codepages_c                 C   sL   | j s| jsd S t }d|_| | j |_| | j|_td}||_	|S )Nr   r=   )
rn   ro   r   r=   r   buildBASEAxisZ	HorizAxisZVertAxisr   r   )r|   r   r   r2   r2   r3   r     s   zBuilder.buildBASEc                 C   s  |sd S |\}}t  }t  |_||j_t||j_t  |_g |j_t||j_t	|D ]R}t  }|d |_
t  |_d|j_t  |j_||d |jj_g |jj_t|d |jj_|d D ]}t  }d|_||_|jjj| qd|jj| q.|S )Nr   r   r   )r   ZAxisZBaseTagListZBaselineTagr   ZBaseTagCountZBaseScriptListZBaseScriptRecordZBaseScriptCountr   ZBaseScriptTagZ
BaseScriptZBaseLangSysCountZ
BaseValuesindexZDefaultIndexZ	BaseCoordZBaseCoordCountr   Z
Coordinater   )r|   axisbasesscriptsr   recordcZcoordr2   r2   r3   r=    s4   




zBuilder.buildBASEAxisc                 C   s   t  }|  |_t| j| j|_t	| j
| j| j|_|  |_|  |_|jr,dnd|_| jrW| j }|jrWd|_||_| }|| d| jv rW| jd j| t|j|j|j|j|jfsjt|drstd}||_|S d S )Ni  r   i  r?   VarStorer>   )r   r>   buildGDEFGlyphClassDef_GlyphClassDefr  ZbuildAttachListrp   rN   Z
AttachListZbuildLigCaretListrq   rr   ZLigCaretListbuildGDEFMarkAttachClassDef_MarkAttachClassDefbuildGDEFMarkGlyphSetsDef_ZMarkGlyphSetsDefr   rO   ZfinishZVarDatarD  optimizeZremap_device_varidxesr0   r   r   r   r   )r|   r   storeZ
varidx_mapr   r2   r2   r3   r     s@   





	zBuilder.buildGDEFc                 C   s   | j rdd | j  D }n)i }| jD ]	}||  q| jj D ]}|jD ]}|	 D ]}d||< q.q(q#|rBt
 }||_|S d S )Nc                 S      i | ]	\}\}}||qS r2   r2   r:   r   rC  _r2   r2   r3   r     r   z3Builder.buildGDEFGlyphClassDef_.<locals>.<dictcomp>r  )rs   r   r\   r   ZinferGlyphClassesrL   ZmarkClassesr  definitionsglyphSetr   rF  	classDefs)r|   Zclassesr   	markClassmarkClassDefr   r   r2   r2   r3   rE    s    


zBuilder.buildGDEFGlyphClassDef_c                 C   s.   dd | j  D }|sd S t }||_|S )Nc                 S   rL  r2   r2   rM  r2   r2   r3   r   )  r   z8Builder.buildGDEFMarkAttachClassDef_.<locals>.<dictcomp>)rt   r   r   rH  rQ  )r|   rQ  r   r2   r2   r3   rG  (  s   z$Builder.buildGDEFMarkAttachClassDef_c                 C   s<   g }t | j dd dD ]	\}}|| qt|| jS )Nc                 S   s   | d S )Nr   r2   )itemr2   r2   r3   <lambda>3  s    z4Builder.buildGDEFMarkGlyphSetsDef_.<locals>.<lambda>r   )r   rv   r   r   r  ZbuildMarkGlyphSetsDefrN   )r|   Zsetsglyphsid_r2   r2   r3   rI  0  s   z"Builder.buildGDEFMarkGlyphSetsDef_c                 C   s:   d| j vrtd| j d< i | j d _| j| j d jt< d S )NZDebg)r0   r   r   r]   r	   r   r2   r2   r3   r   8  s   
zBuilder.buildDebgc              
   C   s   |dv sJ || j D ]}d |_qg }| j D ]'}|j|krqt||_tt|j| |d d| j| t|j< |	| qz
dd |D }W |S  t
y] } z	tt||j|d }~ww )Nr   )r   r5   r   c                 S   s   g | ]}|  qS r2   )r/   r:   lr2   r2   r3   rI   N  r  z)Builder.buildLookups_.<locals>.<listcomp>)r\   lookup_indexr   r   r   strr   get_lookup_name_r]   r   r#   r   )r|   r;   r   r   Z	otLookupser2   r2   r3   buildLookups_>  s*   



zBuilder.buildLookups_c              
      s  t t|d  }d|_t |_g |j_t |_g |j_t |_| ||j_	i }i }i }dd }t
| j |dD ]\}}|\}	}
}tdd |D }|dkoT|dk}| ||}t|d	krf|sf|sfq;|D ]&}z| j| t| j|d
| j| t|< W qh ty   td Y qhw ||f}||}|d u rt|jj}t }||_t |_| ||j_t||j_t||j_|jj| |||< ||	i |
g | | j |	|
f|kr|||	|
f< q;t
| D ]~\}	}t }|	|_!t" |_"d |j"_#g |j"_$t
| D ]P\}
}t$ }t% |_%d |j%_&||	|
f  d u r0d|j%_'n |j%_' fdd|D |j%_(t|j%j(|j%_)|
dkrS|j%|j"_#q|
|_*|j"j$| qt|j"j$|j"_+|jj| qt|jj|j_,t|jj|j_)t|jj	|j_|S )Nr   c                 S   s(   | d d | d d | d d | d fS )Nr   r   r   r2   )fr2   r2   r3   rU  d  s   ( z#Builder.makeTable.<locals>.<lambda>r   c                 S   s   g | ]
}|j d ur|j qS r8   )rZ  rX  r2   r2   r3   rI   k  r5  z%Builder.makeTable.<locals>.<listcomp>r?   r   r   )r   zWfeaLib.Builder subclass needs upgrading to stash debug information. See fonttools#2065.i  c                    s   g | ]}| kr|qS r2   r2   r  Zreq_feature_indexr2   r3   rI     s
    dflt)-getattrr   r   r   ZScriptRecordr   ZFeatureRecordr   r^  ZLookupr   r^   r   tupleany_feature_variationsr   r]   r[  _replaceKeyErrorwarningswarnr   Z
FeatureTagZFeaturer   ZFeatureParamsri   ZLookupListIndexr   r   r   r_   Z	ScriptTagZScriptZDefaultLangSysZLangSysRecordZLangSysZLookupOrderZReqFeatureIndexZFeatureIndexr   Z
LangSysTagZLangSysCountr   )r|   r;   r   Zfeature_indicesZrequired_feature_indicesrA  ZsortFeatureTagr   r   r   r   feature_tagZlookup_indicesZsize_featureZforce_featureZixZfeature_keyZfeature_indexZfrecZlang_featuresZsrecZlangrecr2   r`  r3   r   S  s   












zBuilder.makeTablec                 C   s   i }d}| j  D ]>\\}}}}g ||< | D ].\}	}
| j|	 }g }|
D ]}|j|kr-q%|jd us4J ||j d}q%|| ||f qq	|r[| D ]\}}t| j||| qNd S d S )NFT)r`   r   r{   r   rZ  r   r&   r0   )r|   r   	table_tagZfeature_varsZhas_any_variationsrS   languageri  
variationsconditionsetbuildersZraw_conditionsetindicesbZconditions_and_lookupsr2   r2   r3   r     s6   


zBuilder.makeFeatureVariationsc                    sX   | j  D ]$\\}}}}||krq| D ]\}}t fdd|D r(  dS qqdS )Nc                 3   s    | ]}|j  kV  qd S r8   )r   )r:   rp  rj  r2   r3   r<     r   z1Builder.any_feature_variations.<locals>.<genexpr>TF)r`   r   r   )r|   ri  rj  rN  r   rl  rm  rn  r2   rq  r3   rd    s   zBuilder.any_feature_variationsc                 C   s(   dd | j  D }||v r|| S d S )Nc                 S   s   i | ]\}}||qS r2   r2   )r:   kvr2   r2   r3   r     s    z,Builder.get_lookup_name_.<locals>.<dictcomp>)rX   r   )r|   r   Zrevr2   r2   r3   r\    s   zBuilder.get_lookup_name_c                 C   s|   |dkr|dkr| j rtd||dkr| jrtd|nd| _||f| j v r4td| | f || j ||f d S )NDFLTra  z_If "languagesystem DFLT dflt" is present, it must be the first of the languagesystem statementszRlanguagesystems using the "DFLT" script tag must precede all other languagesystemsTz1"languagesystem %s %s" has already been specified)rR   r   rW   stripadd)r|   r   r   rk  r2   r2   r3   add_language_system  s*   zBuilder.add_language_systemc                 C   s   | j rt| j S tdhS )N)rt  ra  )rR   r   r   r2   r2   r3   get_default_language_systems_  s   

z%Builder.get_default_language_systems_c                 C   s>   |   | _d| _d | _|| _d| _d | _|dkr|| _d S d S )Nrt  r   r   )rx  rV   rS   rY   r[   rT   rU   rb   r|   r   r5   r2   r2   r3   r      s   

zBuilder.start_featurec                 C   s0   | j d usJ d | _ d | _d | _d| _d | _d S r   )r[   rV   rY   rT   rU   r   r2   r2   r3   r   
  s   
zBuilder.end_featurec                 C   s`   || j v rtd| || jdkrtd||| _d | j |< d | _| jd u r.d| _d | _d S d S )Nz$Lookup "%s" has already been definedr   zpLookup blocks cannot be placed inside 'aalt' features; move it out, and then refer to it with a lookup statementr   )rX   r   r[   rZ   rY   rT   rU   ry  r2   r2   r3   start_lookup_block  s    




zBuilder.start_lookup_blockc                 C   s8   | j d usJ d | _ d | _| jd u rd| _d | _d S d S r   )rZ   rY   r[   rT   rU   r   r2   r2   r3   end_lookup_block$  s   

zBuilder.end_lookup_blockc                 C   s@   || j v s	J |d | _| j | }|d ur| || j d S d S r8   )rX   rY   r   r[   )r|   lookup_namer   r2   r2   r3   add_lookup_call,  s   
zBuilder.add_lookup_callc                 C   s
   || _ d S r8   )rl   )r|   r   Zrevisionr2   r2   r3   set_font_revision3  s   
zBuilder.set_font_revisionc                 C   s   t |dksJ | jdv rtd| j || jd u rtd|d | _| j|| jf}| j|d d|d f}|dks<|rH|rH|d d  | j|< ng | j|< t| j|fg| _|r~| j|f}|| j	v rvtd|
 | j
 | j	| 
 f || j| j	|< d S d S )	Nr  r   r   z7Language statements are not allowed within "feature %s"zCLanguage statements are not allowed within standalone lookup blocksr   ra  r   zPLanguage %s (script %s) has already specified feature %s as its required feature)r   r[   r   rY   rS   r^   r   r   rV   r_   ru  )r|   r   rk  include_defaultrequiredr   r   r2   r2   r3   set_language6  sD   





zBuilder.set_languagec                 C   s~   t |}| j|}|d ur|S t| jd }|| j|< |D ]}|| jv r5| j| \}}td||f |||f| j|< q|S )Nr   z=Glyph %s already has been assigned a MarkAttachmentType at %s)r   ru   r   r   rt   r   )r|   r   rV  rW  r   rN  locr2   r2   r3   getMarkAttachClass_]  s"   

zBuilder.getMarkAttachClass_c                 C   s8   t |}| j|}|d ur|S t| j}|| j|< |S r8   )r   rv   r   r   )r|   r   rV  rW  r2   r2   r3   getMarkFilterSet_o  s   

zBuilder.getMarkFilterSet_c                 C   sT   |d@ }|r|  ||}||d> B }|r"| ||}|dB }|| _nd | _|| _d S )N   r  r  )r  r  rU   rT   )r|   r   r   Z
markAttachZ
markFilterZmarkAttachClassr   r2   r2   r3   set_lookup_flagx  s   
zBuilder.set_lookup_flagc                 C   sp   | j dv rtd| j  || j d u rtd|| j|dfhkr!d S d | _|| _d| _d | _| j|dddd d S )	Nr  z5Script statements are not allowed within "feature %s"zAScript statements are not allowed within standalone lookup blocksra  r   TF)r  r  )r[   r   rV   rY   rS   rT   rU   r  )r|   r   r   r2   r2   r3   
set_script  s&   

zBuilder.set_scriptc                    s>   g }|D ]}|dur|  fdd|D  q| d q|S )zHelper for building chain contextual substitutions

        Given a list of lookup names, finds the LookupBuilder for each name.
        If an input name is None, it gets mapped to a None LookupBuilder.
        Nc                    s   g | ]	} j |jqS r2   )rX   r   r5   rX  r   r2   r3   rI     r   z1Builder.find_lookup_builders_.<locals>.<listcomp>)r   )r|   r   Zlookup_buildersr   r2   r   r3   find_lookup_builders_  s   zBuilder.find_lookup_builders_c                 C   s$   |D ]}| j |t | qd S r8   )rp   r   rQ   r   )r|   r   rV  ZcontourPointsr   r2   r2   r3   add_attach_points  s   zBuilder.add_attach_pointsc                 C   s(   | j dkr
td|| j||f d S )Nr   z9Feature references are only allowed inside "feature aalt")r[   r   ra   r   )r|   r   ZfeatureNamer2   r2   r3   add_feature_reference  s
   
zBuilder.add_feature_referencec                 C      | j | d S r8   )rd   rv  r|   r;   r2   r2   r3   add_featureName     zBuilder.add_featureNamec                 C   r  r8   )rf   rv  r  r2   r2   r3   add_cv_parameter  r  zBuilder.add_cv_parameterc                 C   s.   || j v r| j |  d7  < dS d| j |< dS )zbAdds new items to ``self.cv_num_named_params_``
        or increments the count of existing items.r   N)rh   r  r2   r2   r3   add_to_cv_num_named_params  s   
z"Builder.add_to_cv_num_named_paramsc                 C   s   | j | | d S r8   )rj   r   )r|   	characterr;   r2   r2   r3   add_cv_character  s   zBuilder.add_cv_characterc                 C   s    |r	||f| _ d S ||f| _d S r8   )ro   rn   )r|   r@  rA  verticalr2   r2   r3   set_base_axis  s   zBuilder.set_base_axisc           	      C   sV   | j dkrtd| j  |||||g| _| jD ]\}}||| j f}| j|g  qd S )Nr   z9Parameters statements are not allowed within "feature %s")r[   r   rk   rV   r^   r   )	r|   r   r   r   r   r   r   r   r   r2   r2   r3   set_size_parameters  s   
zBuilder.set_size_parametersc           
      C   s   | j dkr| D ]\}}| j|t }|| q	d S |s#|s#|r-| |||| d S | |t}	| D ]*\}}||	j	v r\||	j	| krPt
d||| ntd||	j	| f |||	j	|< q7d S )Nr   zDRemoving duplicate single substitution from glyph "%s" to "%s" at %sz5Already defined rule for replacing glyph "%s" by "%s")r[   r   rc   r   rQ   rv  add_single_subst_chained_r   r   r   loginfor   )
r|   r   prefixsuffixr   
forceChainZ
from_glyphZto_glyphr   r   r2   r2   r3   add_single_subst  s4   

zBuilder.add_single_substc           
      C   s   |s|s|r'|  |t}| |t}||j|< |jt||hg||g d S |  |t}	||	jv rP||	j| krIt	d|||rEd| nd nt
d| |||	j|< d S )Nz@Removing duplicate multiple substitution from glyph "%s" to %s%sz at r6  z+Already defined substitution for glyph "%s")r   r   r   r   r   rulesr   r"   r  r  r   )
r|   r   r  r   r  Zreplacementsr  chainsubr   r2   r2   r3   add_multiple_subst  s&   

zBuilder.add_multiple_substc           	      C   s   | j dkr| j|t }|| d S |s|r3| |t}| |t}|j	
t||hg||g n| |t}||jv rEtd| |||j|< d S )Nr   z)Already defined alternates for glyph "%s")r[   rc   r   rQ   r   r   r   r   r   r  r   r"   r   r   )	r|   r   r  r   r  replacementr   r  r   r2   r2   r3   add_alternate_subst  s   


zBuilder.add_alternate_substc           
      C   s~   |s|s|r|  |t}| |t}|jt||||g n|  |t}t|s.td|t	t
j| D ]}	||j|	< q5d S Nz!Empty glyph class in substitution)r   r   r   r   r  r   r"   allr   r   	itertoolsproduct	ligatures)
r|   r   r  rV  r  r  r  r  r   r   r2   r2   r3   add_ligature_subst'  s   
zBuilder.add_ligature_substc              	   C   N   t |rt |rt |std|| |t}|jt|||| | d S Nz,Empty glyph class in contextual substitution)r  r   r   r   r  r   r"   r  r|   r   r  rV  r  r   r   r2   r2   r3   add_chain_context_subst=     
zBuilder.add_chain_context_substc                 C   s   |r
t |r
t |std|| |t}|t| }|d u r(| |t}|j	
| |jt|t| g||g d S r  )r  r   r   r   Zfind_chainable_single_substrQ   keysr   r   r   r   r  r   r"   ri   )r|   r   r  r  r   r  r  r2   r2   r3   r  G  s   
z!Builder.add_single_subst_chained_c                 C   s0   |st d|| |t}|j|||f d S r  )r   r   r   r  r   )r|   r   Z
old_prefixZ
old_suffixr   r   r2   r2   r3   add_reverse_chain_single_substU  s   
z&Builder.add_reverse_chain_single_substc                 C   s   |s|s|r|  |||| d S | |t}|D ]6\}}|s#td|| j||dd}	|D ] }
z	|||
|	 W q- tyM } z	tt||j|d }~ww qd S )N%Empty glyph class in positioning ruleFpairPosContext)	add_single_pos_chained_r   r!   r   makeOpenTypeValueRecordadd_posr#   r[  r   )r|   r   r  r  posr  r   rV  r   ZotValueRecordr   r]  r2   r2   r3   add_single_pos^  s    
zBuilder.add_single_posc           	      C   T   |r|s	t d|| |t}| j||dd}| j||dd}|||||| d S Nr  Tr  )r   r   r    r  ZaddClassPair)	r|   r   Zglyphclass1value1Zglyphclass2value2r   v1v2r2   r2   r3   add_class_pair_posn  s   zBuilder.add_class_pair_posc           	      C   r  r  )r   r   r    r  ZaddGlyphPair)	r|   r   Zglyph1r  Zglyph2r  r   r  r  r2   r2   r3   add_specific_pair_posx  s   
zBuilder.add_specific_pair_posc              	   C   s>   |st d|| |t}|||| ||| || d S Nr  )r   r   r   Zadd_attachmentmakeOpenTypeAnchor)r|   r   Z
glyphclassZentryAnchorZ
exitAnchorr   r2   r2   r3   add_cursive_pos  s   


zBuilder.add_cursive_posc           	      C   d   |  |t}| ||| |std||D ]\}}| ||}|D ]}||j|i |j< q"qd S r  )r   r   
add_marks_r   r  r@  r   r5   )	r|   r   r@  marksr   
baseAnchorrR  otBaseAnchorr   r2   r2   r3   add_mark_base_pos  s   
zBuilder.add_mark_base_posc                 C   s|   |  |t}g }|std||D ] }i }| ||| |D ]\}}	| ||||	j< q|| q|D ]}
||j|
< q4d S r  )r   r   r   r  r  r5   r   r  )r|   r   r  Z
componentsr   ZcomponentAnchorsr  ZanchorsZ	ligAnchorrR  r   r2   r2   r3   add_mark_lig_pos  s   
zBuilder.add_mark_lig_posc           	      C   r  r  )r   r   r  r   r  	baseMarksr   r5   )	r|   r   r  r  r   r  rR  r  ZbaseMarkr2   r2   r3   add_mark_mark_pos  s   
zBuilder.add_mark_mark_posc              	   C   r  )N0Empty glyph class in contextual positioning rule)r  r   r   r   r  r   r"   r  r  r2   r2   r3   add_chain_context_pos  r  zBuilder.add_chain_context_posc                 C   s  |r
t |r
t |std|| |t}g }|jD ]\}}}}|| qg }	|D ]=\}
}|d u r8|	d  q*| j||dd}|||
|}|d u rV| 	|t
}|| |
D ]	}|||| qX|	| q*t|t|	ksvJ ||	f|jt|dd |D ||	 d S )Nr  Fr  c                 S   s   g | ]\}}|qS r2   r2   )r:   r   rs  r2   r2   r3   rI     r  z3Builder.add_single_pos_chained_.<locals>.<listcomp>)r  r   r   r   r  r   r   r  Zfind_chainable_single_posr   r!   r  r   r"   )r|   r   r  r  r  r  targetsrN  r   ZsubsrV  r   ZotValuer  r   r2   r2   r3   r    s.   


zBuilder.add_single_pos_chained_c           
      C   s   |D ]>\}}|j D ]6}|j D ].}||jvr'| ||j}|j|f|j|< q|j| d }	|j|	kr>td||	|jf |qq	qdS )z)Helper for add_mark_{base,liga,mark}_pos.r   z&Glyph %s cannot be in both @%s and @%sN)rO  rV  rP  r  r  anchorr5   r   )
r|   r   ZlookupBuilderr  rN  rR  rS  ZmarkZotMarkAnchorZexistingMarkClassr2   r2   r3   r    s$   



zBuilder.add_marks_c                 C   r  r8   )rY   add_subtable_break)r|   r   r2   r2   r3   r    r  zBuilder.add_subtable_breakc                 C   sB   | j |d\}}|r||krtd||f |||f| j |< d S )NNNz0Glyph %s was assigned to a different class at %s)rs   r   r   )r|   r   r   Z
glyphClassZoldClassZoldLocationr2   r2   r3   setGlyphClass_  s   zBuilder.setGlyphClass_c                 C   sd   |D ]	}|  ||d q|D ]	}|  ||d q|D ]	}|  ||d q|D ]	}|  ||d q&d S )Nr   r   r  r  )r  )r|   r   Z
baseGlyphsZligatureGlyphsZ
markGlyphsZcomponentGlyphsr   r2   r2   r3   add_glyphClassDef  s   zBuilder.add_glyphClassDefc                 C   "   |D ]}|| j vr|| j |< qd S r8   )rr   r|   r   rV  Zcaretsr   r2   r2   r3   add_ligatureCaretByIndex_  
   

z!Builder.add_ligatureCaretByIndex_c                 C   r  r8   )rq   r  r2   r2   r3   add_ligatureCaretByPos_  r  zBuilder.add_ligatureCaretByPos_c                 C   s   | j |||||g d S r8   )rm   r   )r|   r   r   r   r   r   r   r2   r2   r3   add_name_record  s   zBuilder.add_name_recordc                 C      || j |< d S r8   )rw   r|   r   r   r2   r2   r3   add_os2_field     zBuilder.add_os2_fieldc                 C   r  r8   )rx   r  r2   r2   r3   add_hhea_field  r  zBuilder.add_hhea_fieldc                 C   r  r8   )ry   r  r2   r2   r3   add_vhea_field  r  zBuilder.add_vhea_fieldc                    sF   d| j vr	tddd | jD   fdd| D }|| j|< d S )NrF   z?Cannot add feature variations to a font without an 'fvar' tablec                 S   s    i | ]}|j |j|j|jfqS r2   )rH   ZminValueZdefaultValueZmaxValue)r:   r?  r2   r2   r3   r     s    z,Builder.add_conditionset.<locals>.<dictcomp>c                    s2   i | ]\}\}}|t | | t | | fqS r2   r'   )r:   r;   ZbottomtopZaxisMapr2   r3   r   $  s    
)r0   r   rP   r   r{   r  r2   r  r3   add_conditionset  s   

zBuilder.add_conditionsetc                 C   s  |du rdS d}d\}}|j durtt|j }|jdur&tt|j}dD ]O}tt||ts3q(t||d durAtd|| j	sItd|t||}| j
|_
|| j	\}}	t||| |	durw|	dkrw|d	krqt|	}nt|	}d
}q(t|j|j|j||}
|rd|
_|
S )zast.Anchor --> otTables.AnchorNFr  )xyZDeviceTable4Can't define a device coordinate and variable scalar5Can't define a variable scalar in a non-variable font    r  Tr  )ZxDeviceTabler  buildDevicedictZyDeviceTablerK   rb  r   r   rO   rP   add_to_variation_storer   r%   ZbuildAnchorr  r  Zcontourpointr   )r|   r   r  variableZdeviceXZdeviceYZdimZ	varscalardefaultr>  Z	otlanchorr2   r2   r3   r  .  s:   





zBuilder.makeOpenTypeAnchorc                 C   s<   i | ]\}}}}| d s|d  |dd  ||fqS )ZReservedr   r   N)
startswithlower)r:   rN  r5   isDevicer2   r2   r3   r   O  s    
zBuilder.<dictcomp>c                 C   s  |sdS i }d}| j  D ]k\}\}}t||d}	|	sq|r(tt|	||< qt|	trt|dd d }
|
d  |
dd  }t||rKt	d|| j
sSt	d|| j|	_|	| j
\}}|||< |durs|d	krst|||
< d
}q|	||< q|r|s|jrddinddi}t|}|S )z&ast.ValueRecord --> otBase.ValueRecordNFr   r  ZDevicer   r  r  r  TZYAdvanceZXAdvance)_VALUEREC_ATTRSr   rb  r  r  r  rK   r   r  r   rO   rP   r  r%   r  Z
buildValue)r|   r   rs  r  Zvrr  ZastNameZotNamer  valZotDeviceNameZfeaDeviceNamer  r>  ZvalRecr2   r2   r3   r  V  s:   





zBuilder.makeOpenTypeValueRecordNF)F)Y__name__
__module____qualname__r   r   r}   r/   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r   r   r=  r   rE  rG  rI  r   r^  r   r   rd  r\  rw  rx  r   r   rz  r{  r}  r~  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   ZvalueRecordFormatr  r  r2   r2   r2   r3   r.   \   s    
F@3+TU-#_	
'	

	
	

!r.   r  )NNF)GZfontTools.miscr   ZfontTools.misc.textToolsr   r   r   r   ZfontTools.feaLib.errorr   Z fontTools.feaLib.lookupDebugInfor   r	   r
   ZfontTools.feaLib.parserr   ZfontTools.feaLib.astr   ZfontTools.feaLib.variableScalarr   ZfontTools.otlLibr   r  ZfontTools.otlLib.maxContextCalcr   ZfontTools.ttLibr   r   ZfontTools.ttLib.tablesr   r   ZfontTools.otlLib.builderr   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   ZfontTools.otlLib.errorr#   ZfontTools.varLib.varStorer$   ZfontTools.varLib.builderr%   ZfontTools.varLib.featureVarsr&   ZfontTools.varLib.modelsr(   collectionsr)   r  ior*   Zloggingrg  r   Z	getLoggerr  r  r4   r7   objectr.   r2   r2   r2   r3   <module>   s8    D


