
    jkeI                     V   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	 Z eg d
      Zd Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d  d!e      Z G d" d#e      Z G d$ d%e      Z G d& d'e      Z  G d( d)e      Z! G d* d+e      Z" G d, d-e      Z# G d. d/e      Z$ G d0 d1e      Z% G d2 d3e      Z& G d4 d5e      Z' G d6 d7e      Z( G d8 d9e      Z) G d: d;e      Z* G d< d=e      Z+ G d> d?e      Z, G d@ dAe      Z- G dB dCe      Z. G dD dEe      Z/ G dF dGe      Z0 G dH dIe      Z1 G dJ dKe      Z2 G dL dMe      Z3 G dN dOe      Z4 G dP dQe      Z5 G dR dSe      Z6 G dT dUe      Z7 G dV dWe      Z8 G dX dYe      Z9 G dZ d[e      Z: G d\ d]e      Z; G d^ d_e      Z< G d` dae      Z= G db dce      Z> G dd dee      Z? G df dge      Z@ G dh die      ZA G dj dke      ZB G dl dme      ZC G dn doe      ZD G dp dqe      ZEdr ZF G ds dte      ZG G du dveG      ZH G dw dxeG      ZI G dy dze      ZJ G d{ d|eG      ZK G d} d~e      ZL G d de      ZM G d de      ZN G d de      ZO G d de      ZP G d de      ZQ G d de      ZR G d de      ZS G d de      ZT G d de      ZU G d de      ZV G d de      ZWy)    )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                 >    | yddj                  d | D              z  S )Nz<device NULL>z<device %s>, c              3   &   K   | ]	  }d |z    yw)z%d %dN ).0ts     6/usr/lib/python3/dist-packages/fontTools/feaLib/ast.py	<genexpr>z!deviceToString.<locals>.<genexpr>T   s     (E1(Es   )join)devices    rQ   deviceToStringrU   P   s$    ~tyy(Ef(EEEE    )4anchor	anchordefanon	anonymousbycontourcursiverT   enum	enumerateexcludedfltexclude_dfltfeaturefromignoreignorebaseglyphsignoreligaturesignoremarksincludeincludedfltinclude_dfltlanguagelanguagesystemlookup
lookupflagmarkmarkattachmenttype	markclassnameidnull
parameterspospositionrequiredrighttoleft
reversesubrsubscriptsub
substitutesubtabletableusemarkfilteringsetuseextensionvaluerecorddefbasegdefheadhheanamevheavmtxc                     t        | d      r| j                         S t        | t              r.t	        |       dk(  r t        | d         dz   t        | d         z   S | j                         t        v rd| z   S | S )NasFea   r   z -    \)hasattrr   
isinstancetuplelenlowerfea_keywords)gs    rQ   r   r      sh    q'wwy	Au	#a&A+QqT{U"U1Q4[00	
l	"axrV   c                   ,    e Zd ZdZddZd ZddZd Zy)	r	   z8A base class representing "something" in a feature file.Nc                 F    |rt        |t              st        | }|| _        y N)r   r   locationselfr   s     rQ   __init__zElement.__init__   s     Jx1CD)84H rV   c                      y r   rN   r   builders     rQ   buildzElement.build   s    rV   c                     t         )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.)NotImplementedErrorr   indents     rQ   r   zElement.asFea   s
     "!rV   c                 "    | j                         S r   r   r   s    rQ   __str__zElement.__str__   s    zz|rV   r    )__name__
__module____qualname____doc__r   r   r   r   rN   rV   rQ   r	   r	      s    B!"rV   r	   c                       e Zd Zy)rB   Nr   r   r   rN   rV   rQ   rB   rB          rV   rB   c                       e Zd Zy)r'   Nr   rN   rV   rQ   r'   r'      r   rV   r'   c                   ,     e Zd ZdZd fd	ZddZ xZS )r   zA comment in a feature file.c                 :    t         t        |   |       || _        y r   )superr   r   text)r   r   r   	__class__s      rQ   r   zComment.__init__   s    gt%h/	rV   c                     | j                   S r   )r   r   s     rQ   r   zComment.asFea   s    yyrV   r   r   r   r   r   r   r   r   __classcell__r   s   @rQ   r   r      s    &
rV   r   c                   &    e Zd ZdZddZd ZddZy)	NullGlyphz5The NULL glyph, used in glyph deletion substitutions.Nc                 0    t         j                  | |       y r   )r'   r   r   s     rQ   r   zNullGlyph.__init__   s    D(+rV   c                      y)BThe glyphs in this class as a tuple of :class:`GlyphName` objects.rN   rN   r   s    rQ   glyphSetzNullGlyph.glyphSet   s    rV   c                      y)NNULLrN   r   s     rQ   r   zNullGlyph.asFea   s    rV   r   r   r   r   r   r   r   r   r   rN   rV   rQ   r   r      s    ?,rV   r   c                   &    e Zd ZdZddZd ZddZy)r   z)A single glyph name, such as ``cedilla``.Nc                 >    t         j                  | |       || _        y r   )r'   r   glyph)r   r   r   s      rQ   r   zGlyphName.__init__   s    D(+
rV   c                     | j                   fS r   )r   r   s    rQ   r   zGlyphName.glyphSet   s    

}rV   c                 ,    t        | j                        S r   )r   r   r   s     rQ   r   zGlyphName.asFea   s    TZZ  rV   r   r   r   rN   rV   rQ   r   r      s    3
!rV   r   c                   D    e Zd ZdZddZd ZddZd Zd Zd Z	d	 Z
d
 Zy)r   z1A glyph class, such as ``[acute cedilla grave]``.Nc                 b    t         j                  | |       ||ng | _        g | _        d| _        y )Nr   )r'   r   glyphsoriginalcurr)r   r   r   s      rQ   r   zGlyphClass.__init__   s.    D(+ & 2f	rV   c                 ,    t        | j                        S r   )r   r   r   s    rQ   r   zGlyphClass.glyphSet   s    T[[!!rV   c                    t        | j                        r| j                  t        | j                        k  rL| j                  j	                  | j                  | j                  d         t        | j                        | _        ddj                  t        t        | j                              z   dz   S ddj                  t        t        | j                              z   dz   S )N[ ])r   r   r   r   extendrS   mapr   r   s     rQ   r   zGlyphClass.asFea   s    t}}yy3t{{++$$T[[%=>,	#eT]]";<<sBB#eT[["9::S@@rV   c                 :    | j                   j                  |       y)z6Add a list of :class:`GlyphName` objects to the class.N)r   r   )r   r   s     rQ   r   zGlyphClass.extend   s    6"rV   c                 :    | j                   j                  |       y)z4Add a single :class:`GlyphName` object to the class.N)r   append)r   r   s     rQ   r   zGlyphClass.append   s    5!rV   c                 P   | j                   t        | j                        k  r2| j                  j	                  | j                  | j                   d        | j                  j                  ||f       | j                  j	                  |       t        | j                        | _         y)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   r   r   r   r   r   r   startendr   s       rQ   	add_rangezGlyphClass.add_range  sr    
 99s4;;''MM  TYY[!9:eS\*6"$	rV   c                    | j                   t        | j                        k  r2| j                  j	                  | j                  | j                   d        | j                  j                  dj                  |      dj                  |      f       | j                  j	                  |       t        | j                        | _         y)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   r   r   r   r   r   formatr   s       rQ   add_cid_rangezGlyphClass.add_cid_range  s     99s4;;''MM  TYY[!9:fmmE2FMM#4FGH6"$	rV   c                 h   | j                   t        | j                        k  r2| j                  j	                  | j                  | j                   d        | j                  j                  |       | j                  j	                  |j                                t        | j                        | _         y)zNAdd glyphs from the given :class:`GlyphClassName` object to the
        class.N)r   r   r   r   r   r   r   )r   gcs     rQ   	add_classzGlyphClass.add_class  st     99s4;;''MM  TYY[!9:R 2;;=)$	rV   NNr   )r   r   r   r   r   r   r   r   r   r   r   r   rN   rV   rQ   r   r      s.    ;"A#"	%%%rV   r   c                   &    e Zd ZdZddZd ZddZy)r   zyA glyph class name, such as ``@FRENCH_MARKS``. This must be instantiated
    with a :class:`GlyphClassDefinition` object.Nc                 b    t         j                  | |       t        |t              sJ || _        y r   )r'   r   r   r   
glyphclass)r   r   r   s      rQ   r   zGlyphClassName.__init__'  s*    D(+*&:;;;$rV   c                 H    t        | j                  j                               S r   )r   r   r   r   s    rQ   r   zGlyphClassName.glyphSet,  s    T__--/00rV   c                 4    d| j                   j                  z   S N@)r   r   r   s     rQ   r   zGlyphClassName.asFea0  s    T__))))rV   r   r   r   rN   rV   rQ   r   r   #  s    4%
1*rV   r   c                   &    e Zd ZdZddZd ZddZy)r   zA mark class name, such as ``@FRENCH_MARKS`` defined with ``markClass``.
    This must be instantiated with a :class:`MarkClass` object.Nc                 b    t         j                  | |       t        |t              sJ || _        y r   )r'   r   r   r   	markClass)r   r   r   s      rQ   r   zMarkClassName.__init__8  s)    D(+)Y///"rV   c                 6    | j                   j                         S r   )r   r   r   s    rQ   r   zMarkClassName.glyphSet=  s    ~~&&((rV   c                 4    d| j                   j                  z   S r   )r   r   r   s     rQ   r   zMarkClassName.asFeaA  s    T^^((((rV   r   r   r   rN   rV   rQ   r   r   4  s    C#
))rV   r   c                        e Zd ZdZddZddZy)r   zAn anonymous data block.Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   tagcontent)r   r   r   r   s       rQ   r   zAnonymousBlock.__init__H  s     4*rV   c                     dj                  | j                        }|| j                  z  }|dj                  | j                        z  }|S )Nzanon {} {{
z}} {};

)r   r   r   r   r   ress      rQ   r   zAnonymousBlock.asFeaM  sB    ##DHH-t|||""488,,
rV   r   r   r   r   r   r   r   r   rN   rV   rQ   r   r   E  s    "
rV   r   c                   &    e Zd ZdZddZd ZddZy)r   z,A block of statements: feature, lookup, etc.Nc                 >    t         j                  | |       g | _        y r   )rB   r   
statementsr   s     rQ   r   zBlock.__init__W  s    4*rV   c                 H    | j                   D ]  }|j                  |        y)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   )r   r   ss      rQ   r   zBlock.build[  s#      	AGGG	rV   c           	          |t         z  }|d|z   j                  | j                  D cg c]  }|j                  |       c}      z   dz   S c c}w )N
r   )SHIFTrS   r   r   )r   r   r   s      rQ   r   zBlock.asFeab  sP    %f}""DOO#TqAGG6G$:#TUV	
#Ts   A
r   r   r   r   r   r   r   r   r   rN   rV   rQ   r   r   T  s    6
rV   r   c                       e Zd ZdZd ZddZy)r
   zpThe top-level element of the syntax tree, containing the whole feature
    file in its ``statements`` attribute.c                 @    t         j                  | d        i | _        y N)r   )r   r   markClassesr   s    rQ   r   zFeatureFile.__init__o  s    td+rV   c                 L    dj                  fd| j                  D              S )Nr   c              3   B   K   | ]  }|j                           yw)r  Nr   )rO   r   r   s     rQ   rR   z$FeatureFile.asFea.<locals>.<genexpr>t  s     IA/Is   )rS   r   r   s    `rQ   r   zFeatureFile.asFeas  s    yyIIIIrV   Nr   r   rN   rV   rQ   r
   r
   k  s    -JrV   r
   c                   &    e Zd ZdZddZd ZddZy)r   zA named feature block.Nc                 N    t         j                  | |       ||c| _        | _        y r   r   r   r   use_extensionr   r   r  r   s       rQ   r   zFeatureBlock.__init__z  !    tX&(,m%	4%rV   c                 V   |j                  | j                  | j                         |j                  }i |_        t        j                  | |       |j                  j                         D ]&  \  }}|j                  |g       j                  |       ( ||_        |j                          y)Call the ``start_feature`` callback on the builder object, visit
        all the statements in this feature, and then call ``end_feature``.N)
start_featurer   r   	features_r   r   items
setdefaultr   end_feature)r   r   featureskeyvalues        rQ   r   zFeatureBlock.build~  s     	dmmTYY7 $$D'"!++113 	7JCR(//6	7$rV   c                     |d| j                   j                         z  z   }| j                  r|dz  }|dz  }|t        j	                  | |      z  }||d| j                   j                         z  z   z  }|S )Nzfeature %s useExtension {
r  } %s;
)r   stripr  r   r   r   s      rQ   r   zFeatureBlock.asFea  ss    }tyy'888?"Cuu{{4{//v	DIIOO$5555
rV   FNr   r  rN   rV   rQ   r   r   w  s     <rV   r   c                   &    e Zd ZdZddZd ZddZy)r   zYA block inside another block, for example when found inside a
    ``cvParameters`` block.Nc                 L    t         j                  | |       || _        || _        y r   )r   r   r   
block_name)r   r   r"  r   s       rQ   r   zNestedBlock.__init__  s    tX&$rV   c                     t         j                  | |       | j                  dk(  r|j                  | j                         y y )NParamUILabelNameID)r   r   r"  add_to_cv_num_named_paramsr   r   s     rQ   r   zNestedBlock.build  s4    D'"??22..txx8 3rV   c                     dj                  || j                        }|t        j                  | |      z  }|dj                  |      z  }|S )Nz{}{} {{
r  z{}}};
)r   r"  r   r   r   s      rQ   r   zNestedBlock.asFea  sI      9u{{4{//y''
rV   r   r   r  rN   rV   rQ   r   r     s    %
9
rV   r   c                   &    e Zd ZdZddZd ZddZy)r   z*A named lookup, containing ``statements``.Nc                 N    t         j                  | |       ||c| _        | _        y r   r  r  s       rQ   r   zLookupBlock.__init__  r  rV   c                     |j                  | j                  | j                         t        j	                  | |       |j                          y r   )start_lookup_blockr   r   r   r   end_lookup_blockr   s     rQ   r   zLookupBlock.build  s4    ""4==$))<D'"  "rV   c                     dj                  | j                        }| j                  r|dz  }|dz  }|t        j	                  | |      z  }|dj                  || j                        z  }|S )Nz
lookup {} r  r  r  z	{}}} {};
)r   r   r  r   r   r   s      rQ   r   zLookupBlock.asFea  si    !!$)),?"Cuu{{4{//|""649955
rV   r  r   r  rN   rV   rQ   r   r     s    4<#rV   r   c                   ,     e Zd ZdZddZd fd	Z xZS )rG   zA ``table ... { }`` block.c                 >    t         j                  | |       || _        y r   )r   r   r   )r   r   r   s      rQ   r   zTableBlock.__init__  s    tX&	rV   c                     dj                  | j                  j                               }|t        t        |   |      z  }|dj                  | j                  j                               z  }|S )Nztable {} {{
r  z}} {};
)r   r   r  r   rG   r   )r   r   r   r   s      rQ   r   zTableBlock.asFea  s\    $$TYY__%67uZ,F,;;z  !233
rV   r   r   r   r   s   @rQ   rG   rG     s    $ rV   rG   c                   &    e Zd ZdZddZd ZddZy)r   z!Example: ``@UPPERCASE = [A-Z];``.Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   r   r   )r   r   r   r   s       rQ   r   zGlyphClassDefinition.__init__  s     4*	rV   c                 H    t        | j                  j                               S r   )r   r   r   r   s    rQ   r   zGlyphClassDefinition.glyphSet  s    T[[))+,,rV   c                 b    d| j                   z   dz   | j                  j                         z   dz   S )Nr   z = ;)r   r   r   r   s     rQ   r   zGlyphClassDefinition.asFea  s,    TYY&):):)<<sBBrV   r   r   r   rN   rV   rQ   r   r     s    +
-CrV   r   c                   (    e Zd ZdZ	 ddZd ZddZy)r   zExample: ``GlyphClassDef @UPPERCASE, [B], [C], [D];``. The parameters
    must be either :class:`GlyphClass` or :class:`GlyphClassName` objects, or
    ``None``.Nc                 j    t         j                  | |       ||c| _        | _        || _        || _        y r   )rB   r   
baseGlyphs
markGlyphsligatureGlyphscomponentGlyphs)r   r7  r8  r9  r:  r   s         rQ   r   zGlyphClassDefStatement.__init__  s4     	4*,6
(,.rV   c                    | j                   r| j                   j                         n	t               }| j                  r| j                  j                         n	t               }| j                  r| j                  j                         n	t               }| j
                  r| j
                  j                         n	t               }|j                  | j                  ||||       y)z3Calls the builder's ``add_glyphClassDef`` callback.N)r7  r   r   r9  r8  r:  add_glyphClassDefr   )r   r   r   ligaro   comps         rQ   r   zGlyphClassDefStatement.build  s    -1__t'')%'151D1Dt""++-%'-1__t'')%'262F2Ft##,,.EG!!$--tT4HrV   c                 b   dj                  | j                  r| j                  j                         nd| j                  r| j                  j                         nd| j                  r| j                  j                         nd| j
                  r| j
                  j                               S d      S )NzGlyphClassDef {}, {}, {}, {};r   )r   r7  r   r9  r8  r:  r   s     rQ   r   zGlyphClassDefStatement.asFea  s    .55'+DOO!!#B+/+>+>D%%'B'+DOO!!#B,0,@,@D  &&(	
 	
 GI	
 	
rV   r   r   r  rN   rV   rQ   r   r     s    
 QU/I
rV   r   c                   *    e Zd ZdZd Zd Zd ZddZy)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                 >    || _         g | _        t               | _        y r   )r   definitionsr   r   )r   r   s     rQ   r   zMarkClass.__init__  s    	!mrV   c                 @   t        |t              sJ | j                  j                  |       |j	                         D ]^  }|| j
                  v r?| j
                  |   j                  }|d}nd| }t        d|d||j                        || j
                  |<   ` y)z@Add a :class:`MarkClassDefinition` statement to this mark class.Nr   z at zGlyph z already defined)r   r   rB  r   r   r   r   r   )r   
definitionr   otherLocr   s        rQ   addDefinitionzMarkClass.addDefinition  s    *&9:::
+((* 
	,E#;;u-66#C 
+C%493?ATAT  ",DKK
	,rV   c                 H    t        | j                  j                               S r   )r   r   keysr   s    rQ   r   zMarkClass.glyphSet#  s    T[[%%'((rV   c                 J    dj                  d | j                  D              }|S )Nr   c              3   <   K   | ]  }|j                           y wr   r   )rO   ds     rQ   rR   z"MarkClass.asFea.<locals>.<genexpr>(  s     <a	<   )rS   rB  r   s      rQ   r   zMarkClass.asFea'  s!    ii<4+;+;<<
rV   Nr   )r   r   r   r   r   rF  r   r   rN   rV   rQ   r   r     s    $
, )rV   r   c                   &    e Zd ZdZddZd ZddZy)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                     t         j                  | |       t        |t              sJ t        |t              rt        |t
              sJ |||c| _        | _        | _        y r   )	rB   r   r   r   r   r'   r   rW   r   )r   r   rW   r   r   s        rQ   r   zMarkClassDefinition.__init__C  sQ    4*)Y///&&)j.LLL3<ff0T[rV   c                 6    | j                   j                         S r   )r   r   r   s    rQ   r   zMarkClassDefinition.glyphSetI  s    {{##%%rV   c                     dj                  | j                  j                         | j                  j                         | j                  j
                        S )NzmarkClass {} {} @{};)r   r   r   rW   r   r   r   s     rQ   r   zMarkClassDefinition.asFeaM  s@    %,,KK!2!2!4dnn6I6I
 	
rV   r   r   r   rN   rV   rQ   r   r   ,  s    ,M&
rV   r   c                   &    e Zd ZdZddZd ZddZy)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                 j    t         j                  | |       |||c| _        | _        | _        || _        y r   )rB   r   prefixr   suffixreplacement)r   rS  r   rT  rU  r   s         rQ   r   z AlternateSubstStatement.__init__Y  s0    4*06v,TZ&rV   c                    | j                   j                         }t        |      dk(  sJ |       t        |      d   }| j                  D cg c]  }|j                          }}| j
                  D cg c]  }|j                          }}| j                  j                         }|j                  | j                  ||||       yc c}w c c}w )z5Calls the builder's ``add_alternate_subst`` callback.r   r   N)	r   r   r   listrS  rT  rU  add_alternate_substr   )r   r   r   prS  r   rT  rU  s           rQ   r   zAlternateSubstStatement.build^  s    

##%5zQ%%UA(,41!**,44(,41!**,44&&//1##DMM65&+V 54s   C3Cc                    d}t        | j                        st        | j                        rt        | j                        r/|dj                  t	        t
        | j                              dz   z  }|t        | j                        dz   z  }t        | j                        rH|ddj                  t	        t
        | j                              z   z  }n|t        | j                        z  }|dz  }|t        | j                        z  }|dz  }|S )Nsub r   'z from r4  )r   rS  rT  rS   r   r   r   rU  r   s      rQ   r   zAlternateSubstStatement.asFeah  s    t{{s4;;/4;;sxxE4;; 783>>5$s**C4;;sSXXc%&=>>>5$$CxuT%%&&s

rV   r   r   r  rN   rV   rQ   r   r   S  s    N
'
WrV   r   c                   *    e Zd ZdZ	 	 	 	 	 ddZddZy)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                     t         j                  | |       || _        |||c| _        | _        | _        ||c| _        | _        y r   )r'   r   r   xycontourpointxDeviceTableyDeviceTable)r   r_  r`  r   ra  rb  rc  r   s           rQ   r   zAnchor.__init__  sD     	D(+	,-q,))/;\,4,rV   c                    | j                   dj                  | j                         S dj                  | j                  | j                        }| j                  r|dj                  | j                        z  }| j
                  s| j                  r:|dz  }|t        | j
                        z  }|dz  }|t        | j                        z  }|dz  }|S )Nz<anchor {}>z<anchor {} {} contourpoint {}r   >)r   r   r_  r`  ra  rb  rc  rU   r   s      rQ   r   zAnchor.asFea  s    99  ''		22$$TVVTVV4%,,T->->??C 1 13JC>$"3"344C3JC>$"3"344Cs

rV   )NNNNNr   r   rN   rV   rQ   r   r   x  s#     JrV   r   c                        e Zd ZdZddZddZy)r   zCA named anchor definition. (2.e.viii). ``name`` should be a string.Nc                 n    t         j                  | |       ||||f\  | _        | _        | _        | _        y r   )rB   r   r   r_  r`  ra  )r   r   r_  r`  ra  r   s         rQ   r   zAnchorDefinition.__init__  s2    4*7;Q<7O4	46464#4rV   c                     dj                  | j                  | j                        }| j                  r|dj                  | j                        z  }|dj                  | j                        z  }|S )NzanchorDef {} {}re  z {};)r   r_  r`  ra  r   r   s      rQ   r   zAnchorDefinition.asFea  s]    &&tvvtvv6%,,T->->??Cv}}TYY''
rV   r   r   r   rN   rV   rQ   r   r     s    MPrV   r   c                   &    e Zd ZdZddZd ZddZy)r   z&A ``GDEF`` table ``Attach`` statement.Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   r   contourPoints)r   r   rl  r   s       rQ   r   zAttachStatement.__init__  s!    4**rV   c                     | j                   j                         }|j                  | j                  || j                         y)z3Calls the builder's ``add_attach_points`` callback.N)r   r   add_attach_pointsr   rl  r   r   r   s      rQ   r   zAttachStatement.build  s0    %%'!!$--9K9KLrV   c                     dj                  | j                  j                         dj                  d | j                  D                    S )NzAttach {} {};r   c              3   2   K   | ]  }t        |        y wr   str)rO   cs     rQ   rR   z(AttachStatement.asFea.<locals>.<genexpr>  s     )MQ#a&)M   )r   r   r   rS   rl  r   s     rQ   r   zAttachStatement.asFea  s<    %%KK)M$:L:L)M!M
 	
rV   r   r   r  rN   rV   rQ   r   r     s    0+
M

rV   r   c                   &    e Zd ZdZddZd ZddZy)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                     t         j                  | |       |||c| _        | _        | _        t        |      | _        t        |      D ]  \  }}|s		 d |D          y # t        $ r |g| j                  |<   Y 1w xY w)Nc              3       K   | ]  }|  y wr   rN   rO   _s     rQ   rR   z4ChainContextPosStatement.__init__.<locals>.<genexpr>       '1Q'   	rB   r   rS  r   rT  rW  lookupsr_   	TypeErrorr   rS  r   rT  r~  r   irm   s           rQ   r   z!ChainContextPosStatement.__init__  {    4*06-T[$+G}"7+ 	/IAv/''	/ ! /'-hDLLO/   	AA:9A:c                 ^   | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}|j	                  | j
                  |||| j                         yc c}w c c}w c c}w )z7Calls the builder's ``add_chain_context_pos`` callback.N)rS  r   r   rT  add_chain_context_posr   r~  r   r   rY  rS  r   r   r   rT  s           rQ   r   zChainContextPosStatement.build  s    (,41!**,44(,41!**,44(,41!**,44%%MM6664<<	
 544   B B%B*c                 ,   d}t        | j                        s;t        | j                        s&t        | j                  D cg c]  }|d u c}      rt        | j                        r(|dj                  d | j                  D              dz   z  }t        | j                        D ]q  \  }}||j                         dz   z  }| j                  |   r&| j                  |   D ]  }|d|j                  z   z  } |t        | j                        dz
  k  sm|dz  }s t        | j                        r\|ddj                  t        t        | j                              z   z  }n,|dj                  t        t        | j                              z  }|dz  }|S c c}w )Npos r   c              3   <   K   | ]  }|j                           y wr   r   rO   r   s     rQ   rR   z1ChainContextPosStatement.asFea.<locals>.<genexpr>       ?a	?rL  r\   lookup r   r4  r   rS  rT  anyr~  rS   r_   r   r   r   r   r   r   r   r   r_  r  r   lus          rQ   r   zChainContextPosStatement.asFea  N   4;;4<<8aATM894;;sxx?4;;??#EE!$++. 1qwwy3&<<?"ll1o 4zBGG334s4;;'!++3JC 4;;sSXXc%&=>>>388Ctzz233Cs

! 9    Fr   r   r  rN   rV   rQ   r    r          	/
rV   r    c                   &    e Zd ZdZddZd ZddZy)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                     t         j                  | |       |||c| _        | _        | _        t        |      | _        t        |      D ]  \  }}|s		 d |D          y # t        $ r |g| j                  |<   Y 1w xY w)Nc              3       K   | ]  }|  y wr   rN   ry  s     rQ   rR   z6ChainContextSubstStatement.__init__.<locals>.<genexpr>  r{  r|  r}  r  s           rQ   r   z#ChainContextSubstStatement.__init__  r  r  c                 ^   | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}|j	                  | j
                  |||| j                         yc c}w c c}w c c}w )z9Calls the builder's ``add_chain_context_subst`` callback.N)rS  r   r   rT  add_chain_context_substr   r~  r  s           rQ   r   z ChainContextSubstStatement.build  s    (,41!**,44(,41!**,44(,41!**,44''MM6664<<	
 544r  c                 ,   d}t        | j                        s;t        | j                        s&t        | j                  D cg c]  }|d u c}      rt        | j                        r(|dj                  d | j                  D              dz   z  }t        | j                        D ]q  \  }}||j                         dz   z  }| j                  |   r&| j                  |   D ]  }|d|j                  z   z  } |t        | j                        dz
  k  sm|dz  }s t        | j                        r\|ddj                  t        t        | j                              z   z  }n,|dj                  t        t        | j                              z  }|dz  }|S c c}w )Nr[  r   c              3   <   K   | ]  }|j                           y wr   r   r  s     rQ   rR   z3ChainContextSubstStatement.asFea.<locals>.<genexpr>#  r  rL  r\  r  r   r4  r  r  s          rQ   r   z ChainContextSubstStatement.asFea  r  r  r   r   r  rN   rV   rQ   r!   r!     r  rV   r!   c                   &    e Zd ZdZddZd ZddZy)r$   znA cursive positioning statement. Entry and exit anchors can either
    be :class:`Anchor` objects or ``None``.Nc                 \    t         j                  | |       || _        ||c| _        | _        y r   )rB   r   r   entryAnchor
exitAnchor)r   r   r  r  r   s        rQ   r   zCursivePosStatement.__init__7  s*    4*$,7)$/rV   c                     |j                  | j                  | j                  j                         | j                  | j
                         y)z8Calls the builder object's ``add_cursive_pos`` callback.N)add_cursive_posr   r   r   r  r  r   s     rQ   r   zCursivePosStatement.build<  s4    MM4??335t7G7G	
rV   c                     | j                   r| j                   j                         nd}| j                  r| j                  j                         nd}dj                  | j                  j                         ||      S )N<anchor NULL>zpos cursive {} {} {};)r  r   r  r   r   )r   r   entryexits       rQ   r   zCursivePosStatement.asFeaB  s\    ,0,<,<  &&(/*.//t$$&&--doo.C.C.EudSSrV   r   r   r  rN   rV   rQ   r$   r$   3  s    /D

TrV   r$   c                   &    e Zd ZdZddZd ZddZy)r)   zExample: ``feature salt;``Nc                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   r   featureName)r   r  r   s      rQ   r   z"FeatureReferenceStatement.__init__K  s#    4*+3['t'rV   c                 P    |j                  | j                  | j                         y)z>Calls the builder object's ``add_feature_reference`` callback.N)add_feature_referencer   r  r   s     rQ   r   zFeatureReferenceStatement.buildO  s    %%dmmT5E5EFrV   c                 8    dj                  | j                        S )Nzfeature {};)r   r  r   s     rQ   r   zFeatureReferenceStatement.asFeaS  s    ##D$4$455rV   r   r   r  rN   rV   rQ   r)   r)   H  s    $BG6rV   r)   c                   &    e Zd ZdZddZd ZddZy)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                 >    t         j                  | |       || _        y r   rB   r   chainContextsr   r  r   s      rQ   r   zIgnorePosStatement.__init__^      4**rV   c                 8   | j                   D ]|  \  }}}|D cg c]  }|j                          }}|D cg c]  }|j                          }}|D cg c]  }|j                          }}|j                  | j                  |||g        ~ yc c}w c c}w c c}w )z[Calls the builder object's ``add_chain_context_pos`` callback on each
        rule context.N)r  r   r  r   r   r   rS  r   rT  rY  r   r   s           rQ   r   zIgnorePosStatement.buildb  s     '+&8&8 	U"FFF,23qajjl3F3,23qajjl3F3,23qajjl3F3))$--QST		U333   BBBc           	         g }| j                   D ]  \  }}}d}t        |      st        |      r|t        |      r%|dj                  t        t        |            dz   z  }|dj                  d |D              z  }t        |      rH|ddj                  t        t        |            z   z  }n"|dj                  t        t        |            z  }|j                  |        ddj                  |      z   dz   S )Nr   r   c              3   B   K   | ]  }|j                         d z     ywr\  Nr   r  s     rQ   rR   z+IgnorePosStatement.asFea.<locals>.<genexpr>r  s     @A	C@   zignore pos rL   r4  r  r   rS   r   r   r   r   r   contextsrS  r   rT  r   s          rQ   r   zIgnorePosStatement.asFeak  s    &*&8&8 
	!"FFFC6{c&kv;388Cv$67#==Csxx@@@@v;3#eV*<!===CsxxE6 233OOC 
	! tyy22S88rV   r   r   r  rN   rV   rQ   r,   r,   W  s    %+U9rV   r,   c                   &    e Zd ZdZddZd ZddZy)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                 >    t         j                  | |       || _        y r   r  r  s      rQ   r   zIgnoreSubstStatement.__init__  r  rV   c                 8   | j                   D ]|  \  }}}|D cg c]  }|j                          }}|D cg c]  }|j                          }}|D cg c]  }|j                          }}|j                  | j                  |||g        ~ yc c}w c c}w c c}w )z]Calls the builder object's ``add_chain_context_subst`` callback on
        each rule context.N)r  r   r  r   r  s           rQ   r   zIgnoreSubstStatement.build  s     '+&8&8 	W"FFF,23qajjl3F3,23qajjl3F3,23qajjl3F3++DMM666SUV		W333r  c           	      z   g }| j                   D ]  \  }}}d}t        |      r%|dj                  t        t        |            dz   z  }|dj                  d |D              z  }t        |      r%|ddj                  t        t        |            z   z  }|j                  |        ddj                  |      z   dz   S )Nr   r   c              3   B   K   | ]  }|j                         d z     ywr  r   r  s     rQ   rR   z-IgnoreSubstStatement.asFea.<locals>.<genexpr>  s     <AGGIO<r  zignore sub rL   r4  r  r  s          rQ   r   zIgnoreSubstStatement.asFea  s    &*&8&8 	!"FFFC6{sxxE6 23c99388<V<<<C6{sSXXc%&8999OOC 	! tyy22S88rV   r   r   r  rN   rV   rQ   r-   r-   {  s    %+W
9rV   r-   c                   2     e Zd ZdZd fd	Zd ZddZ xZS )r.   zAn ``include()`` statement.c                 :    t         t        |   |       || _        y r   )r   r.   r   filename)r   r  r   r   s      rQ   r   zIncludeStatement.__init__  s    .x8 rV   c                 .    t        d| j                        )NzqBuilding an include statement is not implemented yet. Instead, use Parser(..., followIncludes=True) for building.)r   r   r   s    rQ   r   zIncludeStatement.build  s    JMM
 	
rV   c                 &    |d| j                   z  z   S )Nzinclude(%s);)r  r   s     rQ   r   zIncludeStatement.asFea  s    666rV   r   r   )r   r   r   r   r   r   r   r   r   s   @rQ   r.   r.     s    %!
7rV   r.   c                   &    e Zd ZdZddZd ZddZy)r/   z*A ``language`` statement within a feature.Nc                 z    t         j                  | |       t        |      dk(  sJ || _        || _        || _        y )N   )rB   r   r   rk   include_defaultrw   )r   rk   r  rw   r   s        rQ   r   zLanguageStatement.__init__  s:    4*8}!!! . rV   c                 ~    |j                  | j                  | j                  | j                  | j                         y)z4Call the builder object's ``set_language`` callback.)r   rk   r  rw   N)set_languager   rk   r  rw   r   s     rQ   r   zLanguageStatement.build  s3    ]]]] 00]]	 	 	
rV   c                     dj                  | j                  j                               }| j                  s|dz  }| j                  r|dz  }|dz  }|S )Nzlanguage {}z exclude_dfltz	 requiredr4  )r   rk   r  r  rw   r   s      rQ   r   zLanguageStatement.asFea  sQ    ""4==#6#6#89##?"C==;Cs

rV   )TFNr   r  rN   rV   rQ   r/   r/     s    4!
rV   r/   c                   &    e Zd ZdZddZd ZddZy)r0   z)A top-level ``languagesystem`` statement.Nc                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   r{   rk   )r   r{   rk   r   s       rQ   r   z LanguageSystemStatement.__init__  s"    4*&,h"T]rV   c                 f    |j                  | j                  | j                  | j                         y)z<Calls the builder object's ``add_language_system`` callback.N)add_language_systemr   r{   rk   r   s     rQ   r   zLanguageSystemStatement.build  s     ##DMM4;;NrV   c                 j    dj                  | j                  | j                  j                               S )Nzlanguagesystem {} {};)r   r{   rk   r  r   s     rQ   r   zLanguageSystemStatement.asFea  s&    &--dkk4==;N;N;PQQrV   r   r   r  rN   rV   rQ   r0   r0     s    38ORrV   r0   c                   &    e Zd ZdZddZd ZddZy)r*   zA ``head`` table ``FontRevision`` statement. ``revision`` should be a
    number, and will be formatted to three significant decimal places.Nc                 >    t         j                  | |       || _        y r   )rB   r   revision)r   r  r   s      rQ   r   zFontRevisionStatement.__init__  s    4* rV   c                 P    |j                  | j                  | j                         y r   )set_font_revisionr   r  r   s     rQ   r   zFontRevisionStatement.build  s    !!$--?rV   c                 8    dj                  | j                        S )NzFontRevision {:.3f};)r   r  r   s     rQ   r   zFontRevisionStatement.asFea  s    %,,T]];;rV   r   r   r  rN   rV   rQ   r*   r*     s    J!@<rV   r*   c                   &    e Zd ZdZddZd ZddZy)r1   zA ``GDEF`` table ``LigatureCaretByIndex`` statement. ``glyphs`` should be
    a `glyph-containing object`_, and ``carets`` should be a list of integers.Nc                 N    t         j                  | |       ||c| _        | _        y r   rB   r   r   caretsr   r   r  r   s       rQ   r   z&LigatureCaretByIndexStatement.__init__  "    4*$*F T[rV   c                     | j                   j                         }|j                  | j                  |t	        | j
                               y)zBCalls the builder object's ``add_ligatureCaretByIndex_`` callback.N)r   r   add_ligatureCaretByIndex_r   setr  ro  s      rQ   r   z#LigatureCaretByIndexStatement.build  s3    %%'))$--T[[AQRrV   c                     dj                  | j                  j                         dj                  d | j                  D                    S )NzLigatureCaretByIndex {} {};r   c              3   2   K   | ]  }t        |        y wr   rr  rO   r_  s     rQ   rR   z6LigatureCaretByIndexStatement.asFea.<locals>.<genexpr>       )FQ#a&)Fru  r   r   r   rS   r  r   s     rQ   r   z#LigatureCaretByIndexStatement.asFea  s:    ,33KK)F$++)F!F
 	
rV   r   r   r  rN   rV   rQ   r1   r1     s    R4S

rV   r1   c                   &    e Zd ZdZddZd ZddZy)r2   zA ``GDEF`` table ``LigatureCaretByPos`` statement. ``glyphs`` should be
    a `glyph-containing object`_, and ``carets`` should be a list of integers.Nc                 N    t         j                  | |       ||c| _        | _        y r   r  r  s       rQ   r   z$LigatureCaretByPosStatement.__init__  r  rV   c                     | j                   j                         }|j                  | j                  |t	        | j
                               y)z@Calls the builder object's ``add_ligatureCaretByPos_`` callback.N)r   r   add_ligatureCaretByPos_r   r  r  ro  s      rQ   r   z!LigatureCaretByPosStatement.build  s3    %%'''vs4;;?OPrV   c                     dj                  | j                  j                         dj                  d | j                  D                    S )NzLigatureCaretByPos {} {};r   c              3   2   K   | ]  }t        |        y wr   rr  r  s     rQ   rR   z4LigatureCaretByPosStatement.asFea.<locals>.<genexpr>  r  ru  r  r   s     rQ   r   z!LigatureCaretByPosStatement.asFea
  s:    *11KK)F$++)F!F
 	
rV   r   r   r  rN   rV   rQ   r2   r2     s    R4Q

rV   r2   c                   &    e Zd ZdZddZd ZddZy)r3   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                 z    t         j                  | |       |||c| _        | _        | _        ||c| _        | _        y r   )rB   r   rS  r   rT  rU  
forceChain)r   rS  r   rT  rU  r  r   s          rQ   r   zLigatureSubstStatement.__init__  s9    4*17-T[$+,7)$/rV   c                 t   | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}|j	                  | j
                  |||| j                  | j                         y c c}w c c}w c c}w r   )rS  r   r   rT  add_ligature_substr   rU  r  r  s           rQ   r   zLigatureSubstStatement.build  s    (,41!**,44(,41!**,44(,41!**,44""MM66643C3CT__	
 544s   B+B0B5c                 D   d}t        | j                        s!t        | j                        s| j                  rt        | j                        r(|dj	                  d | j                  D              dz   z  }|dj	                  d | j
                  D              z  }t        | j                        rN|ddj	                  d | j                  D              z   z  }n%|dj	                  d | j
                  D              z  }|dz  }|t        | j                        z  }|dz  }|S )	Nr[  r   c              3   <   K   | ]  }|j                           y wr   r   r  s     rQ   rR   z/LigatureSubstStatement.asFea.<locals>.<genexpr>+  r  rL  c              3   B   K   | ]  }|j                         d z     ywr  r   r  s     rQ   rR   z/LigatureSubstStatement.asFea.<locals>.<genexpr>,  s     AAGGIOAr  c              3   <   K   | ]  }|j                           y wr   r   r  s     rQ   rR   z/LigatureSubstStatement.asFea.<locals>.<genexpr>.  s     %EAaggi%ErL  c              3   <   K   | ]  }|j                           y wr   r   r  s     rQ   rR   z/LigatureSubstStatement.asFea.<locals>.<genexpr>0  s     ;!AGGI;rL   by r4  )r   rS  rT  r  rS   r   r   rU  r   s      rQ   r   zLigatureSubstStatement.asFea'  s    t{{s4;;/4??4;;sxx?4;;??#EE388AT[[AAAC4;;sSXX%E%EEEE388;t{{;;;CvuT%%&&s

rV   r   r   r  rN   rV   rQ   r3   r3     s    BD

rV   r3   c                   (    e Zd ZdZ	 ddZd ZddZy)r4   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.Nc                 Z    t         j                  | |       || _        || _        || _        y r   )rB   r   r  markAttachmentmarkFilteringSet)r   r  r  r  r   s        rQ   r   zLookupFlagStatement.__init__=  s+     	4*
, 0rV   c                     d}| j                   | j                   j                         }d}| j                  | j                  j                         }|j                  | j                  | j
                  ||       y)z8Calls the builder object's ``set_lookup_flag`` callback.N)r  r   r  set_lookup_flagr   r  )r   r   
markAttach
markFilters       rQ   r   zLookupFlagStatement.buildE  sh    
*,,557J
  ,..779Jtzz:zRrV   c                    g }g d}d}t        t        |            D ]-  }| j                  |z  dk7  r|j                  ||          |dz  }/ | j                  8|j                  dj                  | j                  j                                      | j                  8|j                  dj                  | j                  j                                      |sdg}dj                  dj                  |            S )	N)RightToLeftIgnoreBaseGlyphsIgnoreLigaturesIgnoreMarksr   r   zMarkAttachmentType {}zUseMarkFilteringSet {}0zlookupflag {};r   )	ranger   r  r   r  r   r   r  rS   )r   r   r   flagsr   r  s         rQ   r   zLookupFlagStatement.asFeaO  s    Us5z" 	AzzD A%

58$19D	 *JJ.55d6I6I6O6O6QRS  ,JJ/66t7L7L7R7R7TUV%C&&sxx}55rV   )r   NNNr   r  rN   rV   rQ   r4   r4   7  s    ! MQ1S6rV   r4   c                   &    e Zd ZdZddZd ZddZy)r5   zRepresents a ``lookup ...;`` statement to include a lookup in a feature.

    The ``lookup`` should be a :class:`LookupBlock` object.Nc                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   r   rm   )r   rm   r   s      rQ   r   z!LookupReferenceStatement.__init__e  s"    4*&."t{rV   c                 N    |j                  | j                  j                         y)z8Calls the builder object's ``add_lookup_call`` callback.N)add_lookup_callrm   r   r   s     rQ   r   zLookupReferenceStatement.buildi  s     0 01rV   c                 L    dj                  | j                  j                        S )Nz
lookup {};)r   rm   r   r   s     rQ   r   zLookupReferenceStatement.asFeam  s    ""4;;#3#344rV   r   r   r  rN   rV   rQ   r5   r5   `  s    ?825rV   r5   c                   &    e Zd ZdZddZd ZddZy)r6   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                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   r   marks)r   r   r  r   s       rQ   r   zMarkBasePosStatement.__init__v  s"    4* $e	4:rV   c                     |j                  | j                  | j                  j                         | j                         y)z:Calls the builder object's ``add_mark_base_pos`` callback.N)add_mark_base_posr   r   r   r  r   s     rQ   r   zMarkBasePosStatement.buildz  s)    !!$--1C1C1EtzzRrV   c                     dj                  | j                  j                               }| j                  D ]?  \  }}|d|z   t        z   dj                  |j                         |j
                        z   z  }A |dz  }|S )Nzpos base {}r   {} mark @{}r4  )r   r   r   r  r  r   r   r   r   ams        rQ   r   zMarkBasePosStatement.asFea~  ss    ""499??#45JJ 	SDAq4&=5(=+?+?	166+RRRC	Ss

rV   r   r   r  rN   rV   rQ   r6   r6   q  s    5,SrV   r6   c                   &    e Zd ZdZddZd ZddZy)r7   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                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   	ligaturesr  )r   r  r  r   s       rQ   r   zMarkLigPosStatement.__init__  "    4*%."
rV   c                     |j                  | j                  | j                  j                         | j                         y)z9Calls the builder object's ``add_mark_lig_pos`` callback.N)add_mark_lig_posr   r  r   r  r   s     rQ   r   zMarkLigPosStatement.build  s)      0G0G0I4::VrV   c                    dj                  | j                  j                               }g }| j                  D ]|  }d}|t	        |      sd|z   t
        dz  z   dz   }nG|D ]B  \  }}|d|z   t
        dz  z   dj                  |j                         |j                        z   z  }D |j                  |       ~ |d|z   t
        z   dz   j                  |      z  }|dz  }|S )	Nzpos ligature {}r   r   r   r  r  ligComponentr4  )	r   r  r   r  r   r  r   r   rS   )r   r   r   ligsltempr  r  s           rQ   r   zMarkLigPosStatement.asFea  s    &&t~~';';'=> 	ADyAf}uqy0?B DAq !!)$ (..qwwy!&&ABD KK	 	v%6<<TBBs

rV   r   r   r  rN   rV   rQ   r7   r7     s    46WrV   r7   c                   &    e Zd ZdZddZd ZddZy)r8   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                 N    t         j                  | |       ||c| _        | _        y r   )rB   r   	baseMarksr  )r   r#  r  r   s       rQ   r   zMarkMarkPosStatement.__init__  r  rV   c                     |j                  | j                  | j                  j                         | j                         y)z:Calls the builder object's ``add_mark_mark_pos`` callback.N)add_mark_mark_posr   r#  r   r  r   s     rQ   r   zMarkMarkPosStatement.build  s)    !!$--1H1H1JDJJWrV   c                     dj                  | j                  j                               }| j                  D ]?  \  }}|d|z   t        z   dj                  |j                         |j
                        z   z  }A |dz  }|S )Nzpos mark {}r   r  r4  )r   r#  r   r  r  r   r  s        rQ   r   zMarkMarkPosStatement.asFea  su    ""4>>#7#7#9:JJ 	SDAq4&=5(=+?+?	166+RRRC	Ss

rV   r   r   r  rN   rV   rQ   r8   r8     s    56XrV   r8   c                   (    e Zd ZdZ	 ddZd ZddZy)r9   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.
    Nc                 x    t         j                  | |       |||c| _        | _        | _        || _        || _        y r   )rB   r   rS  r   rT  rU  r  )r   rS  r   rT  rU  r  r   s          rQ   r   zMultipleSubstStatement.__init__  s9     	4*/5uf,TZ&$rV   c           	         | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}t        | j                  d      r| j                  j                         }n| j                  g}t        |      }g }| j                  D ]T  }	t        |	d      r|	j                         }
n|	g}
t        |
      dk(  rt        |
      |k7  r|
|z  }
|j                  |
       V t        t        |       }t               }t        |      D ]P  \  }}||vs|j                  |       |j                  | j                  ||||xr ||   xs d| j                         R yc c}w c c}w )z;Calls the builder object's ``add_multiple_subst`` callback.r   r   rN   N)rS  r   rT  r   r   r   rU  r   rW  zipr  r_   addadd_multiple_substr   r  )r   r   rY  rS  r   rT  	originalscountreplacesrreplaceseen_originalsr  r   s                 rQ   r   zMultipleSubstStatement.build  sU   (,41!**,44(,41!**,444::z*

++-III!! 	%Aq*%**,#7|q S\U%:!E/OOG$	% X'$Y/ 
	KAx~-""8,**MM,!2OO
	' 54s
   E7E<c                 x   d}t        | j                        s!t        | j                        s| j                  rt        | j                        r/|dj	                  t        t        | j                              dz   z  }|t        | j                        dz   z  }t        | j                        rH|ddj	                  t        t        | j                              z   z  }n|t        | j                        z  }| j                  xs t               g}|dz  }|dj	                  t        t        |            z  }|dz  }|S )Nr[  r   r\  r  r4  )
r   rS  rT  r  rS   r   r   r   rU  r   )r   r   r   rU  s       rQ   r   zMultipleSubstStatement.asFea  s    t{{s4;;/4??4;;sxxE4;; 783>>5$s**C4;;sSXXc%&=>>>5$$C&&79;-vsxxE;/00s

rV   r  r   r  rN   rV   rQ   r9   r9     s    	 NR%BrV   r9   c                   *    e Zd ZdZ	 	 ddZd ZddZy)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>`_.
    Nc                 z    t         j                  | |       || _        ||c| _        | _        ||c| _        | _        y r   )rB   r   
enumeratedglyphs1valuerecord1glyphs2valuerecord2)r   r7  r8  r9  r:  r6  r   s          rQ   r   zPairPosStatement.__init__#  s=     	4*$*1<'d'*1<'d'rV   c                 F   | j                   r| j                  j                         | j                  j                         g}d}t	        j
                  | D ]:  \  }}d}|j                  | j                  || j                  || j                         < |st        d| j                        yt        | j                  t              xr t        | j                  t              }|r\|j                  | j                  | j                  j                  | j                  | j                  j                  | j                         y|j                  | j                  | j                  j                         | j                  | j                  j                         | j                         y)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)r6  r7  r   r9  	itertoolsproductadd_specific_pair_posr   r8  r:  r   r   r   r   add_class_pair_pos)r   r   r   	seen_pairglyph1glyph2is_specifics          rQ   r   zPairPosStatement.build1  sT    ??&&($,,*?*?*ABAI"+"3"3Q"7  	--MM64+<+<fdFWFW
 %;T]]   y9 
jLL)?
 ))""!!""!! &&%%'!!%%'!!rV   c                    | j                   rdnd}| j                  ry|dj                  | j                  j	                         | j
                  j	                         | j                  j	                         | j                  j	                               z  }|S |dj                  | j                  j	                         | j                  j	                         | j
                  j	                               z  }|S )Nzenum r   zpos {} {} {} {};zpos {} {} {};)r6  r:  r   r7  r   r8  r9  r   s      rQ   r   zPairPosStatement.asFea\  s    gb%,,""$!!'')""$!!'')	 C 
 ?))""$dll&8&8&:D<M<M<S<S<U C 
rV   r  r   r  rN   rV   rQ   r<   r<     s      @)VrV   r<   c                   &    e Zd ZdZddZd ZddZy)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                 j    t         j                  | |       ||c| _        | _        || _        || _        y r   )rB   r   
old_prefix
old_suffixr   replacements)r   rG  rH  r   rI  r   s         rQ   r   z)ReverseChainSingleSubstStatement.__init__u  s1    4*+5z((rV   c                    | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  d   j                         }| j                  d   j                         }t        |      dk(  r|t        |      z  }|j                  | j                  ||t        t        ||                   y c c}w c c}w )Nr   r   )
rG  r   rH  r   rI  r   add_reverse_chain_single_substr   dictr*  r   r   rY  rS  r   rT  r-  r/  s           rQ   r   z&ReverseChainSingleSubstStatement.build{  s    (,81!**,88(,81!**,88KKN++-	$$Q'002x=A#i.0H..MM664Ix0H+I	
 98s
   CCc                 ^   d}t        | j                        st        | j                        rt        | j                        r(|dj                  d | j                  D              dz   z  }|dj                  d | j                  D              z  }t        | j                        rU|ddj                  d | j                  D              z   z  }n,|dj                  t        t        | j                              z  }|dj                  dj                  d | j                  D                    z  }|S )Nzrsub r   c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z9ReverseChainSingleSubstStatement.asFea.<locals>.<genexpr>  s     BQaBru  c              3   8   K   | ]  }t        |      d z     ywr  r   r  s     rQ   rR   z9ReverseChainSingleSubstStatement.asFea.<locals>.<genexpr>       @qE!HsN@   c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z9ReverseChainSingleSubstStatement.asFea.<locals>.<genexpr>  s     %H1eAh%Hru   by {};c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z9ReverseChainSingleSubstStatement.asFea.<locals>.<genexpr>       (Maq(Mru  )	r   rG  rH  rS   r   r   r   r   rI  r   s      rQ   r   z&ReverseChainSingleSubstStatement.asFea  s    t3t#74??#sxxB$//BBSHH388@DKK@@@C4??#sSXX%H%HHHH388Ct{{344Cy(M4;L;L(M MNN
rV   r   r   r  rN   rV   rQ   r=   r=   l  s    )	
rV   r=   c                   &    e Zd ZdZddZd ZddZy)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                 x    t         j                  | |       ||c| _        | _        || _        || _        || _        y r   )rB   r   rS  rT  r  r   rI  )r   r   r1  rS  rT  r  r   s          rQ   r   zSingleSubstStatement.__init__  s8    4*#)6 T[$#rV   c                    | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  d   j                         }| j                  d   j                         }t        |      dk(  r|t        |      z  }|j                  | j                  ||t        t        ||            | j                         yc c}w c c}w )z9Calls the builder object's ``add_single_subst`` callback.r   r   N)rS  r   rT  r   rI  r   add_single_substr   r   r*  r  rM  s           rQ   r   zSingleSubstStatement.build  s    (,41!**,44(,41!**,44KKN++-	$$Q'002x=A#i.0H  MMIx01OO	
 54s
   C"C'c                 h   d}t        | j                        s!t        | j                        s| j                  rt        | j                        r(|dj	                  d | j                  D              dz   z  }|dj	                  d | j
                  D              z  }t        | j                        rN|ddj	                  d | j                  D              z   z  }n%|dj	                  d | j
                  D              z  }|dj                  dj	                  d | j                  D                    z  }|S )	Nr[  r   c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z-SingleSubstStatement.asFea.<locals>.<genexpr>  s     >Qa>ru  c              3   8   K   | ]  }t        |      d z     ywr  r   r  s     rQ   rR   z-SingleSubstStatement.asFea.<locals>.<genexpr>  rQ  rR  c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z-SingleSubstStatement.asFea.<locals>.<genexpr>  s     %D1eAh%Dru  c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z-SingleSubstStatement.asFea.<locals>.<genexpr>  s     :E!H:ru  rT  c              3   2   K   | ]  }t        |        y wr   r   r  s     rQ   rR   z-SingleSubstStatement.asFea.<locals>.<genexpr>  rV  ru  )r   rS  rT  r  rS   r   r   rI  r   s      rQ   r   zSingleSubstStatement.asFea  s    t{{s4;;/4??4;;sxx>$++>>DD388@DKK@@@C4;;sSXX%D%DDDD388:dkk:::Cy(M4;L;L(M MNN
rV   r   r   r  rN   rV   rQ   r@   r@     s    $
 rV   r@   c                   &    e Zd ZdZddZd ZddZy)r>   zA ``script`` statement.Nc                 >    t         j                  | |       || _        y r   )rB   r   r{   )r   r{   r   s      rQ   r   zScriptStatement.__init__  s    4*rV   c                 P    |j                  | j                  | j                         y)z,Calls the builder's ``set_script`` callback.N)
set_scriptr   r{   r   s     rQ   r   zScriptStatement.build  s    4==$++6rV   c                 T    dj                  | j                  j                               S )Nz
script {};)r   r{   r  r   s     rQ   r   zScriptStatement.asFea  s     ""4;;#4#4#677rV   r   r   r  rN   rV   rQ   r>   r>     s    !78rV   r>   c                   &    e Zd ZdZddZd ZddZy)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                 j    t         j                  | |       |||c| _        | _        | _        || _        y r   )rB   r   ru   rS  rT  r  )r   ru   rS  rT  r  r   s         rQ   r   zSinglePosStatement.__init__  s/    4*-0&&*$+t{$rV   c                 n   | j                   D cg c]  }|j                          }}| j                  D cg c]  }|j                          }}| j                  D cg c]  \  }}|j                         |f }}}|j	                  | j
                  |||| j                         yc c}w c c}w c c}}w )z7Calls the builder object's ``add_single_pos`` callback.N)rS  r   rT  ru   add_single_posr   r  )	r   r   rY  rS  r   rT  r   r  ru   s	            rQ   r   zSinglePosStatement.build  s    (,41!**,44(,41!**,4459XX>E

e$>>t}}ffc4??S 54>s   B'B,B1c           
         d}t        | j                        s!t        | j                        s| j                  rt        | j                        r/|dj	                  t        t        | j                              dz   z  }|dj	                  | j                  D cg c]1  }t        |d         dz   |d   rd|d   j                         z   ndz   3 c}      z  }t        | j                        r|ddj	                  t        t        | j                              z   z  }nV|dj	                  | j                  D cg c].  }t        |d         dz   |d   r|d   j                         ndz   0 c}      z  }|dz  }|S c c}w c c}w )Nr  r   r   r\  r   r   r4  )r   rS  rT  r  rS   r   r   ru   )r   r   r   r_  s       rQ   r   zSinglePosStatement.asFea  sD   t{{s4;;/4??4;;sxxE4;; 783>>388 "XX !A$K#%1#!

*<2N C 4;;sSXXc%&=>>>388MQXXVqts"adadjjlCV C 	s

 Ws   6E8
53E=
r   r   r  rN   rV   rQ   r?   r?     s    $%
TrV   r?   c                   &    e Zd ZdZddZd ZddZy)rF   zRepresents a subtable break.Nc                 0    t         j                  | |       y r   )rB   r   r   s     rQ   r   zSubtableStatement.__init__  s    4*rV   c                 :    |j                  | j                         y)z<Calls the builder objects's ``add_subtable_break`` callback.N)add_subtable_breakr   r   s     rQ   r   zSubtableStatement.build  s    ""4==1rV   c                      y)Nz	subtable;rN   r   s     rQ   r   zSubtableStatement.asFea  s    rV   r   r   r  rN   rV   rQ   rF   rF     s    &+2rV   rF   c                   P    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 d	dZd Zd Zd Zd
dZd Z	e	Z
y)rH   zRepresents a value record.Nc                     t         j                  | |
       ||c| _        | _        ||c| _        | _        ||c| _        | _        ||c| _        | _	        |	| _
        y r   )r'   r   
xPlacement
yPlacementxAdvanceyAdvance
xPlaDevice
yPlaDevice
xAdvDevice
yAdvDevicevertical)r   rr  rs  rt  ru  rv  rw  rx  ry  rz  r   s              rQ   r   zValueRecord.__init__
  s[     	D(+,6
((0($t},6
(,6
( rV   c                 B   | j                   |j                   k(  xr | j                  |j                  k(  xrj | j                  |j                  k(  xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j
                  |j
                  k(  S r   )rr  rs  rt  ru  rv  rx  r   others     rQ   __eq__zValueRecord.__eq__  s    OOu/// 45#3#334/4 /4 5#3#33	4
 5#3#33	
rV   c                 &    | j                  |       S r   )r~  r|  s     rQ   __ne__zValueRecord.__ne__(  s    ;;u%%%rV   c                 `   t        | j                        t        | j                        z  t        | j                        z  t        | j                        z  t        | j
                        z  t        | j                        z  t        | j                        z  t        | j                        z  S r   )	hashrr  rs  rt  ru  rv  rw  rx  ry  r   s    rQ   __hash__zValueRecord.__hash__+  s    !4??#$4==!" 4==!" 4??#	$
 4??#$ 4??#$ 4??#$		
rV   c                     | sy| j                   | j                  }}| j                  | j                  }}| j                  | j
                  }}| j                  | j                  }	}| j                  }
| |||
rt        |      S ||
st        |      S |xs d}|xs d}|xs d}|xs d}||||	d|d|d|d|d	S d|d|d|d|dt        |      dt        |      dt        |      dt        |	      dS )Nz<NULL>r   <r   rf  )rr  rs  rt  ru  rv  rw  rx  ry  rz  rs  rU   )r   r   r_  r`  rt  ru  rv  rw  rx  ry  rz  s              rQ   r   zValueRecord.asFea7  s   1!]]DMM(!%$//J
!%$//J
== 9H8}$!(8}$ FF=q=q """&'Hh?? :&:&:&:&	
 		
rV   c                 ,     t         fddD              S )Nc              3   :   K   | ]  }t        |      d u  y wr   )getattr)rO   vr   s     rQ   rR   z'ValueRecord.__bool__.<locals>.<genexpr>d  s%      
 D!D(
s   )rr  rs  rt  ru  rv  rw  rx  ry  )r  r   s   `rQ   __bool__zValueRecord.__bool__c  s     
	
 
 	
rV   )
NNNNNNNNFNr   )r   r   r   r   r   r~  r  r  r   r  __nonzero__rN   rV   rQ   rH   rH     sK    $ !(
&

*
X
 KrV   rH   c                        e Zd ZdZddZddZy)rI   z+Represents a named value record definition.Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   r   r  )r   r   r  r   s       rQ   r   zValueRecordDefinition.__init__x  s     4*	
rV   c                 j    dj                  | j                  j                         | j                        S )NzvalueRecordDef {} {};)r   r  r   r   r   s     rQ   r   zValueRecordDefinition.asFea}  s&    &--djj.>.>.@$))LLrV   r   r   r   rN   rV   rQ   rI   rI   u  s    5
MrV   rI   c                 h    | dk(  r|dk(  r|dk(  ry| dk(  r|dk(  r|dk(  rydj                  | ||      S )N   r   i	  r   r   1{} {} {}r   )pideidlids      rQ   simplify_name_attributesr    sC    
axC1H	cQh3!8  c3//rV   c                   &    e Zd ZdZddZd ZddZy)r:   zRepresents a name record. (`Section 9.e. <https://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#9.e>`_)Nc                 v    t         j                  | |       || _        || _        || _        || _        || _        y r   )rB   r   nameID
platformID	platEncIDlangIDstring)r   r  r  r  r  r  r   s          rQ   r   zNameRecord.__init__  s5    4*$"rV   c                     |j                  | j                  | j                  | j                  | j                  | j
                  | j                         y)z8Calls the builder object's ``add_name_record`` callback.N)add_name_recordr   r  r  r  r  r  r   s     rQ   r   zNameRecord.build  s:    MMKKOONNKKKK	
rV   c                    d }t        | j                  | j                  | j                        }|t	        d| j
                        t        | j                  |      }|dk(  r\dj                  t        dt        |      d      D cg c],  } |t        ||         dz  t        ||d	z            z   d
      . c}      }n/dj                  |D cg c]  } |t        |      d       c}      }t        | j                  | j                  | j                        }|dk7  r|dz  }dj                  | j                  ||      S c c}w c c}w )Nc                 >    | dk\  r| dk  r| dvrt        |       S || z  S )N    ~   )"   \   )chr)rt  escape_patterns     rQ   escapez NameRecord.asFea.<locals>.escape  s*    DyQ$Y1L+@1v%))rV   zUnsupported encoding)encoding	utf_16_ber   r   r      r   z\%04xz\%02xr   znameid {} {}"{}";)r   r  r  r  r   r   r   r  rS   r  r   r   r  r   r  )	r   r   r  r  r   r  escaped_stringbplats	            rQ   r   zNameRecord.asFea  s    	* tL!"8$--HHDKK(3{"WW #1c!fa0 71Q4=3.1q51BBHMN  WWA%NqfWQZ&B%NON'U2:CKD"))$++t^LL &Os   1E Er   r   r  rN   rV   rQ   r:   r:     s     K	
MrV   r:   c                       e Zd ZdZd ZddZy)r(   z4Represents a ``sizemenuname`` or ``name`` statement.c                 f    t         j                  | |       |j                  | j                         y)z8Calls the builder object's ``add_featureName`` callback.N)r:   r   add_featureNamer  r   s     rQ   r   zFeatureNameStatement.build  s$    w',rV   c                     | j                   dk(  rd}nd}t        | j                  | j                  | j                        }|dk7  r|dz  }dj                  ||| j                        S )Nsizesizemenunamer   r   r   z
{} {}"{}";)r  r  r  r  r  r   r  )r   r   r   r  s       rQ   r   zFeatureNameStatement.asFea  s[    ;;&  CC'U2:CKD""3dkk::rV   Nr   )r   r   r   r   r   r   rN   rV   rQ   r(   r(     s    >-
;rV   r(   c                       e Zd ZdZddZy)rE   z+Represents a STAT table ``name`` statement.c                     t        | j                  | j                  | j                        }|dk7  r|dz  }dj	                  || j
                        S Nr   r   zname {}"{}";r  r  r  r  r   r  r   r   r  s      rQ   r   zSTATNameStatement.asFea  C    'U2:CKD$$T4;;77rV   Nr   )r   r   r   r   r   rN   rV   rQ   rE   rE     s
    58rV   rE   c                   &    e Zd ZdZddZd ZddZy)rA   zA ``parameters`` statement.Nc                 h    t         j                  | |       || _        || _        || _        || _        y r   )rB   r   
DesignSizeSubfamilyID
RangeStartRangeEnd)r   r  r  r  r  r   s         rQ   r   zSizeParameters.__init__  s/    4*$&$ rV   c                     |j                  | j                  | j                  | j                  | j                  | j
                         y)z<Calls the builder object's ``set_size_parameters`` callback.N)set_size_parametersr   r  r  r  r  r   s     rQ   r   zSizeParameters.build  s5    ##MMOOOOMM	
rV   c                    dj                  | j                  | j                        }| j                  dk7  s| j                  dk7  rA|dj                  t        | j                  dz        t        | j                  dz              z  }|dz   S )Nzparameters {:.1f} {}r   z {} {}
   r4  )r   r  r  r  r  intr   s      rQ   r   zSizeParameters.asFea  sq    $++DOOT=M=MN??a4==A#58??3t';#<c$--RTBT>UVVCSyrV   r   r   r  rN   rV   rQ   rA   rA     s    %!
rV   rA   c                   (    e Zd ZdZ	 ddZd ZddZy)r   z;Represent a name statement inside a ``cvParameters`` block.Nc           	      J    t         j                  | ||||||       || _        y r  )r:   r   r"  )r   r  r  r  r  r  r"  r   s           rQ   r   z"CVParametersNameStatement.__init__  s/     	&*i( 	 	
 %rV   c                 2   d}| j                   dk(  r5dj                  |j                  j                  | j                  d            }|j                  | j                         | j                  | j                   |z   f| _        t        j                  | |       y)z9Calls the builder object's ``add_cv_parameter`` callback.r   r$  z_{}r   N)r"  r   cv_num_named_params_getr  add_cv_parameterr:   r   )r   r   items      rQ   r   zCVParametersNameStatement.build  st    ??22<< < < @ @a PQD  -{{DOOd$:;w'rV   c                     t        | j                  | j                  | j                        }|dk7  r|dz  }dj	                  || j
                        S r  r  r  s      rQ   r   zCVParametersNameStatement.asFea  r  rV   r   r   r  rN   rV   rQ   r   r     s    E SW%(8rV   r   c                   &    e Zd ZdZddZd ZddZy)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                 L    t         j                  | |       || _        || _        y r   )rB   r   	characterr   )r   r  r   r   s       rQ   r   zCharacterStatement.__init__  s     4*"rV   c                 P    |j                  | j                  | j                         y)z9Calls the builder object's ``add_cv_character`` callback.N)add_cv_characterr  r   r   s     rQ   r   zCharacterStatement.build  s      :rV   c                 8    dj                  | j                        S )NzCharacter {:#x};)r   r  r   s     rQ   r   zCharacterStatement.asFea  s    !((88rV   r   r   r  rN   rV   rQ   r"   r"     s    
;9rV   r"   c                   &    e Zd ZdZddZd ZddZy)r   zAn axis definition, being either a ``VertAxis.BaseTagList/BaseScriptList``
    pair or a ``HorizAxis.BaseTagList/BaseScriptList`` pair.Nc                 Z    t         j                  | |       || _        || _        || _        y r   )rB   r   basesscriptsrz  )r   r  r  rz  r   s        rQ   r   zBaseAxis.__init__'  s'    4*
 rV   c                 f    |j                  | j                  | j                  | j                         y)z6Calls the builder object's ``set_base_axis`` callback.N)set_base_axisr  r  rz  r   s     rQ   r   zBaseAxis.build-  s     djj$,,FrV   c                 F   | j                   rdnd}| j                  D cg c];  }dj                  |d   |d   dj                  t	        t
        |d                     = }}dj                  |dj                  | j                        ||d	j                  |            S c c}w )
NVertHorizr  r   r   r   r   z2{}Axis.BaseTagList {};
{}{}Axis.BaseScriptList {};rL   )rz  r  r   rS   r   rs  r  )r   r   	directionr  r  s        rQ   r   zBaseAxis.asFea1  s    "mmF	 \\
 adAaD#((3sAaD>*BC
 
 EKKsxx

+VY		'@R
 	
	
s   A Br   r   r  rN   rV   rQ   r   r   #  s    @!G
rV   r   c                   &    e Zd ZdZddZd ZddZy)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                 L    t         j                  | |       || _        || _        y r   rB   r   r  r  r   r  r  r   s       rQ   r   zOS2Field.__init__A       4*
rV   c                 P    |j                  | j                  | j                         y)z6Calls the builder object's ``add_os2_field`` callback.N)add_os2_fieldr  r  r   s     rQ   r   zOS2Field.buildF  s    dhh

3rV   c                    d }d}d}t        |D cg c]  }|j                         |t        gf c}      }|j                  |D cg c]  }|j                         ||gf c}       d|g|d<   dd g|d<   | j                  |v rBd	j                  || j                     d
    || j                     d   | j                              S yc c}w c c}w )Nc                 @    dj                  t        t        |             S )Nr   )rS   r   rs  )r_  s    rQ   
intarr2strz"OS2Field.asFea.<locals>.intarr2strK  s    88CQK((rV   )FSTypeTypoAscenderTypoDescenderTypoLineGap	winAscent
winDescentXHeight	CapHeightWeightClass
WidthClassLowerOpSizeUpperOpSize)UnicodeRangeCodePageRangePanosepanoseVendorc                 $    dj                  |       S )Nz"{}"r  )r`  s    rQ   <lambda>z OS2Field.asFea.<locals>.<lambda>`  s    &--2B rV   vendor{} {};r   r   r   )rL  r   rs  updater  r   r  )r   r   r  numbersrangesr_  keywordss          rQ   r   zOS2Field.asFeaJ  s    	)
 3@1!'')aX.@AvF!!'')a_5FG&
3&(BC88x??"1%'<x'9!'<TZZ'H   AFs   CCr   r   r  rN   rV   rQ   r;   r;   <  s    G
4rV   r;   c                   &    e Zd ZdZddZd ZddZy)r+   zAn entry in the ``hhea`` table.Nc                 L    t         j                  | |       || _        || _        y r   r  r  s       rQ   r   zHheaField.__init__k  r  rV   c                 P    |j                  | j                  | j                         y)z7Calls the builder object's ``add_hhea_field`` callback.N)add_hhea_fieldr  r  r   s     rQ   r   zHheaField.buildp      txx4rV   c                     d}t        |D cg c]  }|j                         |f c}      }dj                  || j                     | j                        S c c}w )N)CaretOffsetAscender	DescenderLineGapr  rL  r   r   r  r  r   r   fieldsr_  r  s        rQ   r   zHheaField.asFeat  sI    D8A!'')Q89x14::>> 9   Ar   r   r  rN   rV   rQ   r+   r+   h      )
5?rV   r+   c                   &    e Zd ZdZddZd ZddZy)rJ   zAn entry in the ``vhea`` table.Nc                 L    t         j                  | |       || _        || _        y r   r  r  s       rQ   r   zVheaField.__init__}  r  rV   c                 P    |j                  | j                  | j                         y)z7Calls the builder object's ``add_vhea_field`` callback.N)add_vhea_fieldr  r  r   s     rQ   r   zVheaField.build  r  rV   c                     d}t        |D cg c]  }|j                         |f c}      }dj                  || j                     | j                        S c c}w )N)VertTypoAscenderVertTypoDescenderVertTypoLineGapr  r  r  s        rQ   r   zVheaField.asFea  sI    M8A!'')Q89x14::>> 9r  r   r   r  rN   rV   rQ   rJ   rJ   z  r  rV   rJ   c                   &    e Zd ZdZddZd ZddZy)rD   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                 h    t         j                  | |       || _        || _        || _        || _        y r   )rB   r   r   	axisOrdernamesr   )r   r   r  r  r   s        rQ   r   z STATDesignAxisStatement.__init__  s.    4*"
 rV   c                 <    |j                  | | j                         y r   )addDesignAxisr   r   s     rQ   r   zSTATDesignAxisStatement.build  s    dDMM2rV   c           	          |t         z  }d| j                   d| j                   d}|d|z   j                  | j                  D cg c]  }|j                  |       c}      dz   z  }|dz  }|S c c}w )NzDesignAxis r   z { 
r   r  };)r  r   r  rS   r  r   r   r   r   r   s       rQ   r   zSTATDesignAxisStatement.asFea  su    %DHH:Qt~~&6f=v##TZZ$PQWWFW%;$PQTXXXt
 %Qs   A0
r   r   r  rN   rV   rQ   rD   rD     s    !3rV   rD   c                   &    e Zd ZdZddZd ZddZy)r%   ziSTAT table ElidedFallbackName

    Args:
        names: a list of :class:`STATNameStatement` objects
    Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   r  r   )r   r  r   s      rQ   r   zElidedFallbackName.__init__       4*
 rV   c                 P    |j                  | j                  | j                         y r   )setElidedFallbackNamer  r   r   s     rQ   r   zElidedFallbackName.build      %%djj$--@rV   c           	          |t         z  }d}|d|z   j                  | j                  D cg c]  }|j                  |       c}      dz   z  }|dz  }|S c c}w )NzElidedFallbackName { 
r   r  r   )r  rS   r  r   r!  s       rQ   r   zElidedFallbackName.asFea  s]    %'v##TZZ$PQWWFW%;$PQTXXXt
 %Qs   A
r   r   r  rN   rV   rQ   r%   r%     s    !
ArV   r%   c                   &    e Zd ZdZddZd ZddZy)r&   zpSTAT table ElidedFallbackNameID

    Args:
        value: an int pointing to an existing name table name ID
    Nc                 L    t         j                  | |       || _        || _        y r   )rB   r   r  r   )r   r  r   s      rQ   r   zElidedFallbackNameID.__init__  r$  rV   c                 P    |j                  | j                  | j                         y r   )r&  r  r   r   s     rQ   r   zElidedFallbackNameID.build  r'  rV   c                 "    d| j                    dS )NzElidedFallbackNameID r4  )r  r   s     rQ   r   zElidedFallbackNameID.asFea  s    &tzzl!44rV   r   r   r  rN   rV   rQ   r&   r&     s    !
A5rV   r&   c                   &    e Zd ZdZddZd ZddZy)rC   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                 Z    t         j                  | |       || _        || _        || _        y r   )rB   r   r  	locationsr  )r   r  r/  r  r   s        rQ   r   zSTATAxisValueStatement.__init__  s'    4*
"
rV   c                 <    |j                  | | j                         y r   )addAxisValueRecordr   r   s     rQ   r   zSTATAxisValueStatement.build  s    ""47rV   c                    d}| j                   D ]  }||j                         z  } | j                  D ]  }||j                         z  }|dz  } | j                  rdddg}g }d}t	        t        |            D ]-  }| j                  |z  dk7  r|j                  ||          |dz  }/ |ddj                  |       d	z  }|d
z  }|S )NzAxisValue {
r   OlderSiblingFontAttributeElidableAxisValueNamer   r   zflag r   ;
r   )r/  r   r  r  r  r   r   rS   )	r   r   r   r   
nameRecordr  flagStringsr   r  s	            rQ   r   zSTATAxisValueStatement.asFea  s     	$H8>>##C	$ ** 	J:##%%C4KC	 ::02IJEKD3u:& !::$)&&uQx0qy! U388K0155Ct
rV   r   r   r  rN   rV   rQ   rC   rC     s    8rV   rC   c                        e Zd ZdZddZddZy)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                 L    t         j                  | |       || _        || _        y r   )rB   r   r   values)r   r   r:  r   s       rQ   r   z#AxisValueLocationStatement.__init__  s     4*rV   c                 |    |d| j                    dz  }|dj                  d | j                  D               dz  }|S )Nz	location r   c              3   2   K   | ]  }t        |        y wr   rr  )rO   r  s     rQ   rR   z3AxisValueLocationStatement.asFea.<locals>.<genexpr>	  s     7a3q67ru  r5  )r   rS   r:  )r   r   s     rQ   r   z AxisValueLocationStatement.asFea  sC    488*A&&#((74;;778<<
rV   r   r   r   rN   rV   rQ   r   r     s    
rV   r   c                   &    e Zd ZdZddZd ZddZy)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                 L    t         j                  | |       || _        || _        y r   )rB   r   r   
conditions)r   r   r?  r   s       rQ   r   zConditionsetStatement.__init__  s     4*	$rV   c                 f    |j                  | j                  | j                  | j                         y r   )add_conditionsetr   r   r?  r   s     rQ   r   zConditionsetStatement.build  s       		4??KrV   c           	          ||d| j                    dz   dz   z  }| j                  j                         D ]   \  }\  }}||t        z   | d| d| dz   z  }" ||dz   d| j                    dz   z  }|S )Nzconditionset r   r  r5  })r   r?  r  r  )r   r   r   r   minvaluemaxvalues         rQ   r   zConditionsetStatement.asFea  s    v-		{!44u<<)-)>)>)@ 	F%C%(H6E>se1XJaz$EEEC	Fv|$))C000
rV   r   )r   r   r  rN   rV   rQ   r#   r#     s    %
LrV   r#   c                   &    e Zd ZdZddZd ZddZy)VariationBlockzCA variation feature block, applicable in a given set of conditions.Nc                 \    t         j                  | |       |||c| _        | _        | _        y r   )r   r   r   conditionsetr  )r   r   rI  r  r   s        rQ   r   zVariationBlock.__init__*  s,    tX& 	9	4$d&8rV   c                 J   |j                  | j                  | j                         | j                  dk7  r;| j                  |j                  vr#t        d| j                   | j                        |j                  }i |_        t        j                  | |       |j                  j                         D ]V  \  }}|j                  j                  |i       j                  | j                  g       }|j                  |       ||vsRg ||<   X ||_        |j                          y)r  r   z,variation block used undefined conditionset N)r  r   r   rI  conditionsets_r   r  r   r   r  feature_variations_r  r   r  )r   r   r  r  r  r  s         rQ   r   zVariationBlock.build2  s    	dmmTYY7'!!)?)??!>t?P?P>QR  $$D'"!++113 	#JC//::3CNN!!2E LL(" "	# %rV   c                    |d| j                   j                         z  z   }|| j                  dz   z  }| j                  r|dz  }|dz  }|t        j                  | |      z  }||d| j                   j                         z  z   z  }|S )Nzvariation %s r   r  r  r  r  )r   r  rI  r  r   r   r   s      rQ   r   zVariationBlock.asFeaN  s    ):::t  3&&?"Cuu{{4{//v	DIIOO$5555
rV   r  r   r  rN   rV   rQ   rG  rG  '  s    M
8rV   rG  )XfontTools.feaLib.errorr   fontTools.feaLib.locationr   fontTools.misc.encodingToolsr   fontTools.misc.textToolsr   r   collectionsr   r<  r  __all__rU   r  r   r   objectr	   rB   r'   r   r   r   r   r   r   r   r   r
   r   r   r   rG   r   r   r   r   r   r   r   r   r    r!   r$   r)   r,   r-   r.   r/   r0   r*   r1   r2   r3   r4   r5   r6   r7   r8   r9   r<   r=   r@   r>   r?   rF   rH   rI   r  r:   r(   rE   rA   r   r"   r   r;   r+   rJ   rD   r%   r&   rC   r   r#   rG  rN   rV   rQ   <module>rU     s   2 8 4 5 # CLF 57tf ,	 		 		g 	
 !
 ! ;% ;%|*Z *")J )"Y 
I 
.	J% 	J5 @% *% . C9 C 
Y 
<* *Z$
) $
N"i "J"Z "Jy 
i 
&7y 7t7 7tT) T*6	 6!9 !9H99 9B7y 7&	 :Ri R<I <
I 
&
) 
&$Y $N&6) &6R5y 5"9 *5) 5p9 *CY CLPy Pf%y %P+9 +\8i 8% %P	 k* k\	MI 	M0.M .Mb;: ;&8
 8Y 68
 869 9*
y 
2)y )X?	 ?$?	 ?$i 6 .59 5&%Y %P (I 4/U /rV   