)EjT*dZddlZddlZddlmZddlmZddlmZddl m Z m Z ddl mZ ddlmZejdZgd Zd Zd ZGd d ejZGddZddZedkrddlZejedSdS)u6MS VOLT ``.vtp`` to AFDKO ``.fea`` OpenType Layout converter. Usage ----- To convert a VTP project file: .. code-block:: sh $ fonttools voltLib.voltToFea input.vtp output.fea It is also possible convert font files with `TSIV` table (as saved from Volt), in this case the glyph names used in the Volt project will be mapped to the actual glyph names in the font files when written to the feature file: .. code-block:: sh $ fonttools voltLib.voltToFea input.ttf output.fea The ``--quiet`` option can be used to suppress warnings. The ``--traceback`` can be used to get Python traceback in case of exceptions, instead of suppressing the traceback. Limitations ----------- * Not all VOLT features are supported, the script will error if it it encounters something it does not understand. Please report an issue if this happens. * AFDKO feature file syntax for mark positioning is awkward and does not allow setting the mark coverage. It also defines mark anchors globally, as a result some mark positioning lookups might cover many marks than what was in the VOLT file. This should not be an issue in practice, but if it is then the only way is to modify the VOLT file or the generated feature file manually to use unique mark anchors for each lookup. * VOLT allows subtable breaks in any lookup type, but AFDKO feature file implementations vary in their support; currently AFDKO’s makeOTF supports subtable breaks in pair positioning lookups only, while FontTools’ feaLib support it for most substitution lookups and only some positioning lookups. N)StringIO)TopologicalSorter)ast)TTFont TTLibError)ParserzfontTools.voltLib.voltToFea)GDEFGSUBGPOSc,g}t|ttfr(|D]$}|t |%nMt |dr(|t |jn|||S)Nenum) isinstancetuplelistextend_flatten_grouphasattrr append)groupretitems MC:\PYTHON\MyICR_Suite\python\Lib\site-packages\fontTools/voltLib/voltToFea.pyrr=s C%%'' - -D JJ~d++ , , , , -    >%*--.... 5 Jcd|Dd|D}t|}fd|DS)NcBi|]}|j|S)namelower.0rs r zsort_groups..Ms(???u!!##U???rcpi|]3}|jdt|D4S)ctg|]5}t|tj|j6Sr)rVAst GroupNamerrr xs r z*sort_groups...OsD   !T^,, GMMOO   r)rrrrs rr!zsort_groups..Ns\        #E**      rc g|] }| Srr)r r group_maps rr(zsort_groups..Ws > > >IdO > > >r)r static_order)groupsgraphsorterr*s @r sort_groupsr/Lsk?????I       Eu % %F > > > >(;(;(=(= > > >>rc eZdZdfd ZxZS)LookupFNc\t|||g|_dSN)super__init__chained)selfr use_extensionlocation __class__s rr5zLookup.__init__[s* }h777 r)FN)__name__ __module__ __qualname__r5 __classcell__)r:s@rr1r1Zs=rr1ceZdZejdZejdZddZdZdZ ddZ d Z dd Z d Z d Zd ZddZdZdZdZdZddZdZdZdZdZdZdZdZdZdS) VoltToFeaz[^A-Za-z_0-9.]z[^A-Za-z_0-9.\-]NcTt|tjr|dc|_|_nd|c|_|_||_i|_d|_i|_i|_ i|_ i|_ t|_ i|_i|_i|_i|_i|_i|_dSr3)rr$VoltFile_doc _file_or_path_font _glyph_map _glyph_order_gdef _glyphclasses _features_lookupsset_marks _ligatures _markclasses_anchors _settings _lookup_names _class_names)r7 file_or_pathfonts rr5zVoltToFea.__init__ds lDM 2 2 ?,8$ )DIt)),0, )DIt)    ee  rc||jvr`|jd|}||jvr |dz }||jv ||j|<|j|SN_)rR_NOT_LOOKUP_NAME_REsubvaluesr7rress r _lookupNamezVoltToFea._lookupName~s t) ) )*..sD99C+224444s +224444'*D t $!$''rc||jvr`|jd|}||jvr |dz }||jv ||j|<|j|SrW)rS_NOT_CLASS_NAME_RErZr[r\s r _classNamezVoltToFea._classNames t( ( ()--c488C*113333s *113333&)D d # &&rFch|jD]1}t|tjr||2d|jD}t |D]}|||jD]}t|tjrd|vr||6t|tj r| ||gt|tjtj frt|tj r| |t|tjst||jD]I}t|tjr-|jrd|vr(|jrd|vr4||JdS)NcFg|]}t|tj|Sr)rr$GroupDefinition)r ss rr(z0VoltToFea._collectStatements..s*SSSz!T=Q/R/RS!SSSrr r ) statementsrr$GlyphDefinition_glyphDefinitionr/_groupDefinitionAnchorDefinition_anchorDefinitionSettingDefinition_settingDefinitionrdScriptDefinition_scriptDefinitionLookupDefinitionNotImplementedErrorposrZ_lookupDefinition)r7doctablesignore_unsupported_settings statementr,rs r_collectStatementszVoltToFea._collectStatementss 1 1I)T%9:: 1%%i000 TSS^SSS (( ) )E  ! !% ( ( ( ( 5 5I)T%:;; 5V##**9555It'=>> 5'' 3NOOOOI(R'STT 5It'<== 5&&y1111 4+@AA 5))444 5  2 2I)T%:;; 2=V6%9%9=V6%9%9&&y111  2 2rc  tj}|j}jrS|tjd|jjrj|tjd|dtj Dj rr|tjdj D]1}||j ||2j }|D]u}||}|D]G}||} | D]} fd| | D| | <d| D||<Hd| D||<vd| D}|r|tjd | D]\}}tj|} t|d } |d kr7t!| d kr$t"d| dd } | D]>}|d kr,| jtj|t||d } |d kr7t!| d kr$t"d| dd } | D]} |d krK| dkrdnd}| jtj| d|||| D]O}j |}tj|}| j|P@|| ‰jrd|vrg}dD]}|jvrtd|z}tj|j|}|||tj||dtjd}|jtj||||S)Nz# Glyph classesz # Mark classesc3&K|] }|dV dSNr)r cs r z.VoltToFea._buildFeatureFile..s&NNqadNNNNNNrz # LookupscJg|]}|jv| Sr)rrK)r lr7s rr(z/VoltToFea._buildFeatureFile..s4+++!''))t}:T:T:T:T:Trci|] \}}||| Srr)r trs rr!z/VoltToFea._buildFeatureFile..s#&K&K&K1&Kq!&K&K&Krci|] \}}||| Srr)r rres rr!z/VoltToFea._buildFeatureFile..s#$K$K$Kda$KQ$K$K$Krci|] \}}||| Srr)r rfs rr!z/VoltToFea._buildFeatureFile..s#;;;TQ;Aq;;;rz # Featuresc|dkrdndS)NDFLTrr|rks rz-VoltToFea._buildFeatureFile..sfAARSr)keyaaltr|zvFEA syntax does not allow script statements in 'aalt' feature, so only lookups from the first script will be included.c|dkrdndS)Ndfltrr|rrs rrz-VoltToFea._buildFeatureFile..s1;;aaArzzFEA syntax does not allow language statements in 'aalt' feature, so only lookups from the first language will be included.rTF)include_defaultr BASEMARKLIGATURE COMPONENTGDEF_)r FeatureFilerfrIrCommentrr[rOsorteditemsrKr6rJcopy FeatureBlocklenlogwarningScriptStatementLanguageStatementljustrLookupReferenceStatementrHGlyphClassDefinitionGlyphClassName TableBlockGlyphClassDefStatement)r7rurtrflookupfeatures feature_tagscripts script_taglangs language_tagfeature script_tags language_tagsrr lookuprefclasses classname glyphclassgdefs` r_buildFeatureFilezVoltToFea._buildFeatureFilesqo^   ;   ck*;<< = = =   d07799 : : :   O   ck*<== > > >   NNF43D3J3J3L3L,M,MNNN N N N = *   ck-88 9 9 9-..00 * *!!&.111!!&))))>&&((# L LK{+G% L L  +$)L++++#(#6+++E,'''L&K &K&K&K ##$K$Kgmmoo$K$K$KH[ ! !;;X^^%5%5;;; % +   ck,77 8 8 8(0(8(8# +# +$ W*;77$W2S2STTT &((S-=-=-A-AKKR#.bqb/K"-AAJ"f,,*11#2Ej2Q2QRRR$* +==%%%M#f,,]1C1Ca1G1G X)6bqb(9 (5 A A &&006Bf6L6LddRWO#.55 # 5$0$6$6q$9$94C!"!"!" %,J$7 $EAAD%)]4::<<%@F(+(DV(L(LI#.55i@@@@A A!!'**** : $&F**GA ) )4:%% '$**,, 6I!$!9)TZPTEU!V!VJ%%j111NN3#5j#A#ABBBBNN4((((>&))D O " "3#=w#G H H H   d # # # rcP|j+t|j|_|j}|t}|j|j|_||||| |}| Sr3) rC VoltParserrDparseTABLESrE getGlyphOrderrGrxrasFea)r7rurvrtfeas rconvertzVoltToFea.convert s 9 "4#566<<>>DIi >F : ! $ 8 8 : :D  V-HIII$$V,,yy{{rc |j}n#t$r|}YnwxYwtj|j||Sr3)glyphAttributeErrorr GlyphNamerFget)r7rrs r _glyphNamezVoltToFea._glyphNamesV ;DD   DDD }T_00t<<===  c |j}n#t$r|}YnwxYwtj|j|Sr3)rrrrrIr)r7rrs r _groupNamezVoltToFea._groupNamesU ;DD   DDD !$"4TZZ\\"BCCCrcDfd|DS)Ncg|]:}t|ttjfr|n|;Sr)rstrr$rrr r'r7s rr(z'VoltToFea._glyphSet..'sP   $.a#t~1F#G#G NT__Q   Q   rglyphSet)r7rs` r _glyphSetzVoltToFea._glyphSet&s6    ]]__    rc g}|D]}}t|tjr)|||Ft|tjr)|||t|tjr\||j d}|r| ||tj |t|tj rW||}|r| |G|tj |pt||SNTflatten)rr$rrrr%rEnum _coverager rr GlyphClassRangerrq)r7coveragerrrs rrzVoltToFea._coverage,s[ 0 0D$// 0 T__T223333D$.11 0 T__T223333D$),, 0~~di~>>7LL&&&&LL!5!56666D$*-- 0~~d++7LL&&&&LL!5!56666)$/// rcg}|D]^}||d}t|dkrtj|}n|d}||_|S)NTrr|r)rrrrr)r7contextoutrrs r_contextzVoltToFea._contextCsp ! !D~~dD~99H8}}q  >(33#A; JJx  rc||j}||jjd}t j|}t j||}||j|j<dSr) rarrr rrrrIr)r7rrglyphsrclassdefs rrizVoltToFea._groupDefinitionNspuz** >>^F++ +D*==195:++--...rc |j|j|j|j<n#t$rYnwxYw|jdvrp|j|jvr tj|j|j<|j|jj | |j|jdkr!|j |jdS|jdkr|j|j|j<dSdS)Nrrr)rGidrFr TypeErrortyperHrrrrrrMadd componentsrN)r7rs rrhzVoltToFea._glyphDefinitionUs *.*;EH*EDOEJ ' '    D  :B B Bz++),)9)9 5:& Juz " ) 0 01L1L M M M :   KOOEJ ' ' ' ' ' Z: % %*/*:DOEJ ' ' '& %s " //c\|j}|jD]}|j}|jD]}d|jD}|j}||jvr i|j|<||j|vri|j||<||j||vsJ||j|||<dS)NcFi|]}|dddS)\rT)split)r rs rr!z/VoltToFea._scriptDefinition..js)KKKa1774==+TKKKr)tagrrlookupsrJkeys)r7scriptstaglangltagrrftags rrozVoltToFea._scriptDefinitioneszL B BD8D= B BKK7?KKK{t~--+-DN4(t~d33313DN4(.4>$#7#=====3:<<>>t$T*400 B B Brc|jdr|j|j|j<dS|s$td|jdSdS)N COMPILER_zUnsupported setting ignored: )r startswithvaluerQrr)r7settingignore_unsupporteds rrmzVoltToFea._settingDefinitionssi < " "; / / H+2=DN7< ( ( (# H KKF FF G G G G G H Hrc|\}}}}}}|r|pd}|r|pd} |r|pd} tj|||| | |S)N) xPlacement yPlacementxAdvance xPlaDevice yPlaDevice xAdvDevice)rr ValueRecord) r7 adjustmentadvdxdy adv_adjust_by dx_adjust_by dy_adjust_by adv_device dx_device dy_devices r _adjustmentzVoltToFea._adjustmentysAK>R]L,"<}':':'<'<D  9\%7%7%9%9AT  9\%7%7%9%9AT   !     rc|\}}}}}}|rJ|r|pd}|r|pd} tj|pd|pd|pd| pdS)Nr) xDeviceTable yDeviceTable)rrAnchor) r7rrrrrrrrr s r_anchorzVoltToFea._anchorsAK>R]L,     9\%7%7%9%9AT  9\%7%7%9%9AT z G! G!"*d"*d     rc|j}|j}||j}||jvr i|j|<|dr(|dd|ddz}n|}||j|vri|j||<||j|||j<dS)NMARK_)r glyph_namerrrrPrr component)r7 anchordef anchorname glyphnameanchors rrkzVoltToFea._anchorDefinitions^ ( im,, DM ) )')DM) $   ) ) ,#BQB*QRR.*>*>*@*@@JJ#))++J T]95 5 535DM) $Z 0DJ i ,Y-@AAArc D |j}|j}t|tjr%|jD]\\}}\}}|j|dz } |j|dz } d} | | zD]} t| tj sd}  | } | } |} |}t| dksJt|dksJ| tj| d||d||  dSt|tjr|jD]w\}} |} |}t|dksJ| tj|d|fgggdxdSt|tjri}t)}|jD]t\}}|d|j}tj|}|}t)}|D])}||*||s|||s|||D]U}|}j|d|d}tj |||} | j!||f<V|j"D]K}!|!D]4}"|"|vrg||"<||f||"vr||" ||f5LvtGfd|D}#tGfd |D}$|D].}"d}%|#r j$|"}%d tK|%D}||"D]}\}}tj|}tKd|%dzD]P}&|&j|"|vr9j|"||&}||&dz  ||fQ~|"}!|$rtj&|!|d}n3|#rtj'|!|}ntj(|!|d}| |0dSt|tj)r{g}'|j*D]3}|D].}!|!D]}"|' |"/4g}(|j+D]3}|D].}!|!D]}"|( |"/4|'D]}"|"}j|"d d})d}*|"|(vrAj|"d d}*|(,|(-|"| tj.||)|*|(D]Y}"|"}j|"d d}*| tj.|d|*ZdSt_|) Nr|FTr) enumerated.rc3*K|] }|jvVdSr3)rNr nr7s rr~z(VoltToFea._gposLookup..s*DDqa4?2DDDDDDrc3*K|] }|jvVdSr3)rMrs rr~z(VoltToFea._gposLookup..s*<.s777777rentryexit)0rfrrrr$PositionAdjustPairDefinition adjust_pairr coverages_1 coverages_2r%rr rrrPairPosStatementPositionAdjustSingleDefinition adjust_singleSinglePosStatementPositionAttachDefinitionrL coverage_torar MarkClassrupdater isdisjointdifference_updaterrPMarkClassDefinitionrOrallrNrangeMarkMarkPosStatementMarkLigPosStatementMarkBasePosStatementPositionAttachCursiveDefinitioncoverages_entercoverages_exitpopindexCursivePosStatementrq)+r7r fealookuprfrridx1idx2pos1pos2 coverage_1 coverage_2rrglyphs1glyphs2record1record2abrrecordanchorsallmarksrrr markclassmarksmarkrrrmarkdefbaser is_ligatureis_markrrenter_coverage exit_coverager!r"s+` r _gposLookupzVoltToFea._gposLookups) j c4< = = +.1o.C.C.E.E  * tltT _TAX6  _TAX6 # &3**D%dDN;;*%) ..44..44**400**4007||q((((7||q((((!!( GWQZZ#  ,T@ A Ah +)  1**))!,,6{{a''''!!*VAY,?+@"b%PP   T: ; ;` +GuuH(+& J& J$*!OOz,I,IFK,I,IJJ M)44 (--// $22DLL1111''11!++H555 ! &&&!&HHI OOI66E!]956Jj6J6JKANF!5iOOG@GD%y)&<==LJJD $ JJw..,.GDM& 2'$-GG#DM00*i1HIII JJDDDDGDDDDDK<<<y%IF!)a-0778KLLLM t,,D3D%(CCDD D24??DD3D%(CCD!!$'''') ( (*TA B B +N/ 4 4$44D $ 44&--d333344M. 3 3$33D $ 33%,,T222233 ' O O-- d+G4Q7=((=.v6q9D!%%m&9&9$&?&?@@@!!#"9%"M"MNNNN& N N--}T*6215!!#"9%t"L"LMMMM N N &c** *rc$|j}|j}t|tjr|jD]\\} } \} } ||j| dz } ||j | dz }t| dksJt|dksJ| d|df}|rtj |||fg}ntj |||||g}||dSt|tjrtjg}|jD]5\}}|d||d6|rtj |||fg}ntj ||||g}||dSt|tjrtjg}|jD]5\}}|d||d6|rtj |||fg}ntj ||||g}||dSt+|)Nr|rTr)rfrrrr$r#r$rrr%r&rrIgnorePosStatementChainContextPosStatementrr(rr)rr+r,rq)r7rprefixsuffixignorer=r6rfrrr>r?r@rArDrErrwrHrXrs r_gposContextLookupzVoltToFea._gposContextLookup+s) j c4< = =( +.1o.C.C.E.E - -* tltT..)BCC..)BCC7||q((((7||q((((!!*gaj1 # 68P7Q R RII # <'0B!!I!!),,,, - -T@ A A +n&&'F) B B1q   4!@!@AAAA 2VVV4L3MNN 8FFWI    i ( ( ( ( ( T: ; ; +n&&'F" I I !q   $!G!GHHHH 2VVV4L3MNN 8FFWI    i ( ( ( ( (%c** *rc  |j}|j}t|tjri}|jD]'\}}|r|s/|j\}} } t |d| d| d9 |} |} t| dksJt| d | d D]n\} }|t| gt|o)|D]C\}} t%jg|gt%j| }||DdS|jD]\}}|r|s/|j\}} } t |d| d| d9 |} |} t|tjrVt| dksJt| dksJ|t%j| | ggdt|tjrt|tjrGt| dksJ|t%jg| dg| Ot|tjrst| dksJt%jg| g| dd}t9d| Ddkr t;fd| DsJd| D} fd | D} | d }t|dkr |dgz}t|ksJ|t%jd |tg| |RD]I}fd |D}|t%jg|dd g|d dJ||t?|dS) N:: Ignoring empty substitutionr|rFc3XK|]%}t|V&dSr3rrr&s rr~z(VoltToFea._gsubLookup..s2::aAJJLL))::::::rc3bK|])}t|dfvV*dSr{rbr r'rs rr~z(VoltToFea._gsubLookup..s<KKqs1::<<00QF:KKKKKKrc6g|]}|Srrr&s rr(z)VoltToFea._gsubLookup..s ;;;qajjll;;;rcRg|]#}t|dkr |dgzn|$S)r|r)rrds rr(z)VoltToFea._gsubLookup..s5QQQQSVVq[[!vzzaQQQr# c:g|]}|Sr)rrs rr(z)VoltToFea._gsubLookup..s%!E!E!E$//!"4"4!E!E!Er) rfrZrr$SubstitutionAlternateDefinitionmappingrr9rrrrzipr setdefaultrrrrAlternateSubstStatementrSubstitutionSingleDefinitionSingleSubstStatement+SubstitutionReverseChainingSingleDefinitionSubstitutionMultipleDefinitionMultipleSubstStatementSubstitutionLigatureDefinitionLigatureSubstStatementmaxr2rrq)r7rr=rfrZ alternatesrvalpathlinecolumnr replacements src_glyph repl_glyphrrw replacementzippedrs` @r _gsubLookupzVoltToFea._gsubLookupYs\) j c4? @ @ JK--//  S#),&D$KK4 V V$ V V V V VWWW,,#~~c22 6{{a''''-01I&&((,q/*B*B*D*D..)Iz))#dooi.H.H*I*I2NNUUDOOJ7788(2'7'7'9'9 - -#|7r3>,#?#? !!),,,, F ))++= /= /HC c %(\"dF tRRdRRVRRRSSS^^C((F>>#..L#t@AA6 /6{{a''''<((A----!!,V\2r5QQC!QRR0 /C!DEE- /6{{a''''!!.r6!9b,OOC!DEE( /<((A----6LOU ::6:::::q55KKKKFKKKKKKKK;;F;;;FQQQQ&QQQF#/q/":":"<"  < = = ! M 6;  ;$$T**1-Dzz||4=00"$$T**"/ *(// <<<$++CKv{8J,K,KLLLL M$**,,7 $++C,A,C,CDDD$++CKv{8J,K,KLLL*3DM$**,, ' '  --+I&$++K8881:DM&+++-- . ? &  ' ' D6?4J(K(K L L L~ 1 1G]]7<00F]]7=11F%)99F OOVVV4 5 5 5 1#fn--22R000  4o  z!9::+G   $ $W - - -z%  1111'  111*2  &:)++ 7Z+++ 7   z%  33333'  33333('rr3)F)NF)r;r<r=recompilerYr`r5r^rarxrrrrrrrrirhrormr rrkrVr]rrrsrrrr@r@`s$"*%677#$7884((('''"2"2"2"2HVVVp    >>>DDD   .   :::;;; B B BHHHH        K K KC+C+C+J,+,+,+\]/]/]/~000d]4]4]4]4]4rr@c ddl}ddlm}ddlm}|dt j}|dd|d |d d |d |dddtdd|dddd|ddd| |}||j rdnd|j }d} t|}d|vr.t|djd}nt"d d!Sn#t&$rYnwxYwt)||} ||j} n#t.$r}} |jrt3| jdd"d} d#| d$} | r,| \} }}t"| d%|d%|d&| nt"| Yd} ~ d!Sd} ~ wwxYwt7|jd'5}|| ddddS#1swxYwYdS)(z'Convert MS VOLT to AFDKO feature files.rN)Path) configLoggerzfonttools voltLib.voltToFea) descriptioninputINPUTzinput font/VTP file to process)metavarrhelp featurefileOUTPUTzoutput feature filez-tz--tablerruz:List of tables to write, by default all tables are written)actionchoicesdestrz-qz--quiet store_truezSuppress non-error messages)rrz --tracebackuDon’t catch exceptionsERRORINFO)levelTSIVzutf-8z6"TSIV" table is missing, font was not saved from VOLT?r|r9"z" is not supportedr_z: w)argparsepathlibr fontToolsrArgumentParsermain__doc__ add_argumentr parse_argsquietrrrdatadecodererrorrr@rrurq tracebackgetattrargsopenrwrite)rrrrparseroptionsrTrU converterrer9messageryrzr{feafiles rrrJsQOOO&&&&&&  $ $%4<%F t2R xd9N    I   i 3P l1K%%GL7=<f>>>>=L D l## T>>#DL$5$<$)AE EE(F H  A2HH "II  I __main__r3)rloggingriorgraphlibrfontTools.feaLibrfontTools.ttLibrrfontTools.voltLibr$fontTools.voltLib.parserrr getLoggerrrrr/rr1r@rr;sysr"rrrrs++Z &&&&&& ........))))))999999g566 ! ! !    ? ? ?S_ g 4g 4g 4g 4g 4g 4g 4g 4T????D zJJJ CHTTVVr