U
    Dvfz                    @   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l6m7Z7m8Z8 d dl9m:Z: d dl;Z;d dl<Z<d dl=m>Z> d dl?Z?d dl@Z@d dlAZAe?BeCZDdddZEdddZFG dd deGZHd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piecewiseLinearMap)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   </tmp/pip-unpacked-wheel-qlge9rch/fontTools/feaLib/builder.pyaddOpenTypeFeatures2   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   featuresfilenamer,   r-   r1   r2   r2   r3   addOpenTypeFeaturesFromStringD   s    r8   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 ZUdd ZVdd eWjXD ZYdd ZZd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   sz  || _ 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 | _5i | _6d S )Nfvarc                 S   s   g | ]
}|j qS r2   )axisTag)r;   Zaxr2   r2   r3   
<listcomp>{   s     z$Builder.__init__.<locals>.<listcomp>r   F)rA   r@   )7r0   
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_model_cache)selfr0   r1   r2   r2   r3   __init__n   sj    


zBuilder.__init__NFc           
         s,   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ވ   dD ]}||krq |} jr || |jjdks8|jjdks8|jjdkrRt| } j|< ||_q| jkr j|= qt 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: .rA   rC   rD   rE   r5   rB   rF   r@   rA   r   c                 3   s   | ]}| j kV  qd S r9   )r0   r:   r|   r2   r3   r=      s     z Builder.build.<locals>.<genexpr>r?   r>   )(rK   r   rL   rM   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	buildGDEF	buildBASEosenvirongetr
   	buildDebg)
r|   r,   r-   unsupportedZunsupported_stringr<   r   Z	fontTablegdefbaser2   r   r3   r/      st    








$

zBuilder.buildc                 C   s,   || j |}| j|_| j|_| j| |S r9   )r0   rS   
lookupflagrT   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 r9   )rU   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 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)rX   typer   rS   r   rT   rY   r   r0   r[   r   rW   rZ   r   )r|   r   r   r2   r2   r3   get_lookup_  s.    

zBuilder.get_lookup_c              
      s  | j s| jsd S dd | j D }| j dg D ]\}fdd| j D }|spdkrptd|f  q0|D ]j\}}}}|D ]X}t|ts|g}|D ]>}|  D ],\}	}
|	|	g   
 fdd	|
D  qqqqtq0d
d | D }dd | D }|s|sd S dd | j D | _| j}g | _| | jd |r^| |t}||_|rv| |t}||_|   | j
| d S )Nc                 S   s   i | ]\}}|t |qS r2   )rh   )r;   gar2   r2   r3   
<dictcomp>$  s      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   &  s   z/Builder.build_feature_aalt_.<locals>.<listcomp>r   z#%s: Feature %s has not been definedc                 3   s   | ]}| kr|V  qd S r9   r2   r;   r   )alts_for_glyphr2   r3   r=   6  s     z.Builder.build_feature_aalt_.<locals>.<genexpr>c                 S   s&   i | ]\}}t |d kr||d qS )   r   lenr;   glyphreplr2   r2   r3   r   9  s      c                 S   s"   i | ]\}}t |d kr||qS )r   r   r   r2   r2   r3   r   <  s       c                 S   s*   i | ]"\\}}}}|d kr|||f|qS )r   r2   r   r2   r2   r3   r   ?  s    )r`   rb   itemsr]   warningswarnrJ   rh   ZgetAlternateGlyphsr   extendr[   start_featurera   r   r   mappingr   
alternatesend_feature)r|   r   r   r   r   r   r   
lookuplistr   r   altsZsingleZmultiZold_lookupsZsingle_lookupZmulti_lookupr2   )r   r5   r3   r     sP    

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 )NrC   s6                                                         g      ?l   e )	rk   r0   r   r   	decompiletableVersioncreatedmodifiedZfontRevisionr|   r   r2   r2   r3   r   P  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 )NrD   $                                          ZcaretoffsetZascenderZ	descenderZlinegap)
rw   r0   r   r   r   r   ZcaretOffsetascentdescentlineGapr   r2   r2   r3   r   [  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 )NrE   r   i  ZverttypoascenderZverttypodescenderZverttypolinegap)	rx   r0   r   r   r   r   r   r   r   r   r2   r2   r3   r   l  s    


zBuilder.build_vheac                 C   s4   dd |j D }tddD ]}||kr|  S qd S )Nc                 S   s   g | ]
}|j qS r2   )nameID)r;   r5   r2   r2   r3   rI   }  s     z,Builder.get_user_name_id.<locals>.<listcomp>   i  )namesrange)r|   r   ZnameIDsZuser_name_idr2   r2   r3   get_user_name_id{  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FeatureParamsSizerj   
DesignSizeSubfamilyID
RangeStartRangeEndrd   ZSubfamilyNameIDrc   AssertionErrorZFeatureParamsStylisticSetVersionZUINameIDre   ZFeatureParamsCharacterVariantsFormatrf   r   r   r   r   rg   ZNumNamedParametersZFirstParamUILabelNameIDr   ri   Z	CharCountZ	Character)r|   r<   paramsr2   r2   r3   buildFeatureParams  sT    

    zBuilder.buildFeatureParamsc           	      C   s   | j s
d S | jd}|s2td }| jd< g |_| 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| }|||||| q8|j  d S )Nr5   r   )rl   r0   r   r   r   rJ   intrc   rd   r   r   re   rf   setNamesort)	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}|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 )NrB       r   ZfstypepanoseZtypoascenderZtypodescenderZtypolinegapZ	winascentZ
windescent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   attrsattrr2   r2   r3   	checkattr  s    
z%Builder.build_OS_2.<locals>.checkattr)ulCodePageRange1ulCodePageRange2)sxHeight
sCapHeightZusDefaultCharZusBreakCharr   )usLowerOpticalPointSizeusUpperOpticalPointSize))rv   r0   r   r   r   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 krt| d|qt|tr:|| j d< nt|trP|| j d< nt|d S )N)ElidedFallbackNameElidedFallbackNameIDz is already set.r  r  )ry   r   rJ   r   rh   r   )r|   valuer   tokenr2   r2   r3   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 r9   )r<   r;   rr2   r2   r3   r=   .  s     z(Builder.addDesignAxis.<locals>.<genexpr>z$DesignAxis already defined for tag "z".c                 s   s   | ]}|j V  qd S r9   )	axisOrderr
  r2   r2   r3   r=   3  s     z+DesignAxis already defined for axis number r~   )ry   r<   r   r  r   )r|   Z
designAxisr   r2   r2   r3   addDesignAxis+  s    

zBuilder.addDesignAxisc                 C   s   d| j krg | j d< | 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| j d | d S )NAxisValueRecordsc                 S   s   h | ]}|  qS r2   ZasFear;   nr2   r2   r3   	<setcomp>@  s     z-Builder.addAxisValueRecord.<locals>.<setcomp>c                 S   s   h | ]}|  qS r2   r  r  r2   r2   r3   r  A  s     c                 S   s   h | ]}|  qS r2   r  r  r2   r2   r3   r  B  s     c                 S   s   h | ]}|  qS r2   r  r  r2   r2   r3   r  C  s     z8An AxisValueRecord with these values is already defined.)ry   r   	locationsflagsr   r   )r|   ZaxisValueRecordr   Zrecord_r2   r2   r3   addAxisValueRecord:  s$    


zBuilder.addAxisValueRecordc                    s  | j s
d S | j d}|s$tdd | j d}i  g }|D ]}g  |j< q<|d k	rJ|D ]}i }|jdkrv|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 
| qZ|dd |jD |j	d |
| qZ 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  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   x  s      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)ry   r   r   r<   r  r   r  r  updater   r   r0   r   ZgetDebugNameotlZbuildStatTable)r|   rO   ZaxisValueRecordsZformat4_locationsr<   ZavrZ
valuesDictr   r  ZnominalZminValZmaxValZ
designAxesZ	nameTabler   r5   r2   r  r3   r   L  s    











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 }t dD ]T}|d# t |d$ |d d$ D ].}||kr||  d%7  < q||  d&7  < qqbd'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 r2   r2   r;   pZ
pages2bitsr2   r3   rI     s      z,Builder.build_codepages_.<locals>.<listcomp>     10c                 S   s   g | ]}t |d d d qS )N)r   r7  r2   r2   r3   rI     s     )r   r   )r|   r  bitsr  jr2   r9  r3   r     sR    !
zBuilder.build_codepages_c                 C   sL   | j s| jsd S t }d|_| | j |_| | j|_td}||_	|S )Nr   r>   )
rm   rn   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 ]}t  }|d |_
t  |_d|j_t  |j_||d |jj_g |jj_t|d |jj_|d D ](}t  }d|_||_|jjj| q|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   rA    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| | j  t|j|j|j|j|jfst|drtd}||_|S d S d S )Ni  r   i  r@   VarStorer?   )r   r?   buildGDEFGlyphClassDef_GlyphClassDefr  ZbuildAttachListro   rM   Z
AttachListZbuildLigCaretListrp   rq   ZLigCaretListbuildGDEFMarkAttachClassDef_MarkAttachClassDefbuildGDEFMarkGlyphSetsDef_ZMarkGlyphSetsDefr   rN   finishrH  optimizeZremap_device_varidxesr0   r   r{   clearr   r   r   )r|   r   storeZ
varidx_mapr   r2   r2   r3   r     sF    
  





	zBuilder.buildGDEFc                 C   s   | j rdd | j  D }nRi }| jD ]}||  q&| jj D ]&}|jD ]}|	 D ]}d||< q\qPqF|rt
 }||_|S d S d S )Nc                 S   s   i | ]\}\}}||qS r2   r2   r;   r   rG  _r2   r2   r3   r     s    
  z3Builder.buildGDEFGlyphClassDef_.<locals>.<dictcomp>r  )rr   r   r[   r  ZinferGlyphClassesrK   ZmarkClassesr  definitionsglyphSetr   rJ  	classDefs)r|   classesr   	markClassmarkClassDefr   r   r2   r2   r3   rI    s    

zBuilder.buildGDEFGlyphClassDef_c                 C   s.   dd | j  D }|sd S t }||_|S )Nc                 S   s   i | ]\}\}}||qS r2   r2   rR  r2   r2   r3   r   -  s    
  z8Builder.buildGDEFMarkAttachClassDef_.<locals>.<dictcomp>)rs   r   r   rL  rV  )r|   rV  r   r2   r2   r3   rK  ,  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>7      z4Builder.buildGDEFMarkGlyphSetsDef_.<locals>.<lambda>r   )r   ru   r   r   r  ZbuildMarkGlyphSetsDefrM   )r|   Zsetsglyphsid_r2   r2   r3   rM  4  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)r0   r   r  r\   r	   r   r2   r2   r3   r   <  s    
zBuilder.buildDebgc                 C   s  |dkst || jD ]
}d |_qg }| jD ]N}|j|kr<q,t||_tt|j| |d d| j	| t|j< |
| q,g }|D ]}z|
|  W q tk
r } ztt||j|W 5 d }~X Y q tk
r } z*| j	| t|j j}tt|||W 5 d }~X Y qX q|S )Nr   )r   r5   r   )r   r[   lookup_indexr   r   r   strr   get_lookup_name_r\   r   r/   r#   r   	Exception)r|   r<   r   r   Z	otLookupsler   r2   r2   r3   buildLookups_B  s0    



"$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 ]d\}}|\}	}
}tdd |D }|dko|dk}| ||}t|d	kr|s|sqv|D ]R}z,| j| t| j|d
| j| t|< W q tk
r"   td Y qX q||f}||}|d krt|jj}t }||_t |_| ||j_t||j_t||j_|jj| |||< ||	i |
g | | j |	|
f|krv|||	|
f< qvt
| D ]\}	}t }|	|_!t" |_"d |j"_#g |j"_$t
| D ]\}
}t$ }t% |_%d |j%_&||	|
f  d krjd|j%_'n |j%_' fdd|D |j%_(t|j%j(|j%_)|
dkr|j%|j"_#n|
|_*|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   r[  m  r\  z#Builder.makeTable.<locals>.<lambda>r]  c                 S   s   g | ]}|j d k	r|j qS r9   )r`  r;   rd  r2   r2   r3   rI   t  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 r2   r2   r  Zreq_feature_indexr2   r3   rI     s     dflt)-getattrr   r   r   ZScriptRecordr   ZFeatureRecordr   rf  ZLookupr   r]   r   tupleany_feature_variationsr   r\   ra  _replaceKeyErrorr   r   r   Z
FeatureTagZFeaturer   ZFeatureParamsrh   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_indicesrE  ZsortFeatureTagr   r   r   r   feature_tagZlookup_indicesZsize_featureZforce_featureixZfeature_keyZfeature_indexZfrecZlang_featuresZsrecZlangrecr2   ri  r3   r   \  s    













zBuilder.makeTablec                 C   s   i }d}| j  D ]|\\}}}}g ||< | D ]\\}}	| j| }
g }|	D ].}|j|krZqJ|jd k	sht||j d}qJ|| |
|f q0q|r| D ]\}}t| j||| qd S )NFT)	r_   r   rz   r   r`  r   r   r&   r0   )r|   r   	table_tagZfeature_varsZhas_any_variationsrS  rp  
variationsconditionsetbuildersZraw_conditionsetindicesbZconditions_and_lookupsr2   r2   r3   r     s,    

   zBuilder.makeFeatureVariationsc                    sX   | j  D ]H\\}}}}||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 r9   )r   )r;   rw  rr  r2   r3   r=     s     z1Builder.any_feature_variations.<locals>.<genexpr>TF)r_   r   r   )r|   rp  rr  rS  r   rs  rt  ru  r2   rx  r3   rm    s    zBuilder.any_feature_variationsc                 C   s(   dd | j  D }||k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>)rW   r   )r|   r   revr2   r2   r3   rb    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DFLTrj  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)rQ   r   rV   stripadd)r|   r   r   languager2   r2   r3   add_language_system  s(    zBuilder.add_language_systemc                 C   s   | j rt| j S tdhS d S )N)r|  rj  )rQ   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r6|| _d S )Nr|  r   r   )r  rU   rR   rX   rZ   rS   rT   ra   r|   r   r5   r2   r2   r3   r     s    
zBuilder.start_featurec                 C   s0   | j d k	std | _ d | _d | _d| _d | _d S r   )rZ   r   rU   rX   rS   rT   r   r2   r2   r3   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   )rW   r   rZ   rY   rX   rS   rT   r  r2   r2   r3   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 r   )rY   r   rX   rZ   rS   rT   r   r2   r2   r3   end_lookup_block)  s    
zBuilder.end_lookup_blockc                 C   s<   || j kst|d | _| j | }|d k	r8| || j d S r9   )rW   r   rX   r   rZ   )r|   lookup_namer   r2   r2   r3   add_lookup_call1  s
    
zBuilder.add_lookup_callc                 C   s
   || _ d S r9   )rk   )r|   r   revisionr2   r2   r3   set_font_revision8  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   rj  r   zPLanguage %s (script %s) has already specified feature %s as its required feature)r   r   rZ   r   rX   rR   r]   r   r   rU   r^   r}  )r|   r   r  include_defaultrequiredr   r   r2   r2   r3   set_language;  sB    





zBuilder.set_languagec                 C   s~   t |}| j|}|d k	r |S t| jd }|| j|< |D ]<}|| jkrj| j| \}}td||f |||f| j|< q<|S )Nr   z=Glyph %s already has been assigned a MarkAttachmentType at %s)r   rt   r   r   rs   r   )r|   r   r^  r_  r   rS  locr2   r2   r3   getMarkAttachClass_b  s"    

zBuilder.getMarkAttachClass_c                 C   s8   t |}| j|}|d k	r |S t| j}|| j|< |S r9   )r   ru   r   r   )r|   r   r^  r_  r2   r2   r3   getMarkFilterSet_t  s    

zBuilder.getMarkFilterSet_c                 C   sT   |d@ }|r$|  ||}||d> B }|rD| ||}|dB }|| _nd | _|| _d S )N   r   r!  )r  r  rT   rS   )r|   r   r  Z
markAttachZ
markFilterZmarkAttachClassr   r2   r2   r3   set_lookup_flag}  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 )	Nr  z5Script statements are not allowed within "feature %s"zAScript statements are not allowed within standalone lookup blocksrj  r   TF)r  r  )rZ   r   rU   rX   rR   rS   rT   r  )r|   r   r   r2   r2   r3   
set_script  s&    

zBuilder.set_scriptc                    s>   g }|D ]0}|dk	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   )rW   r   r5   rh  r   r2   r3   rI     s     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 r9   )ro   r   rP   r  )r|   r   r^  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")rZ   r   r`   r   )r|   r   ZfeatureNamer2   r2   r3   add_feature_reference  s    
 zBuilder.add_feature_referencec                 C   s   | j | d S r9   )rc   r~  r|   r<   r2   r2   r3   add_featureName  s    zBuilder.add_featureNamec                 C   s   | j | d S r9   )re   r~  r  r2   r2   r3   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)rg   r  r2   r2   r3   add_to_cv_num_named_params  s    
z"Builder.add_to_cv_num_named_paramsc                 C   s   | j | | d S r9   )ri   r   )r|   	characterr<   r2   r2   r3   add_cv_character  s    zBuilder.add_cv_characterc                 C   s   |r||f| _ n
||f| _d S r9   )rn   rm   )r|   rD  rE  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")rZ   r   rj   rU   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|g }||kr|| qd S |sL|sL|r`| |||| d S | |t}	| D ]T\}}||	jkr||	j| krt	
d||| ntd||	j| f |||	j|< qtd S )Nr   zDRemoving duplicate single substitution from glyph "%s" to "%s" at %sz5Already defined rule for replacing glyph "%s" by "%s")rZ   r   rb   r   r   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|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"   r  r  r   )
r|   r   r  r   r  replacementsr  chainsubr   r2   r2   r3   add_multiple_subst   s(    

 zBuilder.add_multiple_substc                    s   | j dkr4| j|g    fdd|D  d S |s<|rr| |t}| |t}|j	t
||hg||g n| |t}||jkrtd| |||j|< d S )Nr   c                 3   s   | ]}| kr|V  qd S r9   r2   r   r   r2   r3   r=     s      z.Builder.add_alternate_subst.<locals>.<genexpr>z)Already defined alternates for glyph "%s")rZ   rb   r   r   r   r   r   r   r  r   r"   r   r   )r|   r   r  r   r  replacementr  r   r2   r  r3   add_alternate_subst  s    

 zBuilder.add_alternate_substc           
      C   sz   |s|s|r>|  |t}| |t}|jt||||g n|  |t}t|s\td|t	j
| D ]}	||j|	< qfd S Nz!Empty glyph class in substitution)r   r   r   r   r  r   r"   allr   	itertoolsproduct	ligatures)
r|   r   r  r^  r  r  r  r  r   r   r2   r2   r3   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   r  r   r"   r  r|   r   r  r^  r  r   r   r2   r2   r3   add_chain_context_substC  s        zBuilder.add_chain_context_substc                 C   sz   |rt |rt |std|| |t}||}|d krH| |t}|j| |j	
t|t| g||g d S r  )r  r   r   r   Zfind_chainable_single_substr   r   r   r  r  r   r"   rh   keys)r|   r   r  r  r   r  r  r2   r2   r3   r  O  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_prefix
old_suffixr   r   r2   r2   r3   add_reverse_chain_single_subst`  s    
z&Builder.add_reverse_chain_single_substc                 C   s   |s|s|r|  |||| n| |t}|D ]x\}}|sDtd|| j||dd}	|D ]L}
z|||
|	 W qX tk
r } ztt||j|W 5 d }~X Y qXX qXq.d S )N%Empty glyph class in positioning ruleFpairPosContext)	add_single_pos_chained_r   r!   r   makeOpenTypeValueRecordadd_posr#   ra  r   )r|   r   r  r  posr  r   r^  r  ZotValueRecordr   re  r2   r2   r3   add_single_posi  s&       zBuilder.add_single_posc           	      C   sT   |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_pos}  s    
zBuilder.add_class_pair_posc           	      C   sT   |r|st d|| |t}| j||dd}| j||dd}|||||| d S r  )r   r   r    r  ZaddGlyphPair)	r|   r   Zglyph1r  Zglyph2r  r   r  r  r2   r2   r3   add_specific_pair_pos  s    
zBuilder.add_specific_pair_posc              	   C   s>   |st d|| |t}|||| ||| || d S Nr  )r   r   r   add_attachmentmakeOpenTypeAnchor)r|   r   Z
glyphclassZentryAnchorZ
exitAnchorr   r2   r2   r3   add_cursive_pos  s    


zBuilder.add_cursive_posc           	      C   sd   |  |t}| ||| |s(td||D ]2\}}| ||}|D ]}||j|i |j< qDq,d S r  )r   r   
add_marks_r   r  rD  r   r5   )	r|   r   rD  marksr   
baseAnchorrX  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|
< qhd S r  )r   r   r   r  r  r5   r   r  )r|   r   r  
componentsr   ZcomponentAnchorsr  ZanchorsZ	ligAnchorrX  r   r2   r2   r3   add_mark_lig_pos  s    
zBuilder.add_mark_lig_posc           	      C   sd   |  |t}| ||| |s(td||D ]2\}}| ||}|D ]}||j|i |j< qDq,d S r  )r   r   r  r   r  	baseMarksr   r5   )	r|   r   r  r  r   r  rX  r  ZbaseMarkr2   r2   r3   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 )N0Empty glyph class in contextual positioning rule)r  r   r   r   r  r   r"   r  r  r2   r2   r3   add_chain_context_pos  s        zBuilder.add_chain_context_posc                 C   s  |rt |rt |std|| |t}g }|jD ]\}}}}|| q4g }	|D ]z\}
}|d krp|	d  qT| j||dd}|||
|}|d kr| 	|t
}|| |
D ]}|||| q|	| qTt|t|	kst||	f|jt|dd |D ||	 d S )Nr  Fr  c                 S   s   g | ]\}}|qS r2   r2   )r;   r   rz  r2   r2   r3   rI     s     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  r  targetsrS  r   subsr^  r  ZotValuer  r   r2   r2   r3   r    s<     
  
zBuilder.add_single_pos_chained_c           
   	   C   s   |D ]\}}|j D ]r}|j D ]b}||jkrT| |t|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)
rT  r^  rU  r  r  copydeepcopyanchorr5   r   )
r|   r   ZlookupBuilderr  rS  rX  rY  markZotMarkAnchorZexistingMarkClassr2   r2   r3   r    s"    

 


zBuilder.add_marks_c                 C   s   | j | d S r9   )rX   add_subtable_break)r|   r   r2   r2   r3   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)rr   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 q4|D ]}|  ||d qLd S )Nr   r   r  r  )r  )r|   r   Z
baseGlyphsZligatureGlyphsZ
markGlyphsZcomponentGlyphsr   r2   r2   r3   add_glyphClassDef  s    zBuilder.add_glyphClassDefc                 C   s"   |D ]}|| j kr|| j |< qd S r9   )rq   r|   r   r^  Zcaretsr   r2   r2   r3   add_ligatureCaretByIndex_  s    
z!Builder.add_ligatureCaretByIndex_c                 C   s2   t |ts|S | ||\}}|d k	r.||fS |S r9   )rJ   r   makeVariablePos)r|   r   caretdefaultdevicer2   r2   r3   makeLigCaret  s    
zBuilder.makeLigCaretc                    s6    fdd|D }|D ]}|j kr|j |< qd S )Nc                    s   g | ]}  |qS r2   )r  )r;   r  r   r|   r2   r3   rI   %  s     z3Builder.add_ligatureCaretByPos_.<locals>.<listcomp>)rp   r  r2   r  r3   add_ligatureCaretByPos_$  s    
zBuilder.add_ligatureCaretByPos_c                 C   s   | j |||||g d S r9   )rl   r   )r|   r   r   r   r   r   r   r2   r2   r3   add_name_record*  s    zBuilder.add_name_recordc                 C   s   || j |< d S r9   )rv   r|   r   r  r2   r2   r3   add_os2_field-  s    zBuilder.add_os2_fieldc                 C   s   || j |< d S r9   )rw   r  r2   r2   r3   add_hhea_field0  s    zBuilder.add_hhea_fieldc                 C   s   || j |< d S r9   )rx   r  r2   r2   r3   add_vhea_field3  s    zBuilder.add_vhea_fieldc                    st   d| j krtd|dd | jD   fdd| D }d| j krf| j d jfdd| D }|| j|< d S )NrG   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minValuedefaultValueZmaxValue)r;   rC  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)axisMapr2   r3   r   C  s
   
avarc                    s*   i | ]"\ } t  fd d|D qS )c                 3   s(   | ] } krt |  n|V  qd S r9   )r(   )r;   rz  )rC  r   r2   r3   r=   Q  s   z6Builder.add_conditionset.<locals>.<dictcomp>.<genexpr>)rl  )r;   Zcondition_range)r   )rC  r3   r   P  s
    )r0   r   rO   r   segmentsrz   )r|   r   r   r  r2   )r  r   r3   add_conditionset6  s"    



zBuilder.add_conditionsetc                 C   sj   | j std|| j|_|js(|jd fS || j | j| jd\}}d }|d k	rb|dkrbt	|}||fS )Nz5Can't define a variable scalar in a non-variable fontr  l    )
rN   r   rO   Z	does_varyr  Zadd_to_variation_storer{   r0   r   r%   )r|   r   	varscalarr  rB  r  r2   r2   r3   r  Z  s"     
  
zBuilder.makeVariablePosc                 C   s   |dkrdS d}d\}}|j dk	r2tt|j }|jdk	rLtt|j}dD ]p}t||}t|tsjqPt||d dk	rtd|| 	||\}}	t
||| |	dk	rP|dkr|	}n|	}d}qPt|j|j|j||}
|rd	|
_|
S )
zast.Anchor --> otTables.AnchorNFr  )xyZDeviceTable4Can't define a device coordinate and variable scalarr  Tr  )ZxDeviceTabler  buildDevicedictZyDeviceTablerk  rJ   r   r   r  r   ZbuildAnchorr  r  Zcontourpointr   )r|   r   r  variableZdeviceXZdeviceYZdimr  r  r  Z	otlanchorr2   r2   r3   r  n  sD    



     zBuilder.makeOpenTypeAnchorc                 C   s<   i | ]4\}}}}| d s|d  |dd  ||fqS )ZReservedr   r   N)
startswithlower)r;   rS  r5   isDevicer2   r2   r3   r     s   

 zBuilder.<dictcomp>c                 C   s   |sdS i }| j  D ]\}\}}t||d}|s4q|rLtt|||< qt|tr|dd d }	|	d  |	dd  }
t||
rt	d|| 
||\||< }|dk	r|||	< q|||< q|r|s|jrddinddi}t|}|S )	z&ast.ValueRecord --> otBase.ValueRecordNr   r  ZDevicer   r  ZYAdvanceZXAdvance)_VALUEREC_ATTRSr   rk  r  r  r  rJ   r   r  r   r  r  Z
buildValue)r|   r   rz  r  ZvrZastNameZotNamer  valZotDeviceNameZfeaDeviceNamer  ZvalRecr2   r2   r3   r    s2    

 


zBuilder.makeOpenTypeValueRecord)NF)F)[__name__
__module____qualname__r   r   r}   r/   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r   r   rA  r   rI  rK  rM  r   rf  r   r   rm  rb  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  r  r  r  r  r  r  r   ZvalueRecordFormatr   r  r2   r2   r2   r3   r.   ]   s   J
>3+TU-$_	
'	 
		
$"r.   )NF)NNF)IZ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'   r(   collectionsr)   r  r  ior*   loggingr   r   	getLoggerr  r  r4   r8   objectr.   r2   r2   r2   r3   <module>   s<   D

     
