
    hhc                        S r SSKJr  SSKJr  SSKJr  SSKJr	  SSK
Jr  SSKJrJr  SSKJr  S	S
KJrJr  S%S jrS rS rS rS rS rS%S jrS rS r " S S\5      r\R=                  \	R>                  S5      S 5       r \R=                  \	RB                  \	RD                  4S5      S 5       r S&S jr#S r$S r%S r&S r'S r(S r)S  r*S! r+S" r,\-S#:X  a4  SS$K.r.SS$K/r/\/R`                  " \.Rb                  " 5       Rd                  5        g$g$)'zModule to build FeatureVariation tables:
https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table

NOTE: The API is experimental and subject to change.
    )hashdict	bit_count)newTable)otTables)	TTVisitor)buildLookupbuildSingleSubstSubtable)OrderedDict   )VarLibErrorVarLibValidationErrorc           	      b   [        U[        5      (       a  U/O
[        U5      nSU;  =(       d    [        U5      S:  n[	        [        U R                  5       5      US9  [        U5      n[        U5      u  pSU ;  a  [        5       U S'   O<[        U S   R                  5      R                  U5      nU(       a  [        SU 35      e[        U S   R                  Xd5      n/ n	U H*  u  pU	R                  X Vs/ s H  oU   PM	     sn45        M,     [!        X S   R                  X5        gs  snf )a  Add conditional substitutions to a Variable Font.

The `conditionalSubstitutions` argument is a list of (Region, Substitutions)
tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to
(minValue, maxValue) tuples. Irrelevant axes may be omitted and they are
interpretted as extending to end of axis in each direction.  A Box represents
an orthogonal 'rectangular' subset of an N-dimensional design space.
A Region represents a more complex subset of an N-dimensional design space,
ie. the union of all the Boxes in the Region.
For efficiency, Boxes within a Region should ideally not overlap, but
functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Example:

# >>> f = TTFont(srcPath)
# >>> condSubst = [
# ...     # A list of (Region, Substitution) tuples.
# ...     ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
# ...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
# ... ]
# >>> addFeatureVariations(f, condSubst)
# >>> f.save(dstPath)

The `featureTag` parameter takes either a str or a iterable of str (the single str
is kept for backwards compatibility), and defines which feature(s) will be
associated with the feature variations.
Note, if this is "rvrn", then the substitution lookup will be inserted at the
beginning of the lookup list so that it is processed before others, otherwise
for any other feature tags it will be appended last.
rvrnr   )
glyphNamessubstitutionsGSUBz4FeatureVariations already exist for feature tag(s): N)
isinstancestrsortedlen_checkSubstitutionGlyphsExistsetgetGlyphOrderoverlayFeatureVariationsmakeSubstitutionsHashable	buildGSUB_existingVariableFeaturestableintersectionr   buildSubstitutionLookupsappendaddFeatureVariationsRaw)fontconditionalSubstitutions
featureTagfeatureTagsprocessLastr   allSubstitutionsexistingTags	lookupMapconditionsAndLookupsconditionSetss               N/var/www/html/env/lib/python3.13/site-packages/fontTools/varLib/featureVars.pyaddFeatureVariationsr0      s>   N #-Z"="=:,6*CUK+Cs;/?!/CK!t))+,.
 --EFM 2K2. T {V0f1C1CDQQ
 F|nU 
 )V,I '?###-@-QaL-@A	
 (@
 Dv,"4"46JX As   8D,c                 D   [        5       n[        U S5      (       a  U R                  bw  U R                  R                  nU R                  R
                   HG  nUR                  R                   H*  nUR                  X$R                     R                  5        M,     MI     U$ )NFeatureVariations)r   hasattrr2   FeatureListFeatureRecordFeatureVariationRecordFeatureTableSubstitutionSubstitutionRecordaddFeatureIndex
FeatureTag)r   existingFeatureVarsTagsfeaturesfvrftsrs        r/   r   r   c   s    !eu)**u/F/F/R$$22**AAC44GG'++H5F5F,G,R,RS H B #"    c                     [        5       nU H3  u  p4X$R                  5       -  nU[        UR                  5       5      -  nM5     X -
  nU(       a  [        SSR	                  U5       35      eg )NzAMissing glyphs are referenced in conditional substitution rules: z, )r   keysvaluesr   join)r   r   referencedGlyphNames_substitutionmissings         r/   r   r   m   sy    5( 1 1 33L$7$7$9 :: ) #/G#		'"#%
 	
 r@   c                    [        5       nU  H.  u  p#[        U5      nX1;   a  X   R                  U5        M*  X!U'   M0     UR                  5        VVs/ s H  u  pEU[	        U5      4PM     n nnA[        5       n[        U 5       HG  u  p2[        [        S U 5       S S95      nX1;   a  X   R                  U5        M:  [	        U5      X'   MI     [        [        UR                  5       5      5      n A[        5       S44n[        U5      n[        U 5       H  u  nu  p[        U5      nSU-  nUR                  5        Hm  u  pU	 Hb  n[        X5      u  nnUb&  [        U5      nUR                  US5      U-  U-  UU'   Uc  M?  [        U5      nUR                  US5      U-  UU'   Md     Mo     UnM     / n[        UR                  5       S S9 Hg  u  pUS:X  a  M  / nSnU(       a3  US-  (       a  UR                  X   S   5        US-  nUS-  nU(       a  M3  UR                  [	        U5      U45        Mi     U$ s  snnf )a  Compute overlaps between all conditional substitutions.

The `conditionalSubstitutions` argument is a list of (Region, Substitutions)
tuples.

A Region is a list of Boxes. A Box is a dict mapping axisTags to
(minValue, maxValue) tuples. Irrelevant axes may be omitted and they are
interpretted as extending to end of axis in each direction.  A Box represents
an orthogonal 'rectangular' subset of an N-dimensional design space.
A Region represents a more complex subset of an N-dimensional design space,
ie. the union of all the Boxes in the Region.
For efficiency, Boxes within a Region should ideally not overlap, but
functionality is not compromised if they do.

The minimum and maximum values are expressed in normalized coordinates.

A Substitution is a dict mapping source glyph names to substitute glyph names.

Returns data is in similar but different format.  Overlaps of distinct
substitution Boxes (*not* Regions) are explicitly listed as distinct rules,
and rules with the same Box merged.  The more specific rules appear earlier
in the resulting list.  Moreover, instead of just a dictionary of substitutions,
a list of dictionaries is returned for substitutions corresponding to each
unique space, with each dictionary being identical to one of the input
substitution dictionaries.  These dictionaries are not merged to allow data
sharing when they are converted into font tables.

Example::

    >>> condSubst = [
    ...     # A list of (Region, Substitution) tuples.
    ...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
    ...     ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
    ...     ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
    ...     ([{"wght": (0.5, 1.0), "wdth": (-1, 1.0)}], {"dollar": "dollar.rvrn"}),
    ... ]
    >>> from pprint import pprint
    >>> pprint(overlayFeatureVariations(condSubst))
    [({'wdth': (0.5, 1.0), 'wght': (0.5, 1.0)},
      [{'dollar': 'dollar.rvrn'}, {'cent': 'cent.rvrn'}]),
     ({'wdth': (0.5, 1.0)}, [{'cent': 'cent.rvrn'}]),
     ({'wght': (0.5, 1.0)}, [{'dollar': 'dollar.rvrn'}])]

c              3   J   #    U  H  n[        [        U5      5      v   M     g 7fN)r   
cleanupBox).0ks     r/   	<genexpr>+overlayFeatureVariations.<locals>.<genexpr>   s     6#Q*Q-((#s   !#c                 F    [        [        U R                  5       5      5      $ rK   )tupler   items)ds    r/   <lambda>*overlayFeatureVariations.<locals>.<lambda>   s    eF1779$56r@   )keyr   r   c                      [        U S   5      * $ )Nr   r   )
BoxAndRanks    r/   rU   rV      s    :a=1I0Ir@   )r   r   extendrS   dictreversedrR   r   updatelist	enumerate
overlayBoxgetr"   )r%   mergedvaluerW   rN   vinitMapInitboxMapi
currRegionrF   newMapcurrRankboxrankcurrBoxr    	remainderrS   
substsLists                       r/   r   r   z   sG   ^ ]F.
sm=Ku%3K / :@HDGH ]F78
6#66
 =Ku%u+FK 9  $HV\\^$<=
 J?$K%F'(@A?J[)6IC%*4W*B'i+#+L#9L+1::lA+F+MPX+XF<(( ( 3I(.

9a(@4(GF9% & (  B EI	 19
ax!!":"=a"@AQJDFA	 d
 	d3i,- Lu  Is   H<c                    0 nUR                  U 5        UR                  U5        [        U 5      [        U5      -   H5  nX   u  pEX   u  pg[        XF5      n[        XW5      n	X:  d  SU4s  $ X4X#'   M7     [	        U5      n
SnSnU  H  nX1;   a  M
  SnSn  O   U Hb  nX0;  a  M
  X#   u  pEX   u  pgXF::  a  Xu::  a  M"  U(       a  X!4s  $ SnSnXF::  a  [        XV5      nUn	OXu::  a  Un[        XG5      n	OX!4s  $ X4X'   Md     U(       a  US4$ X*4$ )a1  Overlays ``top`` box on top of ``bot`` box.

Returns two items:

* Box for intersection of ``top`` and ``bot``, or None if they don't intersect.
* Box for remainder of ``bot``.  Remainder box might not be exact (since the
  remainder might not be a simple box), but is inclusive of the exact
  remainder.
NFT)r]   r   maxminr[   )topbotr    axisTagmin1max1min2max2minimummaximumrn   	extrudingfullyInsides                r/   r`   r`      sT    Ls8c#h&\
\
d/d/ 9 ' 0 '( S	IIK>	  !*
\
<DL $$	 <$oGG\G$oG  $$$-	A D T!!""r@   c                 h    U R                  5        VVs0 s H  u  pUS:w  d  M  X_M     snn$ s  snnf )zReturn a sparse copy of `box`, without redundant (default) values.

>>> cleanupBox({})
{}
>>> cleanupBox({'wdth': (0.0, 1.0)})
{'wdth': (0.0, 1.0)}
>>> cleanupBox({'wdth': (-1.0, 1.0)})
{}

)g      g      ?)rS   )rk   taglimits      r/   rL   rL   L  s/     *-M:38LJCJMMMs   ..c                 2
  ^  [        U[        5      (       a  U/O
[        U5      nSU;  =(       d    [        U5      S:  nUR                  S:  a  SUl        [        5       nUR                  R                   Vs1 s H!  nUR                  U;   d  M  UR                  iM#     snm [        U5      T -
  nU(       Ga  / n	[        U5       HE  n[        U/ 5      n
UR                  R                  R                  U
5        U	R                  U
5        MG     [        UR                  R                  5      UR                  l        [        U5        U	 GH  n
UR                  R                  R                  U
5      nUR                  R                   H  nUR                   R"                  c  [%        SUR&                   S35      eUR                   R(                   Vs/ s H  oR*                  PM     nnUR                   R"                  /U-    H8  nUR,                  R                  U5        [        UR,                  5      Ul        M:     M     UR/                  U5        GM     T (       a8  UR1                  U 4S j[3        UR                  R                  5       5       5        [3        U S   R4                  5       VVs0 s H  u  nnUR6                  U_M     nnn[9        US	5      =(       a    UR:                  SLn/ nU GHc  u  nn/ n[        UR=                  5       5       H;  u  nu  nnUU:  a  [?        S
5      e[A        UU   UU5      nUR                  U5        M=     / n[        U5       H\  nUR                  R                  U   RB                  RD                  nU(       a  UU-   OUU-   nUR                  [G        UU5      5        M^     U(       as  [I        UR:                  U5      =n(       aV  URJ                  RL                  RO                  U5        [        URJ                  RL                  5      URJ                  l(        GMH  UR                  [S        UU5      5        GMf     U(       a  UR:                  R                  S:w  a$  [%        SUR:                  R                  S S35      eUR:                  RT                  RO                  U5        [        UR:                  RT                  5      UR:                  l+        g[Y        U5      Ul        gs  snf s  snf s  snnf )zwLow level implementation of addFeatureVariations that directly
models the possibilities of the FeatureVariations table.r   r     Nz,Feature variations require that the script 'z$' defines a default language system.c              3   P   >#    U  H  u  pUR                   T;   d  M  Uv   M     g 7frK   )r;   )rM   indexfeaturer*   s      r/   rO   *addFeatureVariationsRaw.<locals>.<genexpr>  s*      !
"L!!\1 E"Ls   &	&fvarr2   z<A condition set has a minimum value above the maximum value.   /Unsupported FeatureVariations table version: 0x08x (expected 0x00010000).)-r   r   r   r   Versionr   r4   r5   r;   buildFeatureRecordr"   FeatureCountsortFeatureListr   
ScriptListScriptRecordScriptDefaultLangSysr   	ScriptTagLangSysRecordLangSysr:   r9   r]   r_   axesru   r3   r2   rS   r   buildConditionTableFeatureLookupListIndex#buildFeatureTableSubstitutionRecordfindFeatureVariationRecordr7   r8   rZ   SubstitutionCountbuildFeatureVariationRecordr6   FeatureVariationCountbuildFeatureVariations)!r$   r   r%   r&   r'   r(   varFeatureIndicesr   newTagsvarFeatures
varFeaturevarFeatureIndexscriptRecordlsrlangSystemslangSys	axisIndexaxisaxisIndiceshasFeatureVariationsfeatureVariationRecordsr-   lookupIndicesconditionTableru   minValuemaxValuectrecordsexistingLookupIndicescombinedLookupIndicesr>   r*   s!                                   @r/   r#   r#   _  s    #-Z"="=:,6*CUK+Cs;/?!/CK }}z!" ((666G, 	6L +-G /J+J;J++22:>z* * *-U->->-L-L)M&%J#//==CCJOO % 0 0 = =&&55=%(2233WY  7C6I6I6W6WX6Ws{{6WX , 3 3 B BCkQG((//@+.w/C/C+DG(  R !> !!/2 &  	   !
"+E,=,=,K,K"L!
 	
 8AfARAR7S7SOIti7S  
 	*+S0G0Gt0S  !'?#m-3L4F4F4H-I)G)h("+R  %[%98XNB!!"% .J %&78O$)$5$5$C$C%goo "
  &5"%:: " NN3#%:  9  -e.E.E~VVCV((;;BB7K=@,,??>C((: $**+NGDC (@J ""**j8,,44S99PR  	66==>UV8;##::9
5 #99P"QE4 Ys   8T	T	T5Tc                     [        S5      n [        R                  " 5       =ol        SUl        [        R
                  " 5       Ul        / UR
                  l        [        R                  " 5       Ul        / UR                  l        [        R                  " 5       Ul	        / UR                  l
        [        R                  " 5       nSUl        [        R                  " 5       Ul        SUR                  l        / UR                  l        SUR                  l        [        R                  " 5       n[        R                   " 5       Ul        SUR                   l        / UR                   l        UR                   UR                  l        UR
                  R                  R'                  U5        SUR
                  l        SUl        U $ )z Build a GSUB table from scratch.r   r   DFLTNr     r   )r   otr   r   r   r   r   r4   r5   
LookupListLookupr   r   r   r   LangSysCountr   ReqFeatureIndexr:   r"   ScriptCountr2   )	fontTablegsubsreclangrecs       r/   r   r     s+    IWWY&D?DLmmoDO#%DOO ~~'D%'D"mmoDODOO??DDN))+DK!%DKK "DKK DKK GjjlGO&,GOO##%GOO !(DKKOO  ''-"#DOO!Dr@   c                    [        5       n/ nU  Hf  u  p4/ nU HG  n[        [        UR                  5       5      5      nUR	                  U5        UR                  U5        MI     UR	                  X545        Mh     U[        U5      4$ )zTurn all the substitution dictionaries in sorted tuples of tuples so
they are hashable, to detect duplicates so we don't write out redundant
data.)r   rR   r   rS   r"   r9   )r%   r)   	condSubstr-   substitutionMapsr   substitutionMapsubsts           r/   r   r      s     uI*B&/O&!6!6!89:E  '  '  0 	,67 +C f-...r@   c                       \ rS rSrS rSrg)ShifterVisitori  c                     Xl         g rK   shift)selfr   s     r/   __init__ShifterVisitor.__init__  s    
r@   r   N)__name__
__module____qualname____firstlineno__r   __static_attributes__ r@   r/   r   r     s    r@   r   r   c                 f    U R                   nU Vs/ s H  oUU-   PM	     nn[        XU5        g s  snf rK   )r   setattr)visitorobjattrrc   r   ls         r/   visitr     s0    MME %&1YE&Cu 's   .c                 6    [        XU R                  U-   5        g rK   )r   r   )r   r   r   rc   s       r/   r   r     s     Cw}}u,-r@   c                    U(       a  [        U R                  R                  5      OSn0 n[        U5       H  u  pVX5-   XF'   M     U(       d`  [        U5      n[	        U5      nUR                  U R                  R                  5        UR                  U R                  R                  5        [        U5       H  u  pY[        U	5      n
[        [        U
5      /5      nU(       a&  U R                  R                  R                  U5        O%U R                  R                  R                  X[5        U R                  R                  XI      UL a  M   e   [        U R                  R                  5      U R                  l        U$ )zhBuild the lookups for the glyph substitutions, return a dict mapping
the substitution to lookup indices.r   )r   r   r   r_   r   r   r4   r5   r[   r	   r
   r"   insertLookupCount)r   r)   r(   
firstIndexr+   rg   r   r   r   r   substMaplookups               r/   r!   r!   #  s*    1<T__++,JI'(89%/^	" : $% 'd&&445doo,,-./;6x@ABOO""))&1OO""))!4%%i&676AAA 0 #&doo&<&<"=DOOr@   c                 j    [         R                  " 5       nSUl        Xl        [	        U 5      Ul        U$ )z%Build the FeatureVariations subtable.r   )r   r2   r   r6   r   r   )r   fvs     r/   r   r   B  s0    				BBJ 7"#:;BIr@   c                     [         R                  " 5       nXl        [         R                  " 5       Ul        XR                  l        UR                  R                  5         U$ )zBuild a FeatureRecord.)r   r5   r;   r   r   populateDefaults)r&   lookupListIndicesfrs      r/   r   r   K  sA    				BMBJ!2JJJJ!Ir@   c                 b   [         R                  " 5       n[         R                  " 5       Ul        XR                  l        [	        U 5      UR                  l        [         R                  " 5       Ul        SUR                  l        XR                  l        [	        U5      UR                  l	        U$ )zBuild a FeatureVariationRecord.r   )
r   r6   ConditionSetConditionTabler   ConditionCountr7   r   r8   r   )r   substitutionRecordsr>   s      r/   r   r   U  s    

#
#
%C(C&4#&).&9C##%#>#>#@C +5C  (6I  3589L5MC  2Jr@   c                     [         R                  " 5       nXl        [         R                  " 5       Ul        XR                  l        [        U5      UR                  l        U$ )z'Build a FeatureTableSubstitutionRecord.)r   FeatureTableSubstitutionRecordr:   r   r   r   r   )featureIndexr   r?   s      r/   r   r   b  sD    ,,.D$::<DL#4LL "#45DLLKr@   c                 b    [         R                  " 5       nSUl        Xl        Xl        X#l        U$ )zBuild a ConditionTable.r   )r   r   Format	AxisIndexFilterRangeMinValueFilterRangeMaxValue)r   filterRangeMinValuefilterRangeMaxValuer   s       r/   r   r   l  s-    				BBIL00Ir@   c                     U R                   S:w  a  [        SU R                   S S35      eU R                   H   nXR                  R                  :X  d  M  Us  $    g)z?Find a FeatureVariationRecord that has the same conditionTable.r   r   r   r   N)r   r   r6   r   r   )featureVariationsr   r>   s      r/   r   r   v  sg      J."**3//FH
 	

 !77--<<<J 8 r@   c                    [        U R                  R                  5       VVs/ s H  u  pUR                  X4PM     nnnUR	                  5         U VVVs/ s H  u  pAo"PM	     snnnU R                  l        [        [        U VVVs/ s H  u  pAo!PM	     snnn[        [        U5      5      5      5      n[        X5        gs  snnf s  snnnf s  snnnf )zSort the feature list by feature tag, and remap the feature indices
elsewhere. This is needed after the feature list has been modified.
N)
r_   r4   r5   r;   sortr[   zipranger   remapFeatures)r   r   featagIndexFear   featureRemaps         r/   r   r     s     $E$5$5$C$CDDJE 
$D   BM&N+s3s+&NE#+6+s3U+6c+>N8OPL
 %&
 'O6s   CCCc                    [        U R                  R                  5       Hh  u  p#UR                  R                  nUb  [        XA5        [        UR                  R                  5       H  u  pVUR                  n[        Xq5        M     Mj     [        U S5      (       a\  U R                  bN  U R                  R                   H3  nUR                  R                   H  n	XR                     U	l        M     M5     ggg)z7Go through the scripts list, and remap feature indices.Nr2   )r_   r   r   r   r   _remapLangSysr   r   r3   r2   r6   r7   r8   r:   )
r   r  scriptIndexscriptdefaultLangSyslangSysRecordIndex
langSysRecr   r>   r?   s
             r/   r   r     s    ()9)9)F)FG55%.7.78S8S.T* ((G'0 /U	  H u)**u/F/F/R**AAC44GG$01B1B$C! H B 0S*r@   c                     U R                   S:w  a  XR                      U l         U R                   Vs/ s H  o!U   PM	     snU l        g s  snf )Nr   )r   r:   )r   r  r   s      r/   r  r    sF    &("./F/F"G=D=Q=QR=QE/=QRGRs   A	__main__N)r   )F)3__doc__fontTools.misc.dictToolsr   fontTools.misc.intToolsr   fontTools.ttLibr   fontTools.ttLib.tablesr   r   fontTools.ttLib.ttVisitorr   fontTools.otlLib.builderr	   r
   collectionsr   errorsr   r   r0   r   r   r   r`   rL   r#   r   r   r   register_attrr   r   SubstLookupRecordPosLookupRecordr!   r   r   r   r   r   r   r   r   r  r   doctestsysexittestmodfailedr   r@   r/   <module>r     s$   . - $ 1 / J # 6NYb#

pzR#jN&xR@B/ Y 
 bjj*;< = 2--.0A..>
'&D S zHHW__%%& r@   