a
    w=icR                    @   s  d dl mZ d dlmZ d dlmZ d dlmZmZ d dl	m
Z
 d dlZdZg dZd	d
 Zeg dZdd ZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG d d! d!eZG d"d# d#eZG d$d% d%eZG d&d' d'eZG d(d) d)eZ G d*d+ d+eZ!G d,d- d-eZ"G d.d/ d/eZ#G d0d1 d1eZ$G d2d3 d3eZ%G d4d5 d5eZ&G d6d7 d7eZ'G d8d9 d9eZ(G d:d; d;eZ)G d<d= d=eZ*G d>d? d?eZ+G d@dA dAeZ,G dBdC dCeZ-G dDdE dEeZ.G dFdG dGeZ/G dHdI dIeZ0G dJdK dKeZ1G dLdM dMeZ2G dNdO dOeZ3G dPdQ dQeZ4G dRdS dSeZ5G dTdU dUeZ6G dVdW dWeZ7G dXdY dYeZ8G dZd[ d[eZ9G d\d] d]eZ:G d^d_ d_eZ;G d`da daeZ<G dbdc dceZ=G ddde deeZ>G dfdg dgeZ?G dhdi dieZ@G djdk dkeZAG dldm dmeZBG dndo doeZCG dpdq dqeZDG drds dseZEdtdu ZFG dvdw dweZGG dxdy dyeGZHG dzd{ d{eGZIG d|d} d}eZJG d~d deGZKG dd deZLG dd deZMG dd deZNG dd deZOG dd deZPG dd deZQG dd deZRG dd deZSG dd deZTG dd deZUG dd deZVG dd deZWdS )    )FeatureLibError)FeatureLibLocation)getEncoding)byteordtobytes)OrderedDictNz    )BElementFeatureFileComment	GlyphName
GlyphClassGlyphClassNameMarkClassNameAnonymousBlockBlockFeatureBlockNestedBlockLookupBlockGlyphClassDefinitionGlyphClassDefStatement	MarkClassMarkClassDefinitionAlternateSubstStatementAnchorAnchorDefinitionAttachStatementAxisValueLocationStatementBaseAxisCVParametersNameStatementChainContextPosStatementChainContextSubstStatementCharacterStatementConditionsetStatementCursivePosStatementElidedFallbackNameElidedFallbackNameID
ExpressionFeatureNameStatementFeatureReferenceStatementFontRevisionStatement	HheaFieldIgnorePosStatementIgnoreSubstStatementIncludeStatementLanguageStatementLanguageSystemStatementLigatureCaretByIndexStatementLigatureCaretByPosStatementLigatureSubstStatementLookupFlagStatementLookupReferenceStatementMarkBasePosStatementMarkLigPosStatementMarkMarkPosStatementMultipleSubstStatement
NameRecordOS2FieldPairPosStatement ReverseChainSingleSubstStatementScriptStatementSinglePosStatementSingleSubstStatementSizeParameters	StatementSTATAxisValueStatementSTATDesignAxisStatementSTATNameStatementSubtableStatement
TableBlockValueRecordValueRecordDefinition	VheaFieldc                 C   s(   | d u rdS dd dd | D  S d S )Nz<device NULL>z<device %s>, c                 s   s   | ]}d | V  qdS )z%d %dN ).0trK   rK   e/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/site-packages/fontTools/feaLib/ast.py	<genexpr>T       z!deviceToString.<locals>.<genexpr>)join)devicerK   rK   rN   deviceToStringP   s    rS   )4anchorZ	anchordefZanonZ	anonymousZbyZcontourZcursiverR   enum	enumerateZexcludedfltZexclude_dfltfeaturefromignoreZignorebaseglyphsZignoreligaturesZignoremarksincludeZincludedfltZinclude_dfltlanguageZlanguagesystemlookupZ
lookupflagmarkZmarkattachmenttypeZ	markclassZnameidnull
parameterspospositionrequiredZrighttoleftZ
reversesubZrsubscriptsub
substituteZsubtabletableZusemarkfilteringsetZuseextensionZvaluerecorddefbaseZgdefheadZhheanameZvheaZvmtxc                 C   s`   t | dr|  S t| trDt| dkrDt| d d t| d  S |  tv rXd|  S | S d S )NasFea   r   z -    \)hasattrrj   
isinstancetuplelenlowerfea_keywords)grK   rK   rN   rj      s    
rj   c                   @   s4   e Zd ZdZdddZdd Zddd	Zd
d ZdS )r   z8A base class representing "something" in a feature file.Nc                 C   s    |rt |tst| }|| _d S N)ro   r   locationselfrv   rK   rK   rN   __init__   s    zElement.__init__c                 C   s   d S ru   rK   rx   builderrK   rK   rN   build   s    zElement.build c                 C   s   t dS )zReturns this element as a string of feature code. For block-type
        elements (such as :class:`FeatureBlock`), the `indent` string is
        added to the start of each line in the output.N)NotImplementedErrorrx   indentrK   rK   rN   rj      s    zElement.asFeac                 C   s   |   S ru   rj   rx   rK   rK   rN   __str__   s    zElement.__str__)N)r}   )__name__
__module____qualname____doc__ry   r|   rj   r   rK   rK   rK   rN   r      s
   

r   c                   @   s   e Zd ZdS )rA   Nr   r   r   rK   rK   rK   rN   rA      s   rA   c                   @   s   e Zd ZdS )r&   Nr   rK   rK   rK   rN   r&      s   r&   c                       s,   e Zd ZdZd fdd	Zd	ddZ  ZS )
r
   zA comment in a feature file.Nc                    s   t t| | || _d S ru   )superr
   ry   text)rx   r   rv   	__class__rK   rN   ry      s    zComment.__init__r}   c                 C   s   | j S ru   )r   r   rK   rK   rN   rj      s    zComment.asFea)N)r}   r   r   r   r   ry   rj   __classcell__rK   rK   r   rN   r
      s   r
   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )	NullGlyphz5The NULL glyph, used in glyph deletion substitutions.Nc                 C   s   t | | d S ru   )r&   ry   rw   rK   rK   rN   ry      s    zNullGlyph.__init__c                 C   s   dS )BThe glyphs in this class as a tuple of :class:`GlyphName` objects.rK   rK   r   rK   rK   rN   glyphSet   s    zNullGlyph.glyphSetr}   c                 C   s   dS )NNULLrK   r   rK   rK   rN   rj      s    zNullGlyph.asFea)N)r}   r   r   r   r   ry   r   rj   rK   rK   rK   rN   r      s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   z)A single glyph name, such as ``cedilla``.Nc                 C   s   t | | || _d S ru   )r&   ry   glyph)rx   r   rv   rK   rK   rN   ry      s    zGlyphName.__init__c                 C   s   | j fS r   )r   r   rK   rK   rN   r      s    zGlyphName.glyphSetr}   c                 C   s
   t | jS ru   )rj   r   r   rK   rK   rN   rj      s    zGlyphName.asFea)N)r}   r   rK   rK   rK   rN   r      s   
r   c                   @   sT   e Zd ZdZdddZdd Zddd	Zd
d Zdd Zdd Z	dd Z
dd ZdS )r   z1A glyph class, such as ``[acute cedilla grave]``.Nc                 C   s.   t | | |d ur|ng | _g | _d| _d S )Nr   )r&   ry   glyphsoriginalcurr)rx   r   rv   rK   rK   rN   ry      s    zGlyphClass.__init__c                 C   s
   t | jS r   )rp   r   r   rK   rK   rN   r      s    zGlyphClass.glyphSetr}   c                 C   sv   t | jrX| jt | jk r>| j| j| jd   t | j| _ddtt| j d S ddtt| j d S d S )N[ ])rq   r   r   r   extendrQ   maprj   r   rK   rK   rN   rj      s    
zGlyphClass.asFeac                 C   s   | j | dS )z6Add a list of :class:`GlyphName` objects to the class.N)r   r   )rx   r   rK   rK   rN   r      s    zGlyphClass.extendc                 C   s   | j | dS )z4Add a single :class:`GlyphName` object to the class.N)r   append)rx   r   rK   rK   rN   r      s    zGlyphClass.appendc                 C   sT   | j t| jk r(| j| j| j d  | j||f | j| t| j| _ dS )a  Add a range (e.g. ``A-Z``) to the class. ``start`` and ``end``
        are either :class:`GlyphName` objects or strings representing the
        start and end glyphs in the class, and ``glyphs`` is the full list of
        :class:`GlyphName` objects in the range.N)r   rq   r   r   r   r   rx   startendr   rK   rK   rN   	add_range  s
    zGlyphClass.add_rangec                 C   s`   | j t| jk r(| j| j| j d  | jd|d|f | j| t| j| _ dS )zAdd a range to the class by glyph ID. ``start`` and ``end`` are the
        initial and final IDs, and ``glyphs`` is the full list of
        :class:`GlyphName` objects in the range.Nz\{})r   rq   r   r   r   r   formatr   rK   rK   rN   add_cid_range  s
    zGlyphClass.add_cid_rangec                 C   sT   | j t| jk r(| j| j| j d  | j| | j|  t| j| _ dS )zNAdd glyphs from the given :class:`GlyphClassName` object to the
        class.N)r   rq   r   r   r   r   r   )rx   gcrK   rK   rN   	add_class  s
    zGlyphClass.add_class)NN)r}   )r   r   r   r   ry   r   rj   r   r   r   r   r   rK   rK   rK   rN   r      s   

	
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zyA glyph class name, such as ``@FRENCH_MARKS``. This must be instantiated
    with a :class:`GlyphClassDefinition` object.Nc                 C   s$   t | | t|tsJ || _d S ru   )r&   ry   ro   r   
glyphclass)rx   r   rv   rK   rK   rN   ry   '  s    zGlyphClassName.__init__c                 C   s   t | j S r   )rp   r   r   r   rK   rK   rN   r   ,  s    zGlyphClassName.glyphSetr}   c                 C   s   d| j j S N@)r   ri   r   rK   rK   rN   rj   0  s    zGlyphClassName.asFea)N)r}   r   rK   rK   rK   rN   r   #  s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zA mark class name, such as ``@FRENCH_MARKS`` defined with ``markClass``.
    This must be instantiated with a :class:`MarkClass` object.Nc                 C   s$   t | | t|tsJ || _d S ru   )r&   ry   ro   r   	markClass)rx   r   rv   rK   rK   rN   ry   8  s    zMarkClassName.__init__c                 C   s
   | j  S r   )r   r   r   rK   rK   rN   r   =  s    zMarkClassName.glyphSetr}   c                 C   s   d| j j S r   )r   ri   r   rK   rK   rN   rj   A  s    zMarkClassName.asFea)N)r}   r   rK   rK   rK   rN   r   4  s   
r   c                   @   s$   e Zd ZdZdddZd	ddZdS )
r   zAn anonymous data block.Nc                 C   s   t | | || _|| _d S ru   )rA   ry   tagcontent)rx   r   r   rv   rK   rK   rN   ry   H  s    zAnonymousBlock.__init__r}   c                 C   s*   d | j}|| j7 }|d | j7 }|S )Nzanon {} {{
z}} {};

)r   r   r   rx   r   resrK   rK   rN   rj   M  s    
zAnonymousBlock.asFea)N)r}   r   r   r   r   ry   rj   rK   rK   rK   rN   r   E  s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   z,A block of statements: feature, lookup, etc.Nc                 C   s   t | | g | _d S ru   )rA   ry   
statementsrw   rK   rK   rN   ry   W  s    zBlock.__init__c                 C   s   | j D ]}|| qdS )zWhen handed a 'builder' object of comparable interface to
        :class:`fontTools.feaLib.builder`, walks the statements in this
        block, calling the builder callbacks.N)r   r|   )rx   r{   srK   rK   rN   r|   [  s    
zBlock.buildr}   c                    s.    t 7   d   fdd| jD  d S )N
c                    s   g | ]}|j  d qS r   r   rL   r   r   rK   rN   
<listcomp>f  rP   zBlock.asFea.<locals>.<listcomp>)SHIFTrQ   r   r   rK   r   rN   rj   b  s    zBlock.asFea)N)r}   r   r   r   r   ry   r|   rj   rK   rK   rK   rN   r   T  s   
r   c                   @   s"   e Zd ZdZdd ZdddZdS )	r	   zpThe top-level element of the syntax tree, containing the whole feature
    file in its ``statements`` attribute.c                 C   s   t j| d d i | _d S N)rv   )r   ry   ZmarkClassesr   rK   rK   rN   ry   o  s    zFeatureFile.__init__r}   c                    s   d  fdd| jD S )Nr   c                 3   s   | ]}|j  d V  qdS )r   Nr   r   r   rK   rN   rO   t  rP   z$FeatureFile.asFea.<locals>.<genexpr>)rQ   r   r   rK   r   rN   rj   s  s    zFeatureFile.asFeaN)r}   r   rK   rK   rK   rN   r	   k  s   r	   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )r   zA named feature block.FNc                 C   s   t | | || | _| _d S ru   r   ry   ri   use_extensionrx   ri   r   rv   rK   rK   rN   ry   z  s    zFeatureBlock.__init__c                 C   s`   | | j| j |j}i |_t| | |j D ]\}}||g | q2||_|	  dS )Call the ``start_feature`` callback on the builder object, visit
        all the statements in this feature, and then call ``end_feature``.N)
start_featurerv   ri   	features_r   r|   items
setdefaultr   end_feature)rx   r{   featureskeyvaluerK   rK   rN   r|   ~  s    zFeatureBlock.buildr}   c                 C   sT   |d| j    }| jr |d7 }|d7 }|tj| |d7 }||d| j    7 }|S )Nzfeature %s useExtension {
r   } %s;
)ri   stripr   r   rj   r   rK   rK   rN   rj     s    zFeatureBlock.asFea)FN)r}   r   rK   rK   rK   rN   r   w  s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zYA block inside another block, for example when found inside a
    ``cvParameters`` block.Nc                 C   s   t | | || _|| _d S ru   )r   ry   r   
block_name)rx   r   r   rv   rK   rK   rN   ry     s    zNestedBlock.__init__c                 C   s&   t | | | jdkr"|| j d S )NParamUILabelNameID)r   r|   r   Zadd_to_cv_num_named_paramsr   rz   rK   rK   rN   r|     s    
zNestedBlock.buildr}   c                 C   s2   d || j}|tj| |d7 }|d |7 }|S )Nz{}{} {{
r   z{}}};
)r   r   r   rj   r   rK   rK   rN   rj     s    zNestedBlock.asFea)N)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )r   z*A named lookup, containing ``statements``.FNc                 C   s   t | | || | _| _d S ru   r   r   rK   rK   rN   ry     s    zLookupBlock.__init__c                 C   s(   | | j| j t| | |  d S ru   )Zstart_lookup_blockrv   ri   r   r|   Zend_lookup_blockrz   rK   rK   rN   r|     s    zLookupBlock.buildr}   c                 C   sJ   d | j}| jr|d7 }|d7 }|tj| |d7 }|d || j7 }|S )Nz
lookup {} r   r   r   z	{}}} {};
)r   ri   r   r   rj   r   rK   rK   rN   rj     s    zLookupBlock.asFea)FN)r}   r   rK   rK   rK   rN   r     s   
r   c                       s,   e Zd ZdZdddZd	 fdd	Z  ZS )
rF   zA ``table ... { }`` block.Nc                 C   s   t | | || _d S ru   )r   ry   ri   )rx   ri   rv   rK   rK   rN   ry     s    zTableBlock.__init__r}   c                    s>   d | j }|tt| j|d7 }|d | j 7 }|S )Nztable {} {{
r   z}} {};
)r   ri   r   r   rF   rj   r   r   rK   rN   rj     s    zTableBlock.asFea)N)r}   r   rK   rK   r   rN   rF     s   
rF   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   z!Example: ``@UPPERCASE = [A-Z];``.Nc                 C   s   t | | || _|| _d S ru   )rA   ry   ri   r   )rx   ri   r   rv   rK   rK   rN   ry     s    zGlyphClassDefinition.__init__c                 C   s   t | j S r   )rp   r   r   r   rK   rK   rN   r     s    zGlyphClassDefinition.glyphSetr}   c                 C   s   d| j  d | j  d S )Nr   z = ;)ri   r   rj   r   rK   rK   rN   rj     s    zGlyphClassDefinition.asFea)N)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zExample: ``GlyphClassDef @UPPERCASE, [B], [C], [D];``. The parameters
    must be either :class:`GlyphClass` or :class:`GlyphClassName` objects, or
    ``None``.Nc                 C   s*   t | | || | _| _|| _|| _d S ru   )rA   ry   
baseGlyphs
markGlyphsligatureGlyphscomponentGlyphs)rx   r   r   r   r   rv   rK   rK   rN   ry     s    zGlyphClassDefStatement.__init__c                 C   sp   | j r| j  nt }| jr&| j nt }| jr<| j nt }| jrR| j nt }|| j|||| dS )z3Calls the builder's ``add_glyphClassDef`` callback.N)r   r   rp   r   r   r   Zadd_glyphClassDefrv   )rx   r{   rg   Zligar]   comprK   rK   rN   r|     s
    zGlyphClassDefStatement.buildr}   c                 C   sP   d | jr| j nd| jr&| j nd| jr8| j nd| jrJ| j ndS )NzGlyphClassDef {}, {}, {}, {};r}   )r   r   rj   r   r   r   r   rK   rK   rN   rj     s    zGlyphClassDefStatement.asFea)N)r}   r   rK   rK   rK   rN   r     s
    
r   c                   @   s2   e Zd ZdZdd Zdd Zdd Zdd	d
ZdS )r   aB  One `or more` ``markClass`` statements for the same mark class.

    While glyph classes can be defined only once, the feature file format
    allows expanding mark classes with multiple definitions, each using
    different glyphs and anchors. The following are two ``MarkClassDefinitions``
    for the same ``MarkClass``::

        markClass [acute grave] <anchor 350 800> @FRENCH_ACCENTS;
        markClass [cedilla] <anchor 350 -200> @FRENCH_ACCENTS;

    The ``MarkClass`` object is therefore just a container for a list of
    :class:`MarkClassDefinition` statements.
    c                 C   s   || _ g | _t | _d S ru   )ri   definitionsr   r   )rx   ri   rK   rK   rN   ry     s    zMarkClass.__init__c                 C   sx   t |tsJ | j| | D ]P}|| jv rh| j| j}|du rJd}n
d| }td||f |j|| j|< q"dS )z@Add a :class:`MarkClassDefinition` statement to this mark class.Nr}   z at zGlyph %s already defined%s)ro   r   r   r   r   r   rv   r   )rx   
definitionr   ZotherLocr   rK   rK   rN   addDefinition  s    

zMarkClass.addDefinitionc                 C   s   t | j S r   )rp   r   keysr   rK   rK   rN   r   #  s    zMarkClass.glyphSetr}   c                 C   s   d dd | jD }|S )Nr   c                 s   s   | ]}|  V  qd S ru   r   )rL   drK   rK   rN   rO   (  rP   z"MarkClass.asFea.<locals>.<genexpr>)rQ   r   r   rK   rK   rN   rj   '  s    zMarkClass.asFeaN)r}   )r   r   r   r   ry   r   r   rj   rK   rK   rK   rN   r     s
   r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   a   A single ``markClass`` statement. The ``markClass`` should be a
    :class:`MarkClass` object, the ``anchor`` an :class:`Anchor` object,
    and the ``glyphs`` parameter should be a `glyph-containing object`_ .

    Example:

        .. code:: python

            mc = MarkClass("FRENCH_ACCENTS")
            mc.addDefinition( MarkClassDefinition(mc, Anchor(350, 800),
                GlyphClass([ GlyphName("acute"), GlyphName("grave") ])
            ) )
            mc.addDefinition( MarkClassDefinition(mc, Anchor(350, -200),
                GlyphClass([ GlyphName("cedilla") ])
            ) )

            mc.asFea()
            # markClass [acute grave] <anchor 350 800> @FRENCH_ACCENTS;
            # markClass [cedilla] <anchor 350 -200> @FRENCH_ACCENTS;

    Nc                 C   sL   t | | t|tsJ t|tr.t|ts2J |||  | _| _| _d S ru   )	rA   ry   ro   r   r   r&   r   rT   r   )rx   r   rT   r   rv   rK   rK   rN   ry   C  s    zMarkClassDefinition.__init__c                 C   s
   | j  S r   )r   r   r   rK   rK   rN   r   I  s    zMarkClassDefinition.glyphSetr}   c                 C   s   d | j | j | jjS )NzmarkClass {} {} @{};)r   r   rj   rT   r   ri   r   rK   rK   rN   rj   M  s    zMarkClassDefinition.asFea)N)r}   r   rK   rK   rK   rN   r   ,  s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zA ``sub ... from ...`` statement.

    ``prefix``, ``glyph``, ``suffix`` and ``replacement`` should be lists of
    `glyph-containing objects`_. ``glyph`` should be a `one element list`.Nc                 C   s,   t | | |||  | _| _| _|| _d S ru   )rA   ry   prefixr   suffixreplacement)rx   r   r   r   r   rv   rK   rK   rN   ry   Y  s    z AlternateSubstStatement.__init__c                 C   sl   | j  }t|dksJ |t|d }dd | jD }dd | jD }| j }|| j|||| dS )z5Calls the builder's ``add_alternate_subst`` callback.rl   r   c                 S   s   g | ]}|  qS rK   r   rL   prK   rK   rN   r   c  rP   z1AlternateSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   d  rP   N)	r   r   rq   listr   r   r   Zadd_alternate_substrv   )rx   r{   r   r   r   r   rK   rK   rN   r|   ^  s    

zAlternateSubstStatement.buildr}   c                 C   s   d}t | jst | jrtt | jr<|dtt| jd 7 }|t| jd 7 }t | jr|ddtt| j 7 }n|t| j7 }|d7 }|t| j7 }|d7 }|S )Nsub r   'z from r   )rq   r   r   rQ   r   rj   r   r   r   rK   rK   rN   rj   h  s    

zAlternateSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r   S  s   

r   c                   @   s$   e Zd ZdZdddZd	ddZdS )
r   zAn ``Anchor`` element, used inside a ``pos`` rule.

    If a ``name`` is given, this will be used in preference to the coordinates.
    Other values should be integer.
    Nc                 C   s:   t | | || _|||  | _| _| _|| | _| _d S ru   )r&   ry   ri   xycontourpointxDeviceTableyDeviceTable)rx   r   r   ri   r   r   r   rv   rK   rK   rN   ry     s    
zAnchor.__init__r}   c                 C   s   | j d urd| j S d| j| j}| jr<|d| j7 }| jsH| jrt|d7 }|t| j7 }|d7 }|t| j7 }|d7 }|S )Nz<anchor {}>z<anchor {} {} contourpoint {}r   >)ri   r   r   r   r   r   r   rS   r   rK   rK   rN   rj     s    
zAnchor.asFea)NNNNN)r}   r   rK   rK   rK   rN   r   x  s   
     
r   c                   @   s$   e Zd ZdZdddZd	ddZdS )
r   zCA named anchor definition. (2.e.viii). ``name`` should be a string.Nc                 C   s,   t | | ||||f\| _| _| _| _d S ru   )rA   ry   ri   r   r   r   )rx   ri   r   r   r   rv   rK   rK   rN   ry     s    zAnchorDefinition.__init__r}   c                 C   s:   d | j| j}| jr&|d | j7 }|d | j7 }|S )NzanchorDef {} {}r   z {};)r   r   r   r   ri   r   rK   rK   rN   rj     s
    zAnchorDefinition.asFea)NN)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   z&A ``GDEF`` table ``Attach`` statement.Nc                 C   s   t | | || _|| _d S ru   )rA   ry   r   contourPoints)rx   r   r   rv   rK   rK   rN   ry     s    zAttachStatement.__init__c                 C   s    | j  }|| j|| j dS )z3Calls the builder's ``add_attach_points`` callback.N)r   r   Zadd_attach_pointsrv   r   rx   r{   r   rK   rK   rN   r|     s    
zAttachStatement.buildr}   c                 C   s$   d | j ddd | jD S )NzAttach {} {};r   c                 s   s   | ]}t |V  qd S ru   str)rL   crK   rK   rN   rO     rP   z(AttachStatement.asFea.<locals>.<genexpr>)r   r   rj   rQ   r   r   rK   rK   rN   rj     s    zAttachStatement.asFea)N)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   a@  A chained contextual positioning statement.

    ``prefix``, ``glyphs``, and ``suffix`` should be lists of
    `glyph-containing objects`_ .

    ``lookups`` should be a list of elements representing what lookups
    to apply at each glyph position. Each element should be a
    :class:`LookupBlock` to apply a single chaining lookup at the given
    position, a list of :class:`LookupBlock`\ s to apply multiple
    lookups, or ``None`` to apply no lookup. The length of the outer
    list should equal the length of ``glyphs``; the inner lists can be
    of variable length.Nc              	   C   sx   t | | |||  | _| _| _t|| _t|D ]>\}}|r4zdd |D  W q4 typ   |g| j|< Y q40 q4d S )Nc                 s   s   | ]
}|V  qd S ru   rK   rL   _rK   rK   rN   rO     rP   z4ChainContextPosStatement.__init__.<locals>.<genexpr>	rA   ry   r   r   r   r   lookupsrV   	TypeErrorrx   r   r   r   r   rv   ir\   rK   rK   rN   ry     s    
z!ChainContextPosStatement.__init__c                 C   sJ   dd | j D }dd | jD }dd | jD }|| j|||| j dS )z7Calls the builder's ``add_chain_context_pos`` callback.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z2ChainContextPosStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   rL   rt   rK   rK   rN   r     rP   c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   N)r   r   r   add_chain_context_posrv   r   rx   r{   r   r   r   rK   rK   rN   r|     s    zChainContextPosStatement.buildr}   c                 C   s  d}t | js,t | js,tdd | jD rt | jrT|ddd | jD d 7 }t| jD ]Z\}}|| d 7 }| j| r| j| D ]}|d|j	 7 }q|t | jd	 k r^|d7 }q^t | jr|ddt
t| j 7 }n|dt
t| j7 }|d
7 }|S )Npos c                 S   s   g | ]}|d uqS ru   rK   rL   r   rK   rK   rN   r     rP   z2ChainContextPosStatement.asFea.<locals>.<listcomp>r   c                 s   s   | ]}|  V  qd S ru   r   r   rK   rK   rN   rO     rP   z1ChainContextPosStatement.asFea.<locals>.<genexpr>r    lookup rl   r   rq   r   r   anyr   rQ   rV   r   rj   ri   r   r   rx   r   r   r   rt   ZlurK   rK   rN   rj     s*    



zChainContextPosStatement.asFea)N)r}   r   rK   rK   rK   rN   r     s   
	r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r    aA  A chained contextual substitution statement.

    ``prefix``, ``glyphs``, and ``suffix`` should be lists of
    `glyph-containing objects`_ .

    ``lookups`` should be a list of elements representing what lookups
    to apply at each glyph position. Each element should be a
    :class:`LookupBlock` to apply a single chaining lookup at the given
    position, a list of :class:`LookupBlock`\ s to apply multiple
    lookups, or ``None`` to apply no lookup. The length of the outer
    list should equal the length of ``glyphs``; the inner lists can be
    of variable length.Nc              	   C   sx   t | | |||  | _| _| _t|| _t|D ]>\}}|r4zdd |D  W q4 typ   |g| j|< Y q40 q4d S )Nc                 s   s   | ]
}|V  qd S ru   rK   r   rK   rK   rN   rO     rP   z6ChainContextSubstStatement.__init__.<locals>.<genexpr>r   r   rK   rK   rN   ry     s    
z#ChainContextSubstStatement.__init__c                 C   sJ   dd | j D }dd | jD }dd | jD }|| j|||| j dS )z9Calls the builder's ``add_chain_context_subst`` callback.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z4ChainContextSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   N)r   r   r   add_chain_context_substrv   r   r   rK   rK   rN   r|     s    z ChainContextSubstStatement.buildr}   c                 C   s  d}t | js,t | js,tdd | jD rt | jrT|ddd | jD d 7 }t| jD ]Z\}}|| d 7 }| j| r| j| D ]}|d|j	 7 }q|t | jd	 k r^|d7 }q^t | jr|ddt
t| j 7 }n|dt
t| j7 }|d
7 }|S )Nr   c                 S   s   g | ]}|d uqS ru   rK   r   rK   rK   rN   r      rP   z4ChainContextSubstStatement.asFea.<locals>.<listcomp>r   c                 s   s   | ]}|  V  qd S ru   r   r   rK   rK   rN   rO   #  rP   z3ChainContextSubstStatement.asFea.<locals>.<genexpr>r   r   rl   r   r   r   rK   rK   rN   rj     s*    



z ChainContextSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r      s   
	r    c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r#   znA cursive positioning statement. Entry and exit anchors can either
    be :class:`Anchor` objects or ``None``.Nc                 C   s$   t | | || _|| | _| _d S ru   )rA   ry   r   entryAnchor
exitAnchor)rx   r   r   r   rv   rK   rK   rN   ry   7  s    zCursivePosStatement.__init__c                 C   s    | | j| j | j| j dS )z8Calls the builder object's ``add_cursive_pos`` callback.N)Zadd_cursive_posrv   r   r   r   r   rz   rK   rK   rN   r|   <  s    zCursivePosStatement.buildr}   c                 C   s<   | j r| j  nd}| jr$| j nd}d| j ||S )N<anchor NULL>zpos cursive {} {} {};)r   rj   r   r   r   )rx   r   entryexitrK   rK   rN   rj   B  s    zCursivePosStatement.asFea)N)r}   r   rK   rK   rK   rN   r#   3  s   
r#   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r(   zExample: ``feature salt;``Nc                 C   s   t | | || | _| _d S ru   )rA   ry   rv   featureName)rx   r  rv   rK   rK   rN   ry   K  s    z"FeatureReferenceStatement.__init__c                 C   s   | | j| j dS )z>Calls the builder object's ``add_feature_reference`` callback.N)Zadd_feature_referencerv   r  rz   rK   rK   rN   r|   O  s    zFeatureReferenceStatement.buildr}   c                 C   s   d | jS )Nzfeature {};)r   r  r   rK   rK   rN   rj   S  s    zFeatureReferenceStatement.asFea)N)r}   r   rK   rK   rK   rN   r(   H  s   
r(   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r+   zAn ``ignore pos`` statement, containing `one or more` contexts to ignore.

    ``chainContexts`` should be a list of ``(prefix, glyphs, suffix)`` tuples,
    with each of ``prefix``, ``glyphs`` and ``suffix`` being
    `glyph-containing objects`_ .Nc                 C   s   t | | || _d S ru   rA   ry   chainContextsrx   r  rv   rK   rK   rN   ry   ^  s    zIgnorePosStatement.__init__c                 C   sT   | j D ]H\}}}dd |D }dd |D }dd |D }|| j|||g  qdS )z[Calls the builder object's ``add_chain_context_pos`` callback on each
        rule context.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   f  rP   z,IgnorePosStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   g  rP   c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   h  rP   N)r  r   rv   r   rK   rK   rN   r|   b  s
    zIgnorePosStatement.buildr}   c                 C   s   g }| j D ]\}}}d}t|s(t|rt|rH|dtt|d 7 }|ddd |D 7 }t|r|ddtt| 7 }n|dtt|7 }|| q
dd| d S )Nr}   r   c                 s   s   | ]}|  d  V  qdS r   Nr   r   rK   rK   rN   rO   r  rP   z+IgnorePosStatement.asFea.<locals>.<genexpr>zignore pos rJ   r   r  rq   rQ   r   rj   r   rx   r   contextsr   r   r   r   rK   rK   rN   rj   k  s    zIgnorePosStatement.asFea)N)r}   r   rK   rK   rK   rN   r+   W  s   
	r+   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r,   zAn ``ignore sub`` statement, containing `one or more` contexts to ignore.

    ``chainContexts`` should be a list of ``(prefix, glyphs, suffix)`` tuples,
    with each of ``prefix``, ``glyphs`` and ``suffix`` being
    `glyph-containing objects`_ .Nc                 C   s   t | | || _d S ru   r  r  rK   rK   rN   ry     s    zIgnoreSubstStatement.__init__c                 C   sT   | j D ]H\}}}dd |D }dd |D }dd |D }|| j|||g  qdS )z]Calls the builder object's ``add_chain_context_subst`` callback on
        each rule context.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z.IgnoreSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   N)r  r   rv   r   rK   rK   rN   r|     s
    zIgnoreSubstStatement.buildr}   c                 C   s   g }| j D ]\}}}d}t|s(t|rt|rH|dtt|d 7 }|ddd |D 7 }t|r|ddtt| 7 }n|dtt|7 }|| q
dd| d S )Nr}   r   c                 s   s   | ]}|  d  V  qdS r  r   r   rK   rK   rN   rO     rP   z-IgnoreSubstStatement.asFea.<locals>.<genexpr>zignore sub rJ   r   r  r  rK   rK   rN   rj     s    zIgnoreSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r,   {  s   
	r,   c                       s4   e Zd ZdZd
 fdd	Zdd Zddd	Z  ZS )r-   zAn ``include()`` statement.Nc                    s   t t| | || _d S ru   )r   r-   ry   filename)rx   r
  rv   r   rK   rN   ry     s    zIncludeStatement.__init__c                 C   s   t d| jd S )NzqBuilding an include statement is not implemented yet. Instead, use Parser(..., followIncludes=True) for building.)r   rv   r   rK   rK   rN   r|     s    zIncludeStatement.buildr}   c                 C   s   |d| j   S )Nzinclude(%s);)r
  r   rK   rK   rN   rj     s    zIncludeStatement.asFea)N)r}   )r   r   r   r   ry   r|   rj   r   rK   rK   r   rN   r-     s   r-   c                   @   s,   e Zd ZdZdddZdd Zdd
dZdS )r.   z*A ``language`` statement within a feature.TFNc                 C   s2   t | | t|dksJ || _|| _|| _d S )N   )rA   ry   rq   r[   include_defaultrb   )rx   r[   r  rb   rv   rK   rK   rN   ry     s
    zLanguageStatement.__init__c                 C   s   |j | j| j| j| jd dS )z4Call the builder object's ``set_language`` callback.)rv   r[   r  rb   N)Zset_languagerv   r[   r  rb   rz   rK   rK   rN   r|     s    zLanguageStatement.buildr}   c                 C   s8   d | j }| js|d7 }| jr,|d7 }|d7 }|S )Nzlanguage {}z exclude_dfltz	 requiredr   )r   r[   r   r  rb   r   rK   rK   rN   rj     s    zLanguageStatement.asFea)TFN)r}   r   rK   rK   rK   rN   r.     s   
	r.   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r/   z)A top-level ``languagesystem`` statement.Nc                 C   s   t | | || | _| _d S ru   )rA   ry   rc   r[   )rx   rc   r[   rv   rK   rK   rN   ry     s    z LanguageSystemStatement.__init__c                 C   s   | | j| j| j dS )z<Calls the builder object's ``add_language_system`` callback.N)Zadd_language_systemrv   rc   r[   rz   rK   rK   rN   r|     s    zLanguageSystemStatement.buildr}   c                 C   s   d | j| j S )Nzlanguagesystem {} {};)r   rc   r[   r   r   rK   rK   rN   rj     s    zLanguageSystemStatement.asFea)N)r}   r   rK   rK   rK   rN   r/     s   
r/   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r)   zA ``head`` table ``FontRevision`` statement. ``revision`` should be a
    number, and will be formatted to three significant decimal places.Nc                 C   s   t | | || _d S ru   )rA   ry   revision)rx   r  rv   rK   rK   rN   ry     s    zFontRevisionStatement.__init__c                 C   s   | | j| j d S ru   )Zset_font_revisionrv   r  rz   rK   rK   rN   r|     s    zFontRevisionStatement.buildr}   c                 C   s   d | jS )NzFontRevision {:.3f};)r   r  r   rK   rK   rN   rj     s    zFontRevisionStatement.asFea)N)r}   r   rK   rK   rK   rN   r)     s   
r)   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r0   zA ``GDEF`` table ``LigatureCaretByIndex`` statement. ``glyphs`` should be
    a `glyph-containing object`_, and ``carets`` should be a list of integers.Nc                 C   s   t | | || | _| _d S ru   rA   ry   r   caretsrx   r   r  rv   rK   rK   rN   ry     s    z&LigatureCaretByIndexStatement.__init__c                 C   s$   | j  }|| j|t| j dS )zBCalls the builder object's ``add_ligatureCaretByIndex_`` callback.N)r   r   Zadd_ligatureCaretByIndex_rv   setr  r   rK   rK   rN   r|     s    
z#LigatureCaretByIndexStatement.buildr}   c                 C   s$   d | j ddd | jD S )NzLigatureCaretByIndex {} {};r   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   z6LigatureCaretByIndexStatement.asFea.<locals>.<genexpr>r   r   rj   rQ   r  r   rK   rK   rN   rj     s    z#LigatureCaretByIndexStatement.asFea)N)r}   r   rK   rK   rK   rN   r0     s   
r0   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r1   zA ``GDEF`` table ``LigatureCaretByPos`` statement. ``glyphs`` should be
    a `glyph-containing object`_, and ``carets`` should be a list of integers.Nc                 C   s   t | | || | _| _d S ru   r  r  rK   rK   rN   ry     s    z$LigatureCaretByPosStatement.__init__c                 C   s$   | j  }|| j|t| j dS )z@Calls the builder object's ``add_ligatureCaretByPos_`` callback.N)r   r   Zadd_ligatureCaretByPos_rv   r  r  r   rK   rK   rN   r|     s    
z!LigatureCaretByPosStatement.buildr}   c                 C   s$   d | j ddd | jD S )NzLigatureCaretByPos {} {};r   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   z4LigatureCaretByPosStatement.asFea.<locals>.<genexpr>r  r   rK   rK   rN   rj     s    z!LigatureCaretByPosStatement.asFea)N)r}   r   rK   rK   rK   rN   r1      s   
r1   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r2   aS  A chained contextual substitution statement.

    ``prefix``, ``glyphs``, and ``suffix`` should be lists of
    `glyph-containing objects`_; ``replacement`` should be a single
    `glyph-containing object`_.

    If ``forceChain`` is True, this is expressed as a chaining rule
    (e.g. ``sub f' i' by f_i``) even when no context is given.Nc                 C   s4   t | | |||  | _| _| _|| | _| _d S ru   )rA   ry   r   r   r   r   
forceChain)rx   r   r   r   r   r  rv   rK   rK   rN   ry     s    zLigatureSubstStatement.__init__c                 C   sN   dd | j D }dd | jD }dd | jD }|| j|||| j| j d S )Nc                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   #  rP   z0LigatureSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   $  rP   c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   %  rP   )r   r   r   Zadd_ligature_substrv   r   r  r   rK   rK   rN   r|   "  s    zLigatureSubstStatement.buildr}   c                 C   s   d}t | jst | js| jrt | jrF|ddd | jD d 7 }|ddd | jD 7 }t | jr|dddd | jD  7 }n|ddd | jD 7 }|d7 }|t| j7 }|d	7 }|S )
Nr   r   c                 s   s   | ]}|  V  qd S ru   r   r   rK   rK   rN   rO   .  rP   z/LigatureSubstStatement.asFea.<locals>.<genexpr>c                 s   s   | ]}|  d  V  qdS r  r   r   rK   rK   rN   rO   /  rP   c                 s   s   | ]}|  V  qd S ru   r   r   rK   rK   rN   rO   1  rP   c                 s   s   | ]}|  V  qd S ru   r   r   rK   rK   rN   rO   3  rP    by r   )rq   r   r   r  rQ   r   rj   r   r   rK   rK   rN   rj   *  s    

 zLigatureSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r2     s   	
r2   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )r3   zA ``lookupflag`` statement. The ``value`` should be an integer value
    representing the flags in use, but not including the ``markAttachment``
    class and ``markFilteringSet`` values, which must be specified as
    glyph-containing objects.r   Nc                 C   s"   t | | || _|| _|| _d S ru   )rA   ry   r   markAttachmentmarkFilteringSet)rx   r   r  r  rv   rK   rK   rN   ry   @  s    zLookupFlagStatement.__init__c                 C   sH   d}| j dur| j  }d}| jdur0| j }|| j| j|| dS )z8Calls the builder object's ``set_lookup_flag`` callback.N)r  r   r  Zset_lookup_flagrv   r   )rx   r{   Z
markAttachZ
markFilterrK   rK   rN   r|   H  s    



zLookupFlagStatement.buildr}   c                 C   s   g }g d}d}t t|D ](}| j|@ dkr<|||  |d> }q| jd urf|d| j  | jd ur|d| j  |sdg}dd|S )	N)ZRightToLeftZIgnoreBaseGlyphsZIgnoreLigaturesZIgnoreMarksrl   r   zMarkAttachmentType {}zUseMarkFilteringSet {}0zlookupflag {};r   )	rangerq   r   r   r  r   rj   r  rQ   )rx   r   r   flagsr   r   rK   rK   rN   rj   R  s    


zLookupFlagStatement.asFea)r   NNN)r}   r   rK   rK   rK   rN   r3   :  s
    

r3   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r4   zRepresents a ``lookup ...;`` statement to include a lookup in a feature.

    The ``lookup`` should be a :class:`LookupBlock` object.Nc                 C   s   t | | || | _| _d S ru   )rA   ry   rv   r\   )rx   r\   rv   rK   rK   rN   ry   h  s    z!LookupReferenceStatement.__init__c                 C   s   | | jj dS )z8Calls the builder object's ``add_lookup_call`` callback.N)Zadd_lookup_callr\   ri   rz   rK   rK   rN   r|   l  s    zLookupReferenceStatement.buildr}   c                 C   s   d | jjS )Nz
lookup {};)r   r\   ri   r   rK   rK   rN   rj   p  s    zLookupReferenceStatement.asFea)N)r}   r   rK   rK   rK   rN   r4   c  s   
r4   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r5   zA mark-to-base positioning rule. The ``base`` should be a
    `glyph-containing object`_. The ``marks`` should be a list of
    (:class:`Anchor`, :class:`MarkClass`) tuples.Nc                 C   s   t | | || | _| _d S ru   )rA   ry   rg   marks)rx   rg   r  rv   rK   rK   rN   ry   y  s    zMarkBasePosStatement.__init__c                 C   s   | | j| j | j dS )z:Calls the builder object's ``add_mark_base_pos`` callback.N)Zadd_mark_base_posrv   rg   r   r  rz   rK   rK   rN   r|   }  s    zMarkBasePosStatement.buildr}   c                 C   sN   d | j }| jD ]*\}}|d| t d | |j 7 }q|d7 }|S )Nzpos base {}r   {} mark @{}r   )r   rg   rj   r  r   ri   rx   r   r   amrK   rK   rN   rj     s
    $zMarkBasePosStatement.asFea)N)r}   r   rK   rK   rK   rN   r5   t  s   
r5   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r6   a  A mark-to-ligature positioning rule. The ``ligatures`` must be a
    `glyph-containing object`_. The ``marks`` should be a list of lists: each
    element in the top-level list represents a component glyph, and is made
    up of a list of (:class:`Anchor`, :class:`MarkClass`) tuples representing
    mark attachment points for that position.

    Example::

        m1 = MarkClass("TOP_MARKS")
        m2 = MarkClass("BOTTOM_MARKS")
        # ... add definitions to mark classes...

        glyph = GlyphName("lam_meem_jeem")
        marks = [
            [ (Anchor(625,1800), m1) ], # Attachments on 1st component (lam)
            [ (Anchor(376,-378), m2) ], # Attachments on 2nd component (meem)
            [ ]                         # No attachments on the jeem
        ]
        mlp = MarkLigPosStatement(glyph, marks)

        mlp.asFea()
        # pos ligature lam_meem_jeem <anchor 625 1800> mark @TOP_MARKS
        # ligComponent <anchor 376 -378> mark @BOTTOM_MARKS;

    Nc                 C   s   t | | || | _| _d S ru   )rA   ry   	ligaturesr  )rx   r  r  rv   rK   rK   rN   ry     s    zMarkLigPosStatement.__init__c                 C   s   | | j| j | j dS )z9Calls the builder object's ``add_mark_lig_pos`` callback.N)Zadd_mark_lig_posrv   r  r   r  rz   rK   rK   rN   r|     s    zMarkLigPosStatement.buildr}   c                 C   s   d | j }g }| jD ]l}d}|d u s2t|sHd| td  d }n4|D ].\}}|d| td  d | |j 7 }qL|| q|d| t d |7 }|d7 }|S )	Nzpos ligature {}r}   r   rk   r   r  ZligComponentr   )	r   r  rj   r  rq   r   ri   r   rQ   )rx   r   r   Zligsltempr  r  rK   rK   rN   rj     s(    
zMarkLigPosStatement.asFea)N)r}   r   rK   rK   rK   rN   r6     s   
r6   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r7   zA mark-to-mark positioning rule. The ``baseMarks`` must be a
    `glyph-containing object`_. The ``marks`` should be a list of
    (:class:`Anchor`, :class:`MarkClass`) tuples.Nc                 C   s   t | | || | _| _d S ru   )rA   ry   	baseMarksr  )rx   r"  r  rv   rK   rK   rN   ry     s    zMarkMarkPosStatement.__init__c                 C   s   | | j| j | j dS )z:Calls the builder object's ``add_mark_mark_pos`` callback.N)Zadd_mark_mark_posrv   r"  r   r  rz   rK   rK   rN   r|     s    zMarkMarkPosStatement.buildr}   c                 C   sN   d | j }| jD ]*\}}|d| t d | |j 7 }q|d7 }|S )Nzpos mark {}r   r  r   )r   r"  rj   r  r   ri   r  rK   rK   rN   rj     s
    $zMarkMarkPosStatement.asFea)N)r}   r   rK   rK   rK   rN   r7     s   
r7   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )r8   a  A multiple substitution statement.

    Args:
        prefix: a list of `glyph-containing objects`_.
        glyph: a single glyph-containing object.
        suffix: a list of glyph-containing objects.
        replacement: a list of glyph-containing objects.
        forceChain: If true, the statement is expressed as a chaining rule
            (e.g. ``sub f' i' by f_i``) even when no context is given.
    FNc                 C   s2   t | | |||  | _| _| _|| _|| _d S ru   )rA   ry   r   r   r   r   r  )rx   r   r   r   r   r  rv   rK   rK   rN   ry     s    zMultipleSubstStatement.__init__c              	   C   s~   dd | j D }dd | jD }| js^t| jdr^| j D ]}|| j|||| j| j q<n|| j|| j|| j| j dS )z;Calls the builder object's ``add_multiple_subst`` callback.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z0MultipleSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   r   N)	r   r   r   rn   r   r   Zadd_multiple_substrv   r  )rx   r{   r   r   r   rK   rK   rN   r|     s(    	zMultipleSubstStatement.buildr}   c                 C   s   d}t | jst | js| jrzt | jrB|dtt| jd 7 }|t| jd 7 }t | jr|ddtt| j 7 }n|t| j7 }| jpt	 g}|d7 }|dtt|7 }|d7 }|S )Nr   r   r   r  r   )
rq   r   r   r  rQ   r   rj   r   r   r   )rx   r   r   r   rK   rK   rN   rj     s    

zMultipleSubstStatement.asFea)FN)r}   r   rK   rK   rK   rN   r8     s
    
r8   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )r;   a  A pair positioning statement.

    ``glyphs1`` and ``glyphs2`` should be `glyph-containing objects`_.
    ``valuerecord1`` should be a :class:`ValueRecord` object;
    ``valuerecord2`` should be either a :class:`ValueRecord` object or ``None``.
    If ``enumerated`` is true, then this is expressed as an
    `enumerated pair <https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#6.b.ii>`_.
    FNc                 C   s2   t | | || _|| | _| _|| | _| _d S ru   )rA   ry   
enumeratedglyphs1valuerecord1glyphs2valuerecord2)rx   r$  r%  r&  r'  r#  rv   rK   rK   rN   ry     s    	zPairPosStatement.__init__c                 C   s   | j rb| j | j g}d}tj| D ]$\}}d}|| j|| j|| j	 q(|s^t
d| jdS t| jtoxt| jt}|r|| j| jj| j| jj| j	 n$|| j| j | j| j | j	 dS )aM  Calls a callback on the builder object:

        * If the rule is enumerated, calls ``add_specific_pair_pos`` on each
          combination of first and second glyphs.
        * If the glyphs are both single :class:`GlyphName` objects, calls
          ``add_specific_pair_pos``.
        * Else, calls ``add_class_pair_pos``.
        FTz%Empty glyph class in positioning ruleN)r#  r$  r   r&  	itertoolsproductZadd_specific_pair_posrv   r%  r'  r   ro   r   r   Zadd_class_pair_pos)rx   r{   rt   Z	seen_pairZglyph1Zglyph2Zis_specificrK   rK   rN   r|   +  s>    	zPairPosStatement.buildr}   c                 C   sj   | j r
dnd}| jrB|d| j | j | j | j 7 }n$|d| j | j | j 7 }|S )Nzenum r}   zpos {} {} {} {};zpos {} {} {};)r#  r'  r   r$  rj   r%  r&  r   rK   rK   rN   rj   V  s    zPairPosStatement.asFea)FN)r}   r   rK   rK   rK   rN   r;     s     
+r;   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r<   aP  A reverse chaining substitution statement. You don't see those every day.

    Note the unusual argument order: ``suffix`` comes `before` ``glyphs``.
    ``old_prefix``, ``old_suffix``, ``glyphs`` and ``replacements`` should be
    lists of `glyph-containing objects`_. ``glyphs`` and ``replacements`` should
    be one-item lists.
    Nc                 C   s*   t | | || | _| _|| _|| _d S ru   )rA   ry   
old_prefix
old_suffixr   replacements)rx   r*  r+  r   r,  rv   rK   rK   rN   ry   o  s    z)ReverseChainSingleSubstStatement.__init__c              	   C   st   dd | j D }dd | jD }| jd  }| jd  }t|dkrT|t| }|| j||tt	|| d S )Nc                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   v  rP   z:ReverseChainSingleSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r   w  rP   r   rl   )
r*  r+  r   r   r,  rq   Zadd_reverse_chain_single_substrv   dictziprx   r{   r   r   Z	originalsZreplacesrK   rK   rN   r|   u  s    z&ReverseChainSingleSubstStatement.buildr}   c                 C   s   d}t | jst | jrt | jr@|ddd | jD d 7 }|ddd | jD 7 }t | jr|dddd | jD  7 }n|dtt| j7 }|dddd | jD 7 }|S )	Nzrsub r   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   z9ReverseChainSingleSubstStatement.asFea.<locals>.<genexpr>c                 s   s   | ]}t |d  V  qdS r  r   r   rK   rK   rN   rO     rP   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP    by {};c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   )	rq   r*  r+  rQ   r   r   rj   r   r,  r   rK   rK   rN   rj     s    

  z&ReverseChainSingleSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r<   f  s   
r<   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r?   a.  A single substitution statement.

    Note the unusual argument order: ``prefix`` and suffix come `after`
    the replacement ``glyphs``. ``prefix``, ``suffix``, ``glyphs`` and
    ``replace`` should be lists of `glyph-containing objects`_. ``glyphs`` and
    ``replace`` should be one-item lists.
    Nc                 C   s0   t | | || | _| _|| _|| _|| _d S ru   )rA   ry   r   r   r  r   r,  )rx   r   replacer   r   r  rv   rK   rK   rN   ry     s
    zSingleSubstStatement.__init__c              	   C   sx   dd | j D }dd | jD }| jd  }| jd  }t|dkrT|t| }|| j||tt	||| j
 dS )z9Calls the builder object's ``add_single_subst`` callback.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z.SingleSubstStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   r   rl   N)r   r   r   r   r,  rq   Zadd_single_substrv   r   r.  r  r/  rK   rK   rN   r|     s    zSingleSubstStatement.buildr}   c                 C   s   d}t | jst | js| jrt | jrF|ddd | jD d 7 }|ddd | jD 7 }t | jr|dddd | jD  7 }n|ddd | jD 7 }|ddd	d | jD 7 }|S )
Nr   r   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   z-SingleSubstStatement.asFea.<locals>.<genexpr>c                 s   s   | ]}t |d  V  qdS r  r   r   rK   rK   rN   rO     rP   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   r0  c                 s   s   | ]}t |V  qd S ru   r   r   rK   rK   rN   rO     rP   )rq   r   r   r  rQ   r   r   r,  r   rK   rK   rN   rj     s    

  zSingleSubstStatement.asFea)N)r}   r   rK   rK   rK   rN   r?     s   
r?   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r=   zA ``script`` statement.Nc                 C   s   t | | || _d S ru   )rA   ry   rc   )rx   rc   rv   rK   rK   rN   ry     s    zScriptStatement.__init__c                 C   s   | | j| j dS )z,Calls the builder's ``set_script`` callback.N)Z
set_scriptrv   rc   rz   rK   rK   rN   r|     s    zScriptStatement.buildr}   c                 C   s   d | j S )Nz
script {};)r   rc   r   r   rK   rK   rN   rj     s    zScriptStatement.asFea)N)r}   r   rK   rK   rK   rN   r=     s   
r=   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r>   zA single position statement. ``prefix`` and ``suffix`` should be
    lists of `glyph-containing objects`_.

    ``pos`` should be a one-element list containing a (`glyph-containing object`_,
    :class:`ValueRecord`) tuple.Nc                 C   s,   t | | |||  | _| _| _|| _d S ru   )rA   ry   r`   r   r   r  )rx   r`   r   r   r  rv   rK   rK   rN   ry     s    zSinglePosStatement.__init__c                 C   sJ   dd | j D }dd | jD }dd | jD }|| j|||| j dS )z7Calls the builder object's ``add_single_pos`` callback.c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   z,SinglePosStatement.build.<locals>.<listcomp>c                 S   s   g | ]}|  qS rK   r   r   rK   rK   rN   r     rP   c                 S   s   g | ]\}}|  |fqS rK   r   )rL   rt   r   rK   rK   rN   r     rP   N)r   r   r`   Zadd_single_posrv   r  )rx   r{   r   r   r`   rK   rK   rN   r|     s    zSinglePosStatement.buildr}   c                 C   s   d}t | jst | js| jrt | jrB|dtt| jd 7 }|ddd | jD 7 }t | jr|ddtt| j 7 }n|ddd | jD 7 }|d7 }|S )Nr   r   c                 S   s8   g | ]0}t |d  d |d r.d|d    nd qS )r   r   rl   r   r}   r   r   rK   rK   rN   r     s   z,SinglePosStatement.asFea.<locals>.<listcomp>c                 S   s4   g | ],}t |d  d |d r*|d   nd qS )r   r   rl   r}   r   r   rK   rK   rN   r     rP   r   )rq   r   r   r  rQ   r   rj   r`   r   rK   rK   rN   rj     s     

zSinglePosStatement.asFea)N)r}   r   rK   rK   rK   rN   r>     s   
r>   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )rE   zRepresents a subtable break.Nc                 C   s   t | | d S ru   )rA   ry   rw   rK   rK   rN   ry     s    zSubtableStatement.__init__c                 C   s   | | j dS )z<Calls the builder objects's ``add_subtable_break`` callback.N)Zadd_subtable_breakrv   rz   rK   rK   rN   r|     s    zSubtableStatement.buildr}   c                 C   s   dS )Nz	subtable;rK   r   rK   rK   rN   rj     s    zSubtableStatement.asFea)N)r}   r   rK   rK   rK   rN   rE     s   
rE   c                
   @   sH   e Zd ZdZdddZdd Zdd	 Zd
d ZdddZdd Z	e	Z
dS )rG   zRepresents a value record.NFc                 C   sN   t | |
 || | _| _|| | _| _|| | _| _|| | _| _	|	| _
d S ru   )r&   ry   
xPlacement
yPlacementxAdvanceyAdvance
xPlaDevice
yPlaDevice
xAdvDevice
yAdvDevicevertical)rx   r2  r3  r4  r5  r6  r7  r8  r9  r:  rv   rK   rK   rN   ry     s    zValueRecord.__init__c                 C   sH   | j |j koF| j|jkoF| j|jkoF| j|jkoF| j|jkoF| j|jkS ru   )r2  r3  r4  r5  r6  r8  rx   otherrK   rK   rN   __eq__  s    




zValueRecord.__eq__c                 C   s   |  | S ru   )r=  r;  rK   rK   rN   __ne__"  s    zValueRecord.__ne__c                 C   sP   t | jt | jA t | jA t | jA t | jA t | jA t | jA t | jA S ru   )	hashr2  r3  r4  r5  r6  r7  r8  r9  r   rK   rK   rN   __hash__%  s     zValueRecord.__hash__r}   c              
   C   s   | sdS | j | j }}| j| j }}| j| j }}| j| j }}	| j}
|d u r~|d u r~|d u rj|
rjt	|S |d u r~|
s~t	|S |pd}|pd}|pd}|pd}|d u r|d u r|d u r|	d u rd||||f S d||||t
|t
|t
|t
|	f S )Nz<NULL>r   z<%s %s %s %s>z<%s %s %s %s %s %s %s %s>)r2  r3  r4  r5  r6  r7  r8  r9  r:  r   rS   )rx   r   r   r   r4  r5  r6  r7  r8  r9  r:  rK   rK   rN   rj   1  sF    zValueRecord.asFeac                    s   t  fdddD S )Nc                 3   s   | ]}t  |d uV  qd S ru   )getattr)rL   vr   rK   rN   rO   ^  s   z'ValueRecord.__bool__.<locals>.<genexpr>)r2  r3  r4  r5  r6  r7  r8  r9  )r   r   rK   r   rN   __bool__]  s    zValueRecord.__bool__)
NNNNNNNNFN)r}   )r   r   r   r   ry   r=  r>  r@  rj   rC  __nonzero__rK   rK   rK   rN   rG     s$             


,rG   c                   @   s$   e Zd ZdZdddZd	ddZdS )
rH   z+Represents a named value record definition.Nc                 C   s   t | | || _|| _d S ru   )rA   ry   ri   r   )rx   ri   r   rv   rK   rK   rN   ry   r  s    zValueRecordDefinition.__init__r}   c                 C   s   d | j | jS )NzvalueRecordDef {} {};)r   r   rj   ri   r   rK   rK   rN   rj   w  s    zValueRecordDefinition.asFea)N)r}   r   rK   rK   rK   rN   rH   o  s   
rH   c                 C   sJ   | dkr|dkr|dkrdS | dkr8|dkr8|dkr8dS d | ||S d S )N   rl   i	  r}   r   1{} {} {}r   )pidZeidlidrK   rK   rN   simplify_name_attributes{  s
    rK  c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r9   zRepresents a name record. (`Section 9.e. <https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#9.e>`_)Nc                 C   s.   t | | || _|| _|| _|| _|| _d S ru   )rA   ry   nameID
platformID	platEncIDlangIDstring)rx   rL  rM  rN  rO  rP  rv   rK   rK   rN   ry     s    zNameRecord.__init__c                 C   s$   | | j| j| j| j| j| j dS )z8Calls the builder object's ``add_name_record`` callback.N)Zadd_name_recordrv   rL  rM  rN  rO  rP  rz   rK   rK   rN   r|     s    zNameRecord.buildr}   c                    s   dd  t | j| j| j}|d u r.td| jt| j|d|dkrld fddt	d	t
d
D }nd fddD }t| j| j| j}|dkr|d7 }d| j||S )Nc                 S   s,   | dkr | dkr | dvr t | S ||  S d S )N    ~   )"   \   )chr)r   Zescape_patternrK   rK   rN   escape  s    z NameRecord.asFea.<locals>.escapezUnsupported encoding)encoding	utf_16_ber}   c                    s2   g | ]*} t | d  t |d   dqS )   rl   z\%04xr   rL   r   rV  r   rK   rN   r     s   z$NameRecord.asFea.<locals>.<listcomp>r   rk   c                    s   g | ]} t |d qS )z\%02xrZ  )rL   b)rV  rK   rN   r     rP   r   znameid {} {}"{}";)r   rM  rN  rO  r   rv   r   rP  rQ   r  rq   rK  r   rL  )rx   r   rW  escaped_stringplatrK   r\  rN   rj     s     zNameRecord.asFea)N)r}   r   rK   rK   rK   rN   r9     s   
r9   c                   @   s"   e Zd ZdZdd ZdddZdS )	r'   z4Represents a ``sizemenuname`` or ``name`` statement.c                 C   s   t | | || j dS )z8Calls the builder object's ``add_featureName`` callback.N)r9   r|   Zadd_featureNamerL  rz   rK   rK   rN   r|     s    zFeatureNameStatement.buildr}   c                 C   sF   | j dkrd}nd}t| j| j| j}|dkr6|d7 }d||| jS )NsizeZsizemenunameri   r}   r   z
{} {}"{}";)rL  rK  rM  rN  rO  r   rP  )rx   r   r   r_  rK   rK   rN   rj     s    
zFeatureNameStatement.asFeaN)r}   )r   r   r   r   r|   rj   rK   rK   rK   rN   r'     s   r'   c                   @   s   e Zd ZdZdddZdS )rD   z+Represents a STAT table ``name`` statement.r}   c                 C   s0   t | j| j| j}|dkr"|d7 }d|| jS Nr}   r   zname {}"{}";rK  rM  rN  rO  r   rP  rx   r   r_  rK   rK   rN   rj     s    zSTATNameStatement.asFeaN)r}   )r   r   r   r   rj   rK   rK   rK   rN   rD     s   rD   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r@   zA ``parameters`` statement.Nc                 C   s(   t | | || _|| _|| _|| _d S ru   )rA   ry   
DesignSizeSubfamilyID
RangeStartRangeEnd)rx   rd  re  rf  rg  rv   rK   rK   rN   ry     s
    zSizeParameters.__init__c                 C   s    | | j| j| j| j| j dS )z<Calls the builder object's ``set_size_parameters`` callback.N)Zset_size_parametersrv   rd  re  rf  rg  rz   rK   rK   rN   r|     s    zSizeParameters.buildr}   c                 C   sP   d | j| j}| jdks$| jdkrH|d t| jd t| jd 7 }|d S )Nzparameters {:.1f} {}r   z {} {}
   r   )r   rd  re  rf  rg  intr   rK   rK   rN   rj     s    $zSizeParameters.asFea)N)r}   r   rK   rK   rK   rN   r@     s   

r@   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   z;Represent a name statement inside a ``cvParameters`` block.Nc              	   C   s"   t j| ||||||d || _d S r   )r9   ry   r   )rx   rL  rM  rN  rO  rP  r   rv   rK   rK   rN   ry     s    z"CVParametersNameStatement.__init__c                 C   sR   d}| j dkr$d|j| jd}|| j | j| j | f| _t| | dS )z9Calls the builder object's ``add_cv_parameter`` callback.r}   r   z_{}r   N)r   r   Zcv_num_named_params_getrL  Zadd_cv_parameterr9   r|   )rx   r{   itemrK   rK   rN   r|     s    
zCVParametersNameStatement.buildr}   c                 C   s0   t | j| j| j}|dkr"|d7 }d|| jS ra  rb  rc  rK   rK   rN   rj     s    zCVParametersNameStatement.asFea)N)r}   r   rK   rK   rK   rN   r     s
    
	r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r!   a  
    Statement used in cvParameters blocks of Character Variant features (cvXX).
    The Unicode value may be written with either decimal or hexadecimal
    notation. The value must be preceded by '0x' if it is a hexadecimal value.
    The largest Unicode value allowed is 0xFFFFFF.
    Nc                 C   s   t | | || _|| _d S ru   )rA   ry   	characterr   )rx   rl  r   rv   rK   rK   rN   ry     s    zCharacterStatement.__init__c                 C   s   | | j| j dS )z9Calls the builder object's ``add_cv_character`` callback.N)Zadd_cv_characterrl  r   rz   rK   rK   rN   r|     s    zCharacterStatement.buildr}   c                 C   s   d | jS )NzCharacter {:#x};)r   rl  r   rK   rK   rN   rj     s    zCharacterStatement.asFea)N)r}   r   rK   rK   rK   rN   r!     s   
r!   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r   zAn axis definition, being either a ``VertAxis.BaseTagList/BaseScriptList``
    pair or a ``HorizAxis.BaseTagList/BaseScriptList`` pair.Nc                 C   s"   t | | || _|| _|| _d S ru   )rA   ry   basesscriptsr:  )rx   rm  rn  r:  rv   rK   rK   rN   ry   !  s    zBaseAxis.__init__c                 C   s   | | j| j| j dS )z6Calls the builder object's ``set_base_axis`` callback.N)Zset_base_axisrm  rn  r:  rz   rK   rK   rN   r|   '  s    zBaseAxis.buildr}   c              	   C   s>   | j r
dnd}dd | jD }d|d| j||d|S )NZVertZHorizc                 S   s2   g | ]*}d  |d |d dtt|d qS )rG  r   rl   r   rk   )r   rQ   r   r   )rL   r  rK   rK   rN   r   -  s   z"BaseAxis.asFea.<locals>.<listcomp>z2{}Axis.BaseTagList {};
{}{}Axis.BaseScriptList {};r   rJ   )r:  rn  r   rQ   rm  )rx   r   	directionrn  rK   rK   rN   rj   +  s    zBaseAxis.asFea)N)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r:   zAn entry in the ``OS/2`` table. Most ``values`` should be numbers or
    strings, apart from when the key is ``UnicodeRange``, ``CodePageRange``
    or ``Panose``, in which case it should be an array of integers.Nc                 C   s   t | | || _|| _d S ru   rA   ry   r   r   rx   r   r   rv   rK   rK   rN   ry   ;  s    zOS2Field.__init__c                 C   s   | | j| j dS )z6Calls the builder object's ``add_os2_field`` callback.N)Zadd_os2_fieldr   r   rz   rK   rK   rN   r|   @  s    zOS2Field.buildr}   c                    s   dd  d}d}t dd |D }| fdd|D  d g|d	< d
dd g|d< | j|v rd|| j d || j d | jS dS )Nc                 S   s   d tt| S )Nr   )rQ   r   r   )r   rK   rK   rN   
intarr2strE  s    z"OS2Field.asFea.<locals>.intarr2str)ZFSTypeZTypoAscenderZTypoDescenderZTypoLineGapZ	winAscentZ
winDescentZXHeightZ	CapHeightZWeightClassZ
WidthClassZLowerOpSizeZUpperOpSize)ZUnicodeRangeZCodePageRangec                 S   s   g | ]}|  |tgfqS rK   )rr   r   r   rK   rK   rN   r   W  rP   z"OS2Field.asFea.<locals>.<listcomp>c                    s   g | ]}|  | gfqS rK   rr   r   rr  rK   rN   r   X  rP   ZPanoseZpanoseZVendorc                 S   s
   d | S )Nz"{}"rH  )r   rK   rK   rN   <lambda>Z  rP   z OS2Field.asFea.<locals>.<lambda>vendor{} {};r   rl   r}   )r-  updater   r   r   )rx   r   numbersrangeskeywordsrK   rt  rN   rj   D  s    
zOS2Field.asFea)N)r}   r   rK   rK   rK   rN   r:   6  s   
r:   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r*   zAn entry in the ``hhea`` table.Nc                 C   s   t | | || _|| _d S ru   rp  rq  rK   rK   rN   ry   e  s    zHheaField.__init__c                 C   s   | | j| j dS )z7Calls the builder object's ``add_hhea_field`` callback.N)Zadd_hhea_fieldr   r   rz   rK   rK   rN   r|   j  s    zHheaField.buildr}   c                 C   s*   d}t dd |D }d|| j | jS )N)ZCaretOffsetZAscenderZ	DescenderZLineGapc                 S   s   g | ]}|  |fqS rK   rs  r   rK   rK   rN   r   p  rP   z#HheaField.asFea.<locals>.<listcomp>rw  r-  r   r   r   rx   r   fieldsr{  rK   rK   rN   rj   n  s    zHheaField.asFea)N)r}   r   rK   rK   rK   rN   r*   b  s   
r*   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )rI   zAn entry in the ``vhea`` table.Nc                 C   s   t | | || _|| _d S ru   rp  rq  rK   rK   rN   ry   w  s    zVheaField.__init__c                 C   s   | | j| j dS )z7Calls the builder object's ``add_vhea_field`` callback.N)Zadd_vhea_fieldr   r   rz   rK   rK   rN   r|   |  s    zVheaField.buildr}   c                 C   s*   d}t dd |D }d|| j | jS )N)ZVertTypoAscenderZVertTypoDescenderZVertTypoLineGapc                 S   s   g | ]}|  |fqS rK   rs  r   rK   rK   rN   r     rP   z#VheaField.asFea.<locals>.<listcomp>rw  r|  r}  rK   rK   rN   rj     s    zVheaField.asFea)N)r}   r   rK   rK   rK   rN   rI   t  s   
rI   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )rC   zA STAT table Design Axis

    Args:
        tag (str): a 4 letter axis tag
        axisOrder (int): an int
        names (list): a list of :class:`STATNameStatement` objects
    Nc                 C   s(   t | | || _|| _|| _|| _d S ru   )rA   ry   r   	axisOrdernamesrv   )rx   r   r  r  rv   rK   rK   rN   ry     s
    z STATDesignAxisStatement.__init__c                 C   s   | | | j d S ru   )ZaddDesignAxisrv   rz   rK   rK   rN   r|     s    zSTATDesignAxisStatement.buildr}   c                    sP    t 7  d| j d| j d}|d   fdd| jD d 7 }|d7 }|S )NzDesignAxis r   z { 
r   c                    s   g | ]}|j  d qS r   r   r   r   rK   rN   r     rP   z1STATDesignAxisStatement.asFea.<locals>.<listcomp>};)r   r   r  rQ   r  r   rK   r   rN   rj     s
    &zSTATDesignAxisStatement.asFea)N)r}   r   rK   rK   rK   rN   rC     s   
rC   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r$   ziSTAT table ElidedFallbackName

    Args:
        names: a list of :class:`STATNameStatement` objects
    Nc                 C   s   t | | || _|| _d S ru   )rA   ry   r  rv   )rx   r  rv   rK   rK   rN   ry     s    zElidedFallbackName.__init__c                 C   s   | | j| j d S ru   )setElidedFallbackNamer  rv   rz   rK   rK   rN   r|     s    zElidedFallbackName.buildr}   c                    s>    t 7  d}|d   fdd| jD d 7 }|d7 }|S )NzElidedFallbackName { 
r   c                    s   g | ]}|j  d qS r   r   r   r   rK   rN   r     rP   z,ElidedFallbackName.asFea.<locals>.<listcomp>r  )r   rQ   r  r   rK   r   rN   rj     s
    &zElidedFallbackName.asFea)N)r}   r   rK   rK   rK   rN   r$     s   
r$   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r%   zpSTAT table ElidedFallbackNameID

    Args:
        value: an int pointing to an existing name table name ID
    Nc                 C   s   t | | || _|| _d S ru   )rA   ry   r   rv   )rx   r   rv   rK   rK   rN   ry     s    zElidedFallbackNameID.__init__c                 C   s   | | j| j d S ru   )r  r   rv   rz   rK   rK   rN   r|     s    zElidedFallbackNameID.buildr}   c                 C   s   d| j  dS )NzElidedFallbackNameID r   )r   r   rK   rK   rN   rj     s    zElidedFallbackNameID.asFea)N)r}   r   rK   rK   rK   rN   r%     s   
r%   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )rB   zA STAT table Axis Value Record

    Args:
        names (list): a list of :class:`STATNameStatement` objects
        locations (list): a list of :class:`AxisValueLocationStatement` objects
        flags (int): an int
    Nc                 C   s"   t | | || _|| _|| _d S ru   )rA   ry   r  	locationsr  )rx   r  r  r  rv   rK   rK   rN   ry     s    zSTATAxisValueStatement.__init__c                 C   s   | | | j d S ru   )ZaddAxisValueRecordrv   rz   rK   rK   rN   r|     s    zSTATAxisValueStatement.buildr}   c           	      C   s   d}| j D ]}|| 7 }q
| jD ]}|| 7 }|d7 }q"| jrddg}g }d}tt|D ](}| j|@ dkr~|||  |d> }q^|dd| d	7 }|d
7 }|S )NzAxisValue {
r   ZOlderSiblingFontAttributeZElidableAxisValueNamerl   r   zflag r   ;
r  )r  rj   r  r  r  rq   r   rQ   )	rx   r   r   rv   Z
nameRecordr  ZflagStringsr   r   rK   rK   rN   rj     s"    



zSTATAxisValueStatement.asFea)N)r}   r   rK   rK   rK   rN   rB     s   
rB   c                   @   s$   e Zd ZdZdddZd	ddZdS )
r   z
    A STAT table Axis Value Location

    Args:
        tag (str): a 4 letter axis tag
        values (list): a list of ints and/or floats
    Nc                 C   s   t | | || _|| _d S ru   )rA   ry   r   values)rx   r   r  rv   rK   rK   rN   ry     s    z#AxisValueLocationStatement.__init__r}   c                 C   s6   |d| j  d7 }|ddd | jD  d7 }|S )Nz	location r   c                 s   s   | ]}t |V  qd S ru   r   r[  rK   rK   rN   rO     rP   z3AxisValueLocationStatement.asFea.<locals>.<genexpr>r  )r   rQ   r  )rx   r   rK   rK   rN   rj     s     z AxisValueLocationStatement.asFea)N)r}   r   rK   rK   rK   rN   r     s   
r   c                   @   s,   e Zd ZdZd
ddZdd Zddd	ZdS )r"   z
    A variable layout conditionset

    Args:
        name (str): the name of this conditionset
        conditions (dict): a dictionary mapping axis tags to a
            tuple of (min,max) userspace coordinates.
    Nc                 C   s   t | | || _|| _d S ru   )rA   ry   ri   
conditions)rx   ri   r  rv   rK   rK   rN   ry     s    zConditionsetStatement.__init__c                 C   s   | | j| j d S ru   )Zadd_conditionsetri   r  rz   rK   rK   rN   r|     s    zConditionsetStatement.buildr}   c              	   C   sr   ||d| j  d d 7 }| j D ].\}\}}||t | d| d| d 7 }q$||d d| j  d 7 }|S )Nzconditionset r   r   r  })ri   r  r   r   )rx   r   r   r   ZminvalueZmaxvaluerK   rK   rN   rj     s
    $zConditionsetStatement.asFea)N)r}   r}   r   rK   rK   rK   rN   r"     s   	
r"   c                   @   s,   e Zd ZdZdddZdd Zdd	d
ZdS )VariationBlockzCA variation feature block, applicable in a given set of conditions.FNc                 C   s&   t | | |||  | _| _| _d S ru   )r   ry   ri   conditionsetr   )rx   ri   r  r   rv   rK   rK   rN   ry   $  s
    zVariationBlock.__init__c                 C   s   | | j| j | jdkr:| j|jvr:td| j | j|j}i |_t| | |j	 D ]:\}}|j
|i | jg }|| ||vr\g ||< q\||_|  dS )r   r   z,variation block used undefined conditionset N)r   rv   ri   r  Zconditionsets_r   r   r   r|   r   Zfeature_variations_r   r   r   )rx   r{   r   r   r   r   rK   rK   rN   r|   ,  s*    



zVariationBlock.buildr}   c                 C   sb   |d| j    }|| jd 7 }| jr.|d7 }|d7 }|tj| |d7 }||d| j    7 }|S )Nzvariation %s r   r   r   r   r   )ri   r   r  r   r   rj   r   rK   rK   rN   rj   H  s    zVariationBlock.asFea)FN)r}   r   rK   rK   rK   rN   r  !  s   
r  )XZfontTools.feaLib.errorr   ZfontTools.feaLib.locationr   ZfontTools.misc.encodingToolsr   ZfontTools.misc.textToolsr   r   collectionsr   r(  r   __all__rS   r  rs   rj   objectr   rA   r&   r
   r   r   r   r   r   r   r   r	   r   r   r   rF   r   r   r   r   r   r   r   r   r   r    r#   r(   r+   r,   r-   r.   r/   r)   r0   r1   r2   r3   r4   r5   r6   r7   r8   r;   r<   r?   r=   r>   rE   rG   rH   rK  r9   r'   rD   r@   r   r!   r   r:   r*   rI   rC   r$   r%   rB   r   r"   r  rK   rK   rK   rN   <module>   s   F:> -'%%::$$')8=S(.(n	1
,(