B
    Sc                @   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ZCd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    r0   7lib/python3.7/site-packages/fontTools/feaLib/builder.pyaddOpenTypeFeatures1   s    
r2   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*   r+   N)r)   r   namer2   )r.   Zfeaturesfilenamer*   r+   r/   r0   r0   r1   addOpenTypeFeaturesFromStringC   s    r5   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 Z9ddpdq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tagr0   r0   r1   	<genexpr>_   s   zBuilder.<genexpr>)
BASEGDEFGPOSGSUBzOS/2headhhear3   vheaSTATc             C   st  || _ t|tr |d  | _| _nd | | _| _| | _d | _d|krh|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   s   g | ]
}|j qS r0   )axisTag)r6   Zaxr0   r0   r1   
<listcomp>{   s    z$Builder.__init__.<locals>.<listcomp>r   F)r<   r;   )6r.   
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_)selfr.   r/   r0   r0   r1   __init__n   sf    


zBuilder.__init__NFc       
         s0   j d krt j j  _  j   |d kr: j}n4t|}| j }|rndt	|}t
d| dd|kr~   d|kr   d|kr   d|kr   d|kr   d	|krΈ   d
|krވ   xdD ]}||krq |} jr || |jjdks:|jjdks:|jjdkrTt| } j|< ||_q| jkr j|= qW t fdddD rd	 jkrt j jd	 _ d|kr؈ ! }|r| jd< nd jkr؈ jd= d|kr " }	|	r|	 jd< nd jkr jd= |s$t#j$%t&r, '  d S )Nz, z9The following tables were requested but are unsupported: .r<   r=   r>   r?   r3   zOS/2r@   )r;   r<   r   c             3   s   | ]}| j kV  qd S )N)r.   )r6   r7   )ru   r0   r1   r8      s    z Builder.build.<locals>.<genexpr>r:   r9   )(rE   r   rF   rG   parser-   supportedTables	frozensetjoinsortedNotImplementedErrorbuild_feature_aalt_
build_head
build_hhea
build_vhea
build_name
build_OS_2
build_STAT	makeTablerY   makeFeatureVariations
ScriptListScriptCountFeatureListFeatureCount
LookupListLookupCountr   r.   tableanyr   usMaxContext	buildGDEF	buildBASEosenvirongetr
   	buildDebg)
ru   r*   r+   ZunsupportedZunsupported_stringr7   r   Z	fontTablegdefbaser0   )ru   r1   r-      sl    




$

zBuilder.buildc             C   s,   || j |}| j|_| j|_| j| |S )N)r.   rM   
lookupflagrN   markFilterSetrU   append)ru   locationbuilder_classresultr0   r0   r1   get_chained_lookup_   s
    zBuilder.get_chained_lookup_c             C   s6   x0| j D ]&\}}|||f}| j|g | qW d S )N)rO   rW   
setdefaultr   )ru   lookupZfeature_namescriptlangkeyr0   r0   r1   add_lookup_to_feature_   s    
zBuilder.add_lookup_to_feature_c             C   s   | j r6t| j |kr6| j j| jkr6| j j| jkr6| j S | jrL| j rLtd||| j|| _ | j| j _| j| j _| j	
| j  | jr| j | j| j< | jr| | j | j | j S )NzOWithin a named lookup block, all rules must be of the same lookup type and flag)rR   typer   rM   r   rN   rS   r   r.   rU   r   rQ   rT   r   )ru   r   r   r0   r0   r1   get_lookup_   s$    

zBuilder.get_lookup_c          	      s  j sjsd S dd j D }xj dg D ]\}  fddj D }|sl dkrltd  |xn|D ]f\}}}}xX|D ]P}t|ts|g}x:|D ]2}x,|  D ]\}	}
||	t	 
|
 qW qW qW qrW q2W dd | D }fd	d| D }|s|sd S d
d j D _j}g _jd |r`|t}||_|rx|t}||_  j| d S )Nc             S   s   i | ]\}}t ||qS r0   )rJ   )r6   gar0   r0   r1   
<dictcomp>  s    z/Builder.build_feature_aalt_.<locals>.<dictcomp>)Naaltc                s*   g | ]"\\}}}}| kr||||fqS r0   r0   )r6   r   r   featurelookups)r3   r0   r1   rC     s   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   )lenrb   )r6   glyphreplr0   r0   r1   r   /  s   c                s.   i | ]&\}}t |d krt| jjd|qS )r   )r   )r   r|   r.   Z
getGlyphID)r6   r   r   )ru   r0   r1   r   4  s   c             S   s*   i | ]"\\}}}}|d kr||||fqS )r   r0   )r6   r   r   r   r   r0   r0   r1   r   ;  s   )rZ   r\   itemsrW   r   rD   rb   ZgetAlternateGlyphsr   rJ   updaterU   start_featurer[   r   r   mappingr   
alternatesend_featureextend)ru   r   r   r   r   r   r   
lookuplistr   r   altsZsingleZmultiZold_lookupsZsingle_lookupZmulti_lookupr0   )r3   ru   r1   r~     sF    



(
zBuilder.build_feature_aalt_c             C   sX   | j s
d S | jd}|sLtd }| jd< |d| j d|_d |_|_| j |_d S )Nr=   s6                                                         g      ?l   e )	re   r.   r   r   	decompiletableVersionZcreatedZmodifiedZfontRevision)ru   r   r0   r0   r1   r   L  s    zBuilder.build_headc             C   s   | j s
d S | jd}|s@td }| jd< |d| j d|_d| j krV| j d |_d| j krl| j d |_d| j kr| j d |_d| j kr| j d |_	d S )Nr>   s$                                       i   ZcaretoffsetZascenderZ	descenderZlinegap)
rq   r.   r   r   r   r   ZcaretOffsetascentdescentlineGap)ru   r   r0   r0   r1   r   W  s    



zBuilder.build_hheac             C   s   | j s
d S | jd}|s@td }| jd< |d| j d|_d| j krV| j d |_d| j krl| j d |_d| j kr| j d |_d S )Nr?   s$                                       i  ZverttypoascenderZverttypodescenderZverttypolinegap)	rr   r.   r   r   r   r   r   r   r   )ru   r   r0   r0   r1   r   h  s    


zBuilder.build_vheac             C   s4   dd |j D }xtddD ]}||kr|S qW d S )Nc             S   s   g | ]
}|j qS r0   )nameID)r6   r3   r0   r0   r1   rC   y  s    z,Builder.get_user_name_id.<locals>.<listcomp>   i  )namesrange)ru   r   ZnameIDsZuser_name_idr0   r0   r1   get_user_name_idw  s    zBuilder.get_user_name_idc             C   s   d }|dkrJt  }| j\|_|_|_|_|| jkrB| j| |_nd|_n|| j	kr| js\n(|| jksjt
t  }d|_| j| |_n|| jkrt  }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FeatureParamsSizerd   
DesignSizeSubfamilyID
RangeStartRangeEndr^   ZSubfamilyNameIDr]   AssertionErrorZFeatureParamsStylisticSetVersionZUINameIDr_   ZFeatureParamsCharacterVariantsFormatr`   r   r   r   r   ra   ZNumNamedParametersZFirstParamUILabelNameIDr   rc   Z	CharCountZ	Character)ru   r7   Zparamsr0   r0   r1   buildFeatureParams~  s:    

zBuilder.buildFeatureParamsc       	      C   s   | j s
d S | jd}|s2td }| jd< g |_x| j D ]}|\}}}}}t|ts|}|| jkr|| jkr| 	|| j|< | j| d k	st
| j| }nD|d | jkr|| jkr| 	|| j|< | j| d k	st
| j| }|||||| q:W d S )Nr3   r   )rf   r.   r   r   r   rD   intr]   r^   r   r   r_   r`   ZsetName)	ru   r   r3   r   
platformID	platEncIDlangIDstringr7   r0   r0   r1   r     s*    




zBuilder.build_namec             C   s  | j s
d S | jd}|sNtd }| jd< dttdj }||| j d}d| j krh| j d |_	d| j krtd
 }| j d \
|_|_|_|_|_|_|_|_|_|_||_d| j kr| j d |_d| j kr| j d |_d| j kr| j d |_d	| j kr| j d	 |_d
| j kr(| j d
 |_d| j krLtd| j d  d |_d| j krd| j d |_d| j kr|| j d |_d| j kr|| j d  d| j kr|  | j d }|\|_!|_"d}d| j kr| j d |_#d}d| j kr| j d |_$d}d| j kr| j d |_%d}d| j kr4| j d |_&d}dd }t'||j(|_(|dkr^||d |dkrr||d |dkr||d d S )NzOS/2    r   ZfstypepanoseZtypoascenderZtypodescenderZtypolinegapZ	winascentZ
windescentZvendorz'''ZweightclassZ
widthclassZunicoderangeZcodepageranger   Zxheight   Z	capheightZloweropsize   Zupperopsizec             S   s(   x"|D ]}t | |st| |d qW d S )Nr   )hasattrsetattr)r   Zattrsattrr0   r0   r1   	checkattr  s    

z%Builder.build_OS_2.<locals>.checkattr)ulCodePageRange1ulCodePageRange2)sxHeight
sCapHeightZusDefaultCharZusBreakCharr   )usLowerOpticalPointSizeusUpperOpticalPointSize))rp   r.   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)ru   r   datar   r   pagesr   r0   r0   r1   r     st    

2






zBuilder.build_OS_2c             C   s`   x&dD ]}|| j krt| d|qW t|tr>|| j d< nt|trT|| j d< nt|d S )N)ElidedFallbackNameElidedFallbackNameIDz is already set.r   r   )rs   r   rD   r   rb   r   )ru   valuer   tokenr0   r0   r1   setElidedFallbackName  s    




zBuilder.setElidedFallbackNamec             C   s   d| j krg | j d< |jdd | j d D krBtd|j d||jdd | j d D krptd|j d|| j d | d S )	N
DesignAxesc             s   s   | ]}|j V  qd S )N)r7   )r6   rr0   r0   r1   r8   )  s    z(Builder.addDesignAxis.<locals>.<genexpr>z$DesignAxis already defined for tag "z".c             s   s   | ]}|j V  qd S )N)	axisOrder)r6   r   r0   r0   r1   r8   .  s    z+DesignAxis already defined for axis number rw   )rs   r7   r   r   r   )ru   Z
designAxisr   r0   r0   r1   addDesignAxis&  s    

zBuilder.addDesignAxisc             C   s   d| j krg | j d< xh| j d D ]Z}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 W | j d | d S )NAxisValueRecordsc             S   s   h | ]}|  qS r0   )asFea)r6   nr0   r0   r1   	<setcomp>;  s    z-Builder.addAxisValueRecord.<locals>.<setcomp>c             S   s   h | ]}|  qS r0   )r   )r6   r   r0   r0   r1   r   <  s    c             S   s   h | ]}|  qS r0   )r   )r6   r   r0   r0   r1   r   =  s    c             S   s   h | ]}|  qS r0   )r   )r6   r   r0   r0   r1   r   >  s    z8An AxisValueRecord with these values is already defined.)rs   r   	locationsflagsr   r   )ru   ZaxisValueRecordr   Zrecord_r0   r0   r1   addAxisValueRecord5  s    


zBuilder.addAxisValueRecordc                s  | j s
d S | j d}|s$tdd | j d}i  g }x|D ]}g  |j< q>W |d k	rRx|D ]}i }|jdkr||j|d< t|jdkr&|jd }|j}t|dkr||d |j	d t|dkr||d |d |j	d	 t|d
kr|\}	}
}||	|
||j	d  |j 
| q`|dd |jD |j	d |
| q`W  fdd|D }| jd}|std }| jd< g |_	d| j kr| j d }||}|std| dd nd| j kr| j d }tj| j|||d d S )Nr   zDesignAxes not definedr   r   r   r   )r   r3   r   )r   ZlinkedValuer3      )ZnominalValueZrangeMinValueZrangeMaxValuer3   c             S   s   i | ]}|j d  |jqS )r   )valuesr7   )r6   ir0   r0   r1   r   s  s    z&Builder.build_STAT.<locals>.<dictcomp>)r   r3   c                s&   g | ]}|j |j|j |j d qS ))Zorderingr7   r3   r   )r   r7   r   )r6   r   )
axisValuesr0   r1   rC   z  s   z&Builder.build_STAT.<locals>.<listcomp>r3   r   zElidedFallbackNameID z; points to a nameID that does not exist in the "name" tabler   )r   ZelidedFallbackName)rs   r   r   r7   r   r   r   r   r   r   r   r.   r   ZgetDebugNameotlZbuildStatTable)ru   rI   ZaxisValueRecordsZformat4_locationsr7   ZavrZ
valuesDictr   r   ZnominalZminValZmaxValZ
designAxesZ	nameTabler   r3   r0   )r   r1   r   G  sr    












zBuilder.build_STATc                 s   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   fd!d"|D }g }xdt dD ]X}|d# xHt |d$ |d d$ D ].}||kr||  d%7  < q||  d&7  < qW qdW d'd" |D S )(Nr   r   r   r      r                              0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?   )i  i  i  i  i  i  i  i  i  ij  i  i  i  i  iQ  ie  ib  ia  i`  i_  i^  i]  i\  iY  iW  iT  i  i  i  iR  i  c                s   g | ]}| kr | qS r0   r0   )r6   p)
pages2bitsr0   r1   rC     s    z,Builder.build_codepages_.<locals>.<listcomp>     10c             S   s   g | ]}t |d d d qS )N)r   )r6   r  r0   r0   r1   rC     s    )r   r   )ru   r   bitsr   jr0   )r  r1   r     sP    
zBuilder.build_codepages_c             C   sL   | j s| jsd S t }d|_| | j |_| | j|_td}||_	|S )Ni   r9   )
rg   rh   r   r9   r   buildBASEAxisZ	HorizAxisZVertAxisr   r   )ru   r   r   r0   r0   r1   r     s    zBuilder.buildBASEc             C   s  |sd S |\}}t  }t  |_||j_t||j_t  |_g |j_t||j_xt	|D ]}t  }|d |_
t  |_d|j_t  |j_||d |jj_g |jj_t|d |jj_x4|d D ](}t  }d|_||_|jjj| qW |jj| q^W |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   )ru   axisbasesscriptsr   recordcZcoordr0   r0   r1   r     s4    




zBuilder.buildBASEAxisc             C   s   t  }|  |_t| j| j|_t	| j
| j| j|_|  |_|  |_|jrXdnd|_| jr| j }|rd|_||_| }|| d| jkr| jd j| t  t|j|j|j|j|jfst|drtd}||_|S d S d S )Ni  i   i  r;   VarStorer:   )r   r:   buildGDEFGlyphClassDef_GlyphClassDefr   ZbuildAttachListri   rG   Z
AttachListZbuildLigCaretListrj   rk   ZLigCaretListbuildGDEFMarkAttachClassDef_MarkAttachClassDefbuildGDEFMarkGlyphSetsDef_ZMarkGlyphSetsDefr   rH   Zfinishr'  optimizeZremap_device_varidxesr.   r   r   Zclear_cacher   r   r   )ru   r   ZstoreZ
varidx_mapr   r0   r0   r1   r     s:    







zBuilder.buildGDEFc             C   s   | j rdd | j  D }nbi }x| jD ]}||  q(W x>| jj D ].}x(|jD ]}x|	 D ]}d||< qfW qXW qLW |rt
 }||_|S d S d S )Nc             S   s   i | ]\}\}}||qS r0   r0   )r6   r   r&  _r0   r0   r1   r     s    z3Builder.buildGDEFGlyphClassDef_.<locals>.<dictcomp>r   )rl   r   rU   r   ZinferGlyphClassesrE   ZmarkClassesr   definitionsglyphSetr   r)  	classDefs)ru   classesr   	markClassmarkClassDefr   r   r0   r0   r1   r(    s    zBuilder.buildGDEFGlyphClassDef_c             C   s.   dd | j  D }|sd S t }||_|S )Nc             S   s   i | ]\}\}}||qS r0   r0   )r6   r   r&  r.  r0   r0   r1   r   (  s    z8Builder.buildGDEFMarkAttachClassDef_.<locals>.<dictcomp>)rm   r   r   r+  r1  )ru   r1  r   r0   r0   r1   r*  '  s    z$Builder.buildGDEFMarkAttachClassDef_c             C   s@   g }x,t | j dd dD ]\}}|| qW t|| jS )Nc             S   s   | d S )Nr   r0   )itemr0   r0   r1   <lambda>2      z4Builder.buildGDEFMarkGlyphSetsDef_.<locals>.<lambda>)r   )r|   ro   r   r   r   ZbuildMarkGlyphSetsDefrG   )ru   Zsetsglyphsid_r0   r0   r1   r,  /  s
    z"Builder.buildGDEFMarkGlyphSetsDef_c             C   s:   d| j kr$td| j d< i | j d _| j| j d jt< d S )NZDebg)r.   r   r   rV   r	   )ru   r0   r0   r1   r   7  s    
zBuilder.buildDebgc          
   C   s   |dkst |x| jD ]
}d |_qW g }xX| jD ]N}|j|krBq2t||_tt|j| |d d| j	| t|j< |
| q2W ydd |D }W n4 tk
r } ztt||j|W d d }~X Y nX |S )N)r;   r<   )r   r3   r   c             S   s   g | ]}|  qS r0   )r-   )r6   lr0   r0   r1   rC   M  s    z)Builder.buildLookups_.<locals>.<listcomp>)r   rU   lookup_indexr   r   r   strr   get_lookup_name_rV   r   r#   r   )ru   r7   r   r   Z	otLookupser0   r0   r1   buildLookups_=  s$    


$zBuilder.buildLookups_c          
      s2  t t|d  }d|_t |_g |j_t |_g |j_t |_| ||j_	i }i }i }dd }xt
| j |dD ]h\}}|\}	}
}tdd |D }|dko|dk}| ||}t|d	kr|s|sqzxZ|D ]R}y,| j| t| j|d
| j| t|< W q tk
r(   td Y qX qW ||f}||}|d krt|jj}t }||_t |_| ||j_t||j_t||j_|jj| |||< ||	i |
g | | j |	|
f|krz|||	|
f< qzW xt
| D ] \}	}t }|	|_!t" |_"d |j"_#g |j"_$xt
| D ]\}
}t$ }t% |_%d |j%_&||	|
f  d kr|d|j%_'n |j%_' fdd|D |j%_(t|j%j(|j%_)|
dkr|j%|j"_#n|
|_*|j"j$| q8W t|j"j$|j"_+|jj| qW t|jj|j_,t|jj|j_)t|jj	|j_|S )Ni   c             S   s(   | d d | d d | d d | d fS )Nr   r   r   r0   )fr0   r0   r1   r6  c  r7  z#Builder.makeTable.<locals>.<lambda>)r   c             S   s   g | ]}|j d k	r|j qS )N)r;  )r6   r:  r0   r0   r1   rC   j  s    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 r0   r0   )r6   r   )req_feature_indexr0   r1   rC     s    dflt)-getattrr   r   r   ZScriptRecordr   ZFeatureRecordr   r?  ZLookupr|   rW   r   tupleany_feature_variationsr   rV   r<  _replaceKeyErrorwarningswarnr   Z
FeatureTagZFeaturer   ZFeatureParamsrb   ZLookupListIndexr   r   r   rX   Z	ScriptTagZScriptZDefaultLangSysZLangSysRecordZLangSysZLookupOrderZReqFeatureIndexZFeatureIndexr   Z
LangSysTagZLangSysCountr   )ru   r7   r   Zfeature_indicesZrequired_feature_indicesr$  ZsortFeatureTagr   r   r   r   feature_tagZlookup_indicesZsize_featureZforce_featureZixZfeature_keyZfeature_indexZfrecZlang_featuresZsrecZlangrecr0   )rA  r1   r   R  s    


 










zBuilder.makeTablec             C   s   i }d}x| j  D ]\\}}}}g ||< xl| D ]`\}	}
| j|	 }g }x6|
D ].}|j|kr`qP|jd k	snt||j d}qPW || ||f q4W qW |rx$| D ]\}}t| j||| qW d S )NFT)	rY   r   rt   r   r;  r   r   r&   r.   )ru   r   	table_tagZfeature_varsZhas_any_variationsrL   languagerJ  
variationsconditionsetbuildersZraw_conditionsetindicesbZconditions_and_lookupsr0   r0   r1   r     s&    


zBuilder.makeFeatureVariationsc                s\   xV| j  D ]H\\}}}}||kr$qx.| D ]"\}}t fdd|D r.dS q.W qW dS )Nc             3   s   | ]}|j  kV  qd S )N)r   )r6   rQ  )rK  r0   r1   r8     s    z1Builder.any_feature_variations.<locals>.<genexpr>TF)rY   r   r   )ru   rJ  rK  r.  r   rM  rN  rO  r0   )rK  r1   rE    s    zBuilder.any_feature_variationsc             C   s(   dd | j  D }||kr$|| S d S )Nc             S   s   i | ]\}}||qS r0   r0   )r6   kvr0   r0   r1   r     s    z,Builder.get_lookup_name_.<locals>.<dictcomp>)rQ   r   )ru   r   Zrevr0   r0   r1   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 krhtd| | f || j ||f d S )NDFLTrB  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)rK   r   rP   stripadd)ru   r   r   rL  r0   r0   r1   add_language_system  s     zBuilder.add_language_systemc             C   s   | j rt| j S tdhS d S )N)rT  rB  )rK   rz   )ru   r0   r0   r1   get_default_language_systems_  s    
z%Builder.get_default_language_systems_c             C   s:   |   | _d| _d | _|| _d| _d | _|dkr6|| _d S )NrT  r   r   )rX  rO   rL   rR   rT   rM   rN   r[   )ru   r   r3   r0   r0   r1   r     s    
zBuilder.start_featurec             C   s0   | j d k	std | _ d | _d | _d| _d | _d S )Nr   )rT   r   rO   rR   rM   rN   )ru   r0   r0   r1   r   	  s    zBuilder.end_featurec             C   s\   || j krtd| || jdkr,td||| _d | j |< d | _| jd krXd| _d | _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   )rQ   r   rT   rS   rR   rM   rN   )ru   r   r3   r0   r0   r1   start_lookup_block  s    



zBuilder.start_lookup_blockc             C   s4   | j d k	std | _ d | _| jd kr0d| _d | _d S )Nr   )rS   r   rR   rT   rM   rN   )ru   r0   r0   r1   end_lookup_block#  s    
zBuilder.end_lookup_blockc             C   s<   || j kst|d | _| j | }|d k	r8| || j d S )N)rQ   r   rR   r   rT   )ru   Zlookup_namer   r0   r0   r1   add_lookup_call+  s
    
zBuilder.add_lookup_callc             C   s
   || _ d S )N)re   )ru   r   Zrevisionr0   r0   r1   set_font_revision2  s    zBuilder.set_font_revisionc             C   s   t |dkst| jdkr*td| j || jd kr>td|d | _| j|| jf}| j|d d|d f}|dksx|r|r|d d  | j|< n
g | j|< t| j|fg| _	|r| j|f}|| j
krtd| | j | j
|  f || j| j
|< d S )	Nr   )r   r   z7Language statements are not allowed within "feature %s"zCLanguage statements are not allowed within standalone lookup blocksr   rB  r   zPLanguage %s (script %s) has already specified feature %s as its required feature)r   r   rT   r   rR   rL   rW   r   rz   rO   rX   rU  )ru   r   rL  include_defaultrequiredr   r   r0   r0   r1   set_language5  s6    




zBuilder.set_languagec             C   s   t |}| j|}|d k	r |S t| jd }|| j|< xD|D ]<}|| jkrl| j| \}}td||f |||f| j|< q>W |S )Nr   z=Glyph %s already has been assigned a MarkAttachmentType at %s)rz   rn   r   r   rm   r   )ru   r   r8  r9  r   r.  Zlocr0   r0   r1   getMarkAttachClass_\  s    


zBuilder.getMarkAttachClass_c             C   s8   t |}| j|}|d k	r |S t| j}|| j|< |S )N)rz   ro   r   r   )ru   r   r8  r9  r0   r0   r1   getMarkFilterSet_n  s    

zBuilder.getMarkFilterSet_c             C   sT   |d@ }|r$|  ||}||d> B }|rD| ||}|dB }|| _nd | _|| _d S )N   r   r  )r`  ra  rN   rM   )ru   r   r   Z
markAttachZ
markFilterZmarkAttachClassr   r0   r0   r1   set_lookup_flagw  s    zBuilder.set_lookup_flagc             C   sp   | j dkrtd| j  || j d kr.td|| j|dfhkrBd S d | _|| _d| _d | _| j|dddd d S )	N)r   r   z5Script statements are not allowed within "feature %s"zAScript statements are not allowed within standalone lookup blocksrB  r   TF)r]  r^  )rT   r   rO   rR   rL   rM   rN   r_  )ru   r   r   r0   r0   r1   
set_script  s     

zBuilder.set_scriptc                sB   g }x8|D ]0}|dk	r0|  fdd|D  q
| d q
W |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 r0   )rQ   r   r3   )r6   r:  )ru   r0   r1   rC     s    z1Builder.find_lookup_builders_.<locals>.<listcomp>)r   )ru   r   Zlookup_buildersr   r0   )ru   r1   find_lookup_builders_  s    
zBuilder.find_lookup_builders_c             C   s(   x"|D ]}| j |t | qW d S )N)ri   r   rJ   r   )ru   r   r8  ZcontourPointsr   r0   r0   r1   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")rT   r   rZ   r   )ru   r   ZfeatureNamer0   r0   r1   add_feature_reference  s    
zBuilder.add_feature_referencec             C   s   | j | d S )N)r]   rV  )ru   r7   r0   r0   r1   add_featureName  s    zBuilder.add_featureNamec             C   s   | j | d S )N)r_   rV  )ru   r7   r0   r0   r1   add_cv_parameter  s    zBuilder.add_cv_parameterc             C   s,   || j kr| j |  d7  < n
d| j |< dS )zbAdds new items to ``self.cv_num_named_params_``
        or increments the count of existing items.r   N)ra   )ru   r7   r0   r0   r1   add_to_cv_num_named_params  s    
z"Builder.add_to_cv_num_named_paramsc             C   s   | j | | d S )N)rc   r   )ru   	characterr7   r0   r0   r1   add_cv_character  s    zBuilder.add_cv_characterc             C   s   |r||f| _ n
||f| _d S )N)rh   rg   )ru   r#  r$  verticalr0   r0   r1   set_base_axis  s    zBuilder.set_base_axisc       	      C   sZ   | j dkrtd| j  |||||g| _x,| jD ]"\}}||| j f}| j|g  q0W d S )Nr   z9Parameters statements are not allowed within "feature %s")rT   r   rd   rO   rW   r   )	ru   r   r   r   r   r   r   r   r   r0   r0   r1   set_size_parameters  s    
zBuilder.set_size_parametersc       
      C   s   | j dkr>x.| D ]"\}}| j|t }|| qW d S |sJ|sJ|r^| |||| d S | |t}	x`| D ]T\}}||	j	kr||	j	| krt
d||| ntd||	j	| f |||	j	|< qtW d S )Nr   zDRemoving duplicate single substitution from glyph "%s" to "%s" at %sz5Already defined rule for replacing glyph "%s" by "%s")rT   r   r\   r   rJ   rV  add_single_subst_chained_r   r   r   loginfor   )
ru   r   prefixsuffixr   
forceChainZ
from_glyphZto_glyphr   r   r0   r0   r1   add_single_subst  s,    

zBuilder.add_single_substc       
      C   s   |s|s|rN|  |t}| |t}||j|< |jt||hg||g d S |  |t}	||	jkr||	j| krt	d|||rd| nd nt
d| |||	j|< d S )Nz@Removing duplicate multiple substitution from glyph "%s" to %s%sz at r  z+Already defined substitution for glyph "%s")r   r   r   r   r   rulesr   r"   rq  rr  r   )
ru   r   rs  r   rt  Zreplacementsru  chainsubr   r0   r0   r1   add_multiple_subst  s"    

zBuilder.add_multiple_substc       	      C   s   | j dkr(| j|t }|| d S |s0|rf| |t}| |t}|j	
t||hg||g n| |t}||jkrtd| |||j|< d S )Nr   z)Already defined alternates for glyph "%s")rT   r\   r   rJ   r   r   r   r   r   rw  r   r"   r   r   )	ru   r   rs  r   rt  replacementr   rx  r   r0   r0   r1   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|x t	t
j| D ]}	||j|	< qlW d S )Nz!Empty glyph class in substitution)r   r   r   r   rw  r   r"   allr   r|   	itertoolsproduct	ligatures)
ru   r   rs  r8  rt  r{  ru  rx  r   r   r0   r0   r1   add_ligature_subst&  s    
zBuilder.add_ligature_substc          	   C   sN   t |rt |rt |s"td|| |t}|jt|||| | d S )Nz,Empty glyph class in contextual substitution)r}  r   r   r   rw  r   r"   re  )ru   r   rs  r8  rt  r   r   r0   r0   r1   add_chain_context_subst<  s    
zBuilder.add_chain_context_substc             C   s   |rt |rt |std|| |t}|t| }|d krP| |t}|j	
| |jt|t| g||g d S )Nz,Empty glyph class in contextual substitution)r}  r   r   r   Zfind_chainable_single_substrJ   keysr   r   r   r   rw  r   r"   rb   )ru   r   rs  rt  r   rx  ry  r0   r0   r1   rp  F  s    
z!Builder.add_single_subst_chained_c             C   s0   |st d|| |t}|j|||f d S )Nz!Empty glyph class in substitution)r   r   r   rw  r   )ru   r   Z
old_prefixZ
old_suffixr   r   r0   r0   r1   add_reverse_chain_single_substT  s    
z&Builder.add_reverse_chain_single_substc             C   s   |s|s|r|  |||| n| |t}x|D ]|\}}|sFtd|| j||dd}	xT|D ]L}
y|||
|	 W q\ tk
r } ztt||j|W d d }~X Y q\X q\W q0W d S )Nz%Empty glyph class in positioning ruleF)pairPosContext)	add_single_pos_chained_r   r!   r   makeOpenTypeValueRecordadd_posr#   r<  r   )ru   r   rs  rt  posru  r   r8  r   ZotValueRecordr   r>  r0   r0   r1   add_single_pos]  s    

zBuilder.add_single_posc       	      C   sT   |r|st d|| |t}| j||dd}| j||dd}|||||| d S )Nz%Empty glyph class in positioning ruleT)r  )r   r   r    r  ZaddClassPair)	ru   r   Zglyphclass1value1Zglyphclass2value2r   v1v2r0   r0   r1   add_class_pair_posm  s    zBuilder.add_class_pair_posc       	      C   sT   |r|st d|| |t}| j||dd}| j||dd}|||||| d S )Nz%Empty glyph class in positioning ruleT)r  )r   r   r    r  ZaddGlyphPair)	ru   r   Zglyph1r  Zglyph2r  r   r  r  r0   r0   r1   add_specific_pair_posw  s    
zBuilder.add_specific_pair_posc          	   C   s>   |st d|| |t}|||| ||| || d S )Nz%Empty glyph class in positioning rule)r   r   r   Zadd_attachmentmakeOpenTypeAnchor)ru   r   Z
glyphclassZentryAnchorZ
exitAnchorr   r0   r0   r1   add_cursive_pos  s    

zBuilder.add_cursive_posc       	      C   sl   |  |t}| ||| |s(td|x>|D ]6\}}| ||}x |D ]}||j|i |j< qHW q.W d S )Nz%Empty glyph class in positioning rule)r   r   
add_marks_r   r  r#  r   r3   )	ru   r   r#  marksr   
baseAnchorr3  otBaseAnchorr   r0   r0   r1   add_mark_base_pos  s    

zBuilder.add_mark_base_posc             C   s   |  |t}g }|std|xL|D ]D}i }| ||| x"|D ]\}}	| ||||	j< q@W || q$W x|D ]}
||j|
< qrW d S )Nz%Empty glyph class in positioning rule)r   r   r   r  r  r3   r   r  )ru   r   r  Z
componentsr   ZcomponentAnchorsr  ZanchorsZ	ligAnchorr3  r   r0   r0   r1   add_mark_lig_pos  s    


zBuilder.add_mark_lig_posc       	      C   sl   |  |t}| ||| |s(td|x>|D ]6\}}| ||}x |D ]}||j|i |j< qHW q.W d S )Nz%Empty glyph class in positioning rule)r   r   r  r   r  	baseMarksr   r3   )	ru   r   r  r  r   r  r3  r  ZbaseMarkr0   r0   r1   add_mark_mark_pos  s    

zBuilder.add_mark_mark_posc          	   C   sN   t |rt |rt |s"td|| |t}|jt|||| | d S )Nz0Empty glyph class in contextual positioning rule)r}  r   r   r   rw  r   r"   re  )ru   r   rs  r8  rt  r   r   r0   r0   r1   add_chain_context_pos  s    
zBuilder.add_chain_context_posc             C   s  |rt |rt |std|| |t}g }x |jD ]\}}}}|| q6W g }	x|D ]~\}
}|d krv|	d  qZ| j||dd}|||
|}|d kr| 	|t
}|| x|
D ]}|||| qW |	| qZW t|t|	kst||	f|jt|dd |D ||	 d S )Nz0Empty glyph class in contextual positioning ruleF)r  c             S   s   g | ]\}}|qS r0   r0   )r6   r   rS  r0   r0   r1   rC     s    z3Builder.add_single_pos_chained_.<locals>.<listcomp>)r}  r   r   r   rw  r   r   r  Zfind_chainable_single_posr   r!   r  r   r   r"   )ru   r   rs  rt  r  rx  Ztargetsr.  r   Zsubsr8  r   ZotValuery  r   r0   r0   r1   r    s,    



zBuilder.add_single_pos_chained_c       
      C   s   x|D ]\}}xz|j D ]p}xj|j D ]\}||jkrT| ||j}|j|f|j|< q&|j| d }	|j|	kr&td||	|jf |q&W qW qW dS )z)Helper for add_mark_{base,liga,mark}_pos.r   z&Glyph %s cannot be in both @%s and @%sN)r/  r8  r0  r  r  anchorr3   r   )
ru   r   ZlookupBuilderr  r.  r3  r4  ZmarkZotMarkAnchorZexistingMarkClassr0   r0   r1   r    s    

zBuilder.add_marks_c             C   s   | j | d S )N)rR   add_subtable_break)ru   r   r0   r0   r1   r    s    zBuilder.add_subtable_breakc             C   sB   | j |d\}}|r0||kr0td||f |||f| j |< d S )N)NNz0Glyph %s was assigned to a different class at %s)rl   r   r   )ru   r   r   Z
glyphClassZoldClassZoldLocationr0   r0   r1   setGlyphClass_  s    zBuilder.setGlyphClass_c             C   st   x|D ]}|  ||d qW x|D ]}|  ||d q"W x|D ]}|  ||d q>W x|D ]}|  ||d qZW d S )Nr   r   r   r   )r  )ru   r   Z
baseGlyphsZligatureGlyphsZ
markGlyphsZcomponentGlyphsr   r0   r0   r1   add_glyphClassDef  s    



zBuilder.add_glyphClassDefc             C   s&   x |D ]}|| j kr|| j |< qW d S )N)rk   )ru   r   r8  caretsr   r0   r0   r1   add_ligatureCaretByIndex_  s    

z!Builder.add_ligatureCaretByIndex_c             C   s&   x |D ]}|| j kr|| j |< qW d S )N)rj   )ru   r   r8  r  r   r0   r0   r1   add_ligatureCaretByPos_  s    

zBuilder.add_ligatureCaretByPos_c             C   s   | j |||||g d S )N)rf   r   )ru   r   r   r   r   r   r   r0   r0   r1   add_name_record  s    zBuilder.add_name_recordc             C   s   || j |< d S )N)rp   )ru   r   r   r0   r0   r1   add_os2_field  s    zBuilder.add_os2_fieldc             C   s   || j |< d S )N)rq   )ru   r   r   r0   r0   r1   add_hhea_field  s    zBuilder.add_hhea_fieldc             C   s   || j |< d S )N)rr   )ru   r   r   r0   r0   r1   add_vhea_field  s    zBuilder.add_vhea_fieldc                sF   d| j krtddd | jD   fdd| D }|| j|< d S )NrA   z?Cannot add feature variations to a font without an 'fvar' tablec             S   s    i | ]}|j |j|jf|jqS r0   )ZminValueZdefaultValueZmaxValuerB   )r6   r"  r0   r0   r1   r     s   z,Builder.add_conditionset.<locals>.<dictcomp>c                s2   i | ]*\}\}}t | | t | | f|qS r0   )r'   )r6   r7   Zbottomtop)axisMapr0   r1   r   #  s   )r.   r   rI   r   rt   )ru   r   r   r0   )r  r1   add_conditionset  s    


zBuilder.add_conditionsetc             C   s  |dkrdS d}d\}}|j dk	r2tt|j }|jdk	rLtt|j}xdD ]}tt||tshqRt||d dk	rtd|| j	std|t||}| j
|_
|| j	\}}	t||| |	dk	rR|	dkrR|d	krt|	}nt|	}d
}qRW t|j|j|j||}
|rd|
_|
S )zast.Anchor --> otTables.AnchorNF)NN)xyZDeviceTablez4Can't define a device coordinate and variable scalarz5Can't define a variable scalar in a non-variable fontl    r  Tr   )ZxDeviceTabler   buildDevicedictZyDeviceTablerD   rC  r   r   rH   rI   add_to_variation_storer   r%   ZbuildAnchorr  r  Zcontourpointr   )ru   r   r  variableZdeviceXZdeviceYZdimZ	varscalardefaultr!  Z	otlanchorr0   r0   r1   r  -  s8    






zBuilder.makeOpenTypeAnchorc             C   s<   i | ]4\}}}}| d s||f|d  |dd  qS )ZReservedr   r   N)
startswithlower)r6   r.  r3   isDevicer0   r0   r1   r   N  s   
zBuilder.<dictcomp>c             C   s(  |sdS i }d}x| j  D ]\}\}}t||d}	|	s:q|rRtt|	||< qt|	tr|dd d }
|
d  |
dd  }t||rt	d|| j
st	d|| j|	_|	| j
\}}|||< |dk	r|d	krt|||
< d
}q|	||< qW |r|s|jrddinddi}t|}|S )z&ast.ValueRecord --> otBase.ValueRecordNFr   r   ZDevicer   z4Can't define a device coordinate and variable scalarz5Can't define a variable scalar in a non-variable fontl    TZYAdvanceZXAdvance)_VALUEREC_ATTRSr   rC  r   r  r  rD   r   r  r   rH   rI   r  r%   rm  Z
buildValue)ru   r   rS  r  Zvrr  ZastNameZotNamer  valZotDeviceNameZfeaDeviceNamer  r!  ZvalRecr0   r0   r1   r  U  s8    




zBuilder.makeOpenTypeValueRecord)NF)F)Y__name__
__module____qualname__rz   ry   rv   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   rE  r=  rW  rX  r   r   rY  rZ  r[  r\  r_  r`  ra  rc  rd  re  rf  rg  rh  ri  rj  rl  rn  ro  rv  rz  r|  r  r  rp  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  r0   r0   r0   r1   r,   \   s   
F
>3+TU-$_	
'	

	
	

!
r,   )NF)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loggingrH  r   Z	getLoggerr  rq  r2   r5   objectr,   r0   r0   r0   r1   <module>   s4   D


