L iŎ$dZddlZddlZddlmZddlmZddlmZddl m Z m Z ddl mZ ddlmZej"dZgd Zd Zd ZGd d ej,ZGddZddZedk(rddlZej8eyy)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)GDEFGSUBGPOScg}t|ttfr#|D]}|jt ||St |dr&|jt |j |S|j||S)Nenum) isinstancetuplelistextend_flatten_grouphasattrr append)groupretitems a/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/fontTools/voltLib/voltToFea.pyrr=sw C%%' -D JJ~d+ , - J   >%**-. J 5 Jc |Dcic]}|jj|}}|Dcic]f}|jjt|Dcgc]6}t|tj r|j j8c}h}}}t|}|jDcgc]}|| c}Scc}wcc}wcc}}wcc}wN) namelowerrrVAst GroupNamerr static_order)groupsr group_mapxgraphsorterrs r sort_groupsr&Ls8>?u!!#U*?I?     #E* !T^^, GGMMO   E u %F(.(;(;(= >IdO >>@   ?s""C+C;C C9 C Cc eZdZdfd ZxZS)Lookupc6t||||g|_yr)super__init__chained)selfr use_extensionlocation __class__s rr+zLookup.__init__[s }h7 r)FN)__name__ __module__ __qualname__r+ __classcell__)r0s@rr(r(Zs rr(ceZdZejdZejdZddZdZdZ ddZ dZ dd Z d Z d Zd Zdd ZdZdZdZdZddZdZdZdZdZdZdZdZdZy) VoltToFeaz[^A-Za-z_0-9.]z[^A-Za-z_0-9.\-]NcJt|tjr|dc|_|_nd|c|_|_||_i|_d|_i|_i|_ i|_ i|_ t|_ i|_i|_i|_i|_i|_i|_yr)rrVoltFile_doc _file_or_path_font _glyph_map _glyph_order_gdef _glyphclasses _features_lookupsset_marks _ligatures _markclasses_anchors _settings _lookup_names _class_names)r- file_or_pathfonts rr+zVoltToFea.__init__ds lDMM 2,8$ )DIt),0, )DIt)    e  rc||jvri|jjd|}||jjvr"|dz }||jjvr"||j|<|j|SN_)rH_NOT_LOOKUP_NAME_REsubvaluesr-rress r _lookupNamezVoltToFea._lookupName~s t)) )**..sD9C++2244s ++2244'*D  t $!!$''rc||jvri|jjd|}||jjvr"|dz }||jjvr"||j|<|j|SrM)rI_NOT_CLASS_NAME_RErPrQrRs r _classNamezVoltToFea._classNames t(( ())--c48C**1133s **1133&)D  d #  &&rc|jD].}t|tjs|j |0|jDcgc]}t|tj s|!}}t |D]}|j||jD]}t|tjrd|vs"|j|4t|tjr|j||at|tjtj frt|tjr|j|t|tjrt||jD]P}t|tjs|j rd|vr/|j"rd|vr@|j%|Rycc}w)Nr r ) statementsrrGlyphDefinition_glyphDefinitionGroupDefinitionr&_groupDefinitionAnchorDefinition_anchorDefinitionSettingDefinition_settingDefinitionScriptDefinition_scriptDefinitionLookupDefinitionNotImplementedErrorposrP_lookupDefinition)r-doctablesignore_unsupported_settings statementsr!rs r_collectStatementszVoltToFea._collectStatementss 1I)T%9%9:%%i0 1!^^Sz!T=Q=Q/R!SS ( )E  ! !% ( ) 5I)T%:%:;V#**95It'='=>'' 3NOI(<(R>R'STIt'<'<=&&y1 4+@+@A))44 5 2I)T%:%:;==V6%9==V6%9&&y1  2'Ts G,Gc 8 tj}|j}|jrM|j tj d|j |jj|jr]|j tj d|j dt|jjD|jro|j tj d|jjD].}|j |j|j |0|jj}|D]}||}|D]k}||} | D]5} | | D cgc]!} | j|jvs | #c} | | <7| jD cic] \} } | s | |  c} } ||<m|jD cic] \} } | s | |  c} } ||<|jD cic] \} }|s | | }} }|r|j tj d|jD]\}}tj |}t|d}|dk(r(t#|d kDrt$j'd |dd }|D]"}|dk7r.|jj tj(|t||d }|dk(r(t#|d kDrt$j'd |dd }|D]} |dk7rH| d k(rdnd}|jj tj*| j-d|||| D]O}|j|j}tj.|}|jj |Q%|j ||j0rd|vrg}dD]}||j0vrld|jz}tj2||j0|}|j ||j tj4|}|j dtj6d}|jj tj8||j ||Scc} wcc} } wcc} } wcc}} w)Nz# Glyph classesz # Mark classesc3&K|] }|d ywN).0cs r z.VoltToFea._buildFeatureFile..sNqadNsz # Lookupsz # Featuresc|dk(rdSdS)NDFLTrrqrrks rz-VoltToFea._buildFeatureFile..sfARSr)keyaaltrqzvFEA syntax does not allow script statements in 'aalt' feature, so only lookups from the first script will be included.c|dk(rdSdS)Ndfltrrqrrrxs rrzz-VoltToFea._buildFeatureFile..s1;aArzzFEA syntax does not allow language statements in 'aalt' feature, so only lookups from the first language will be included.r~TF)include_defaultr BASEMARKLIGATURE COMPONENTGDEF_)r FeatureFilerYr?rCommentrrQrEsorteditemsrAr,r@copyr FeatureBlocklenlogwarningScriptStatementLanguageStatementljustLookupReferenceStatementr>GlyphClassDefinitionGlyphClassName TableBlockGlyphClassDefStatement)r-rirhrYlookupfeatures feature_tagscripts script_taglangs language_tagltrlffeature script_tags language_tagsrr lookuprefclasses classname glyphclassgdefs r_buildFeatureFilezVoltToFea._buildFeatureFilesoo^^      ckk*;< =   d00779 :      ckk*<= >   NF43D3D3J3J3L,MN N ==   ckk-8 9--..0 *!!&..1!!&) * >>&&(# LK{+G% L  +$)L#(#6+!'')t}}:T+E,'9> &K1q!t&K #  L7>mmo$KdaQT$KH[ ! L&.^^%5;TQAqD;;    ckk,7 8(0(8# +$ W**;7$W2ST &(S-=-AKKR#.bq/K"-AJ"f,**11#2E2Ej2QR$* +=%M#f,]1Ca1G X)6bq(9 (5 A &&06Bf6LdRWO#..55 # 5 5$0$6$6q$94C!" %,J$7 $EAD%)]]4::<%@F(+(D(DV(LI#..55i@A AA4!!'*G# +J ::&F*GA )4::% '$**, 6I!$!9!9)TZZPTEU!VJ%%j1NN3#5#5j#ABNN4( )>>&)D OO " "3#=#=w#G H   d # {+'L$K;s0!T :T  T $T  TT1 T<TcP|j(t|jj|_|j}|t}|j |j j |_|j||||j|}|jSr) r9 VoltParserr:parseTABLESr; getGlyphOrderr=rmrasFea)r-rirjrhfeas rconvertzVoltToFea.convert s 99 "4#5#56<<>DIii >F :: ! $ 8 8 :D  V-HI$$V,yy{rc |j}tj|jj ||S#t$r|}Y A  A c|jDcgc]5}t|ttjfr|j |n|7c}Scc}wr)glyphSetrstrrrr)r-rr#s r _glyphSetzVoltToFea._glyphSet&sJ]]_ $.a#t~~1F#GT__Q Q N   s:Acg}|D]X}t|tjr!|j|j |?t|tj r!|j|j |zt|tjrV|j|jd}|r|j||jtj|t|tjrL|j|}|r|j|*|jtj|Pt||SNTflatten)rrrrrrrEnum _coverager rr GlyphClassRangerre)r-coveragerrrs rrzVoltToFea._coverage,s 0D$/ T__T23D$..1 T__T23D$)),~~dii~>LL&LL!56D$**-~~d+LL&LL!56)$//% 0& rcg}|D]O}|j|d}t|dkDrtj|}n|d}|j |Q|S)NTrrqr)rrrrr)r-contextoutrrs r_contextzVoltToFea._contextCs^ !D~~dD~9H8}q >>(3#A; JJx  ! rc,|j|j}|j|jjd}t j |}t j ||}||j|jj<yr) rWrrr rrrr?r)r-rrglyphsrclassdefs rr]zVoltToFea._groupDefinitionNskuzz* >^^F+ ++D*=195::++-.rc |j|j|j|j<|j dvr|j |j vr+tj|j |j <|j |j jj|j|j|j dk(r&|jj|jy|j dk(r$|j|j|j<yy#t$rYwxYw)Nrrr)r=idr<r TypeErrortyper>rrrrrrCadd componentsrD)r-rs rr[zVoltToFea._glyphDefinitionUs *.*;*;EHH*EDOOEJJ ' ::B Bzz+),)9 5::& JJuzz " ) ) 0 01L M ::  KKOOEJJ ' ZZ: %*/*:*:DOOEJJ '&   s0D77 EEc|j}|jD]}|j}|jD]}|jDcic]}|j ddd}}|j}||j vri|j |<||j |vri|j ||<||j ||vsJ|j |j |||<ycc}w)N\rT)tagrrlookupssplitr@keys) r-scriptstaglangltagrrrftags rrczVoltToFea._scriptDefinitioneszzLL BD88D== B;B??Ka1774=+T1KK{{t~~-+-DNN4(t~~d3313DNN4(.4>>$#7#====3:<<>t$T*40 B BLsC-c|jjdr$|j|j|j<y|s#tj d|jyy)N COMPILER_zUnsupported setting ignored: )r startswithvaluerGrr)r-settingignore_unsupporteds rrazVoltToFea._settingDefinitionssJ << " "; /+2==DNN7<< (# KK7 ~F G$rc|\}}}}}}|xr|jxsd}|xr|jxsd} |xr|jxsd} tj|||| | |S)N) xPlacement yPlacementxAdvance xPlaDevice yPlaDevice xAdvDevice)rr ValueRecord) r- 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%9AT  9\%7%7%9AT   !   rc|\}}}}}}|rJ|xr|jxsd}|xr|jxsd} tj|xsd|xsd|xsd| xsdS)Nr) xDeviceTable yDeviceTable)rrAnchor) r-rrrrrrrrrs r_anchorzVoltToFea._anchors|AK>R]L,    9\%7%7%9AT  9\%7%7%9AT zz G! G!"*d"*d   rc|j}|j}|j|j}||jvri|j|<|j dr|dd|ddj z}n|j }||j|vri|j||<||j|||j<y)NMARK_)r glyph_namerrfrFrr component)r- anchordef anchorname glyphnameanchors rr_zVoltToFea._anchorDefinitions^^ (( imm, DMM )')DMM) $   )#BQ*QR.*>*>*@@J#))+J T]]95 535DMM) $Z 0DJ i ,Y-@-@Arc \ |j}|j}t|tjr |j j D]\\}}\}}|j|dz } |j|dz } d} | | zD]} t| tjrd} !j| } j| }j|}j|}t| dk(sJt|dk(sJ|jtj| d||d|| yt|tj rt|j"D]d\}}j|}j|}t|dk(sJ|jtj$|d|fgggdfyt|tj&ri}t)}|j*D]X\}}j-|d|j.}tj0|}|j3}t)}|D]!}|j5|j7#|j9|s|j;||s|j5||D]S}j=|}j>|d|d}tj@|||} | jB||f<U|jDD]@}!|!j7D]+}"|"|vrg||"<||f||"vs||"j||f-B[tGfd|D}#tGfd |D}$|D]}"d}%|#rjH|"}%tK|%D&cgc]}&g}}&||"D]q\}}tj0|}tKd|%dzD]E}'|'j>|"|vsj>|"||'}||'dz j||fGsj=|"}!|$rtjL|!|d}n2|#rtjN|!|}ntjP|!|d}|j|yt|tjRrbg}(|jTD]/}|D](}!|!j7D]}"|(j|"*1g})|jVD]/}|D](}!|!j7D]}"|)j|"*1|(D]}"j=|"}j>|"d d}*d}+|"|)vr5j>|"d d}+|)jY|)j[|"|jtj\||*|+|)D]N}"j=|"}j>|"d d}+|jtj\|d|+Pyt_|cc}&w) NrqFTr) enumerated.rc3:K|]}|jvywr)rDrsnr-s rruz(VoltToFea._gposLookup..sDqa4??2Dc3:K|]}|jvywr)rCr s rruz(VoltToFea._gposLookup..sy%IF!)a-0778KLMMt,33D%(CD 224?D33D%(CD!!$') (*TAA BN// 4$4D $ 4&--d344 4M.. 3$3D $ 3%,,T233 3' O- d+G4Q7=(==.v6q9D!%%m&9&9$&?@!!#"9"9%"MN O& N-}}T*6215!!#"9"9%t"LM N &c* *]8s) X)c|j}|j}t|tjr|j j D]\\} } \} } |j|j| dz } |j|j| dz }t| dk(sJt|dk(sJ| d|df}|rtj|||fg}ntj|||||g}|j|yt|tjrtj g}|j"D]*\}}|dj%|j|d,|rtj|||fg}ntj||||g}|j|yt|tj&rtj g}|j(D]*\}}|dj%|j|d,|rtj|||fg}ntj||||g}|j|yt+|)NrqrTr)rYrfrrrrrrrrrrIgnorePosStatementChainContextPosStatementrrrrrrrre)r-rprefixsuffixignorer+r,rYrfr,r-r.r/r2r3rrkr6rNrs r_gposContextLookupzVoltToFea._gposContextLookup+sW)) jj c4<< =.1oo.C.C.E -* tltT..)BC..)BC7|q(((7|q(((!!*gaj1 # 6 68P7Q RI # < <'0B!I!!), -T@@ Ann&'F)) B1q   4!@A B22VVV4L3MN 88FFWI    i ( T:: ;nn&'F" I !q   $!GH I22VVV4L3MN 88FFWI    i (%c* *rc  |j}|j}t|tjrei}|j j D]\}}|r|s/|j\}} } tj|d| d| d9|j|} |j|} t| dk(sJt| dj| djD]V\} }|jt|j!| gj#t|j!|X|j D]A\}} t%j&g|gt%j(| }|j#|Cy|j j D]\}}|r|s/|j\}} } tj|d| d| d:|j|} |j|} t|tj*rIt| dk(sJt| dk(sJ|j#t%j,| | ggdt|tj.rt|tj0r.s:aAJJL):s#%c3XK|]!}t|jdfv#ywrprP)rsr#r s rruz(VoltToFea._gsubLookup..s%Kqs1::<0QF:Ks'*# ) rYrPrrSubstitutionAlternateDefinitionmappingrr/rrrrzipr setdefaultrrrrAlternateSubstStatementrSubstitutionSingleDefinitionSingleSubstStatement+SubstitutionReverseChainingSingleDefinitionSubstitutionMultipleDefinitionMultipleSubstStatementSubstitutionLigatureDefinitionLigatureSubstStatementmaxr rre)r-rr+rYrP alternatesr{valpathlinecolumnr replacements src_glyph repl_glyphrrkr# replacementzippedr s @r _gsubLookupzVoltToFea._gsubLookupYsW)) jj c4?? @JKK--/ S#),&D$KK4&$q8U VW,#~~c2 6{a'''-01I&&(,q/*B*B*D.)Iz))#dooi.H*I2NUUDOOJ78 (2'7'7'9 -#|77r3>>,#? !!),  -  ))+= /HCc%(\\"dF tfAdV1VH4QRS^^C(F>>#.L#t@@A6{a'''<(A---!!,,V\2r5QC!Q!QRC!D!DE6{a'''!!..r6!9b,OC!D!DE<(A---66LOU :6::q5KFKKKK4:;qajjl;F;JPQQSVq[!vza?QFQ#/q/":":"D!E$//!"4!E!E"))66 "F3BKVBZ%%i0)#..{= /F<Q "FsQ=: RRc L|j}|j}t|tjr|j j D]\} } | r| s/|j\} } } tj| d| d| d9|j| }|j| }|jtj||||g|_yt|tjtj tj"tj$fst't)|g}|j j D]Z\} } | r| s/|j\} } } tj| d| d| d9|j+|j| d\t-|dkDrtj.|g}|r)|jtj0|||fgy|jtj2||||gy)NrMrNTrrq)rYrPrrr[rUrr/rrrrr ReverseChainSingleSubstStatementr,rYr\r^rTrerrrrIgnoreSubstStatementChainContextSubstStatement)r-rrHrIrJr+r,rYrPr{rbrcrdrerrfs r_gsubContextLookupzVoltToFea._gsubContextLookups)) jj c4KK LKK--/ S#),&D$KK4&$q8U VW,#~~c2 !!88  !#I   11333344   &d3i0 0 ))+ =HCc%(\\"dF tfAdV1VH4QRS MM$..d.; <  = v;?nnV,-F    c668P7QR S   ..vvvyQ rc J d}d}d}|jdk(r|dz}|js|dz}|js|dz}n]t|jtr|j |j}n'|j |j |j }d}|s||tj|||}d}|jjdrd}d |jvrR|jjd d}|j|jvrut|j!|| }||j"j%||j"j%tj&d |jzn|j|j}|j"j%tj(|j"j%tj&d |jz||j|j<njt|j!|j| }||j"j%|||j|jj<|j*;|j"j%tj&d |j*zg} |j,D]} |j/| j0} |j/| j2} | j4d k(} | j%| | | g| s_t7|j,dk(sx| j%ggdg| rtj8|j!|jd z| }|j:j%||j<|j?||n|j@|jC||| D]L\} } } |j<|jE|| | | ||*|j@7|jG|| | | ||Ny|j<|j?||y|j@|jC||yy)NrRTLrqFCOMPILER_USEEXTENSIONLOOKUPSTr)r.rREXCEPT_CONTEXTz chained)$ direction process_base process_marksrrrmark_glyph_setrLookupFlagStatementrGrrrrrAr(rTrYrrSubtableStatementcommentsrrleftrightex_or_inr LookupBlockr,rPrkrfrDrprK)r-rmark_attachementmark_filteringflags lookupflagsr.rr+contextsrrHrIrJr,s rrgzVoltToFea._lookupDefinitions   u $ QJE"" QJE## QJE ,,c 2#v/C/CD   " " .!__V-B-BCN $0N4N11'K >>  < = M 6;; ;;$$T*1-Dzz|4==0"$$T*"/ *((// <$$++CKKv{{8J,KL MM$**,7 $$++C,A,A,CD$$++CKKv{{8J,KL*3DMM$**, '  -+I&$$++K81:DMM&++++- . ?? &  ' ' D6??4J(K L~~ 1G]]7<<0F]]7==1F%%)99F OOVVV4 5#fnn-2R0 1 oo  z!9:+G    $ $W -zz%  1'  1*2 &::)++ 7ZZ+++ 7  zz%  3'  3(rr)F)NF)r1r2r3recompilerOrVr+rTrWrmrrrrrrrr]r[rcrarrr_rDrKrkrprgrrrrr6r6`s$"**%67#$784('"2HVp >D . :; BH    KC+J,+\]/~0d]4rr6c 4ddl}ddlm}ddlm}|j dt j}|jdd|d |jd d |d |jdddtdd|jdddd|jddd|j|}||jrdnd|j}d} t|}d|vr(t|djj!d}nt"j%d y! t)||} |j+|j,} t7|j8d'5}|j;| dddy#t&$rYdwxYw#t.$ru} |j0rt3| j4dd"d} d#| d$} | r'| \} }}t"j%| d%|d%|d&| nt"j%| Yd} ~ y!d} ~ wwxYw#1swYyxYw)(z'Convert MS VOLT to AFDKO feature files.rN)Path) configLoggerzfonttools voltLib.voltToFea) descriptioninputINPUTzinput font/VTP file to process)metavarrhelp featurefileOUTPUTzoutput feature filez-tz--tablerriz: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?rqr/"z" is not supportedrMz: w)argparsepathlibr fontToolsrArgumentParsermain__doc__ add_argumentr parse_argsquietrrrdatadecodererrorrr6rrire tracebackgetattrargsopenrwrite)rrrrparseroptionsrJrK converterrer/messagercrdrefeafiles rrrJs>&  $ $%4<<%F t2R xd9N    I   i 3P l1K%G7==f>==L D l# T>#DL$5$5$<$2F #H> F  F  H A+HH H__main__r)rloggingriorgraphlibrfontTools.feaLibrfontTools.ttLibrrfontTools.voltLibrfontTools.voltLib.parserrr getLoggerrrrr&rr(r6rr1sysrrrrrrs+Z & .)9g56 !  ?S__ g 4g 4T?D z CHHTVr