)EjdZddlmZdZdZd=dZdZdZd ZGd d e Z d Z d>dZ d=dZ dZdZdZdZdZdZ d?dZd=dZedkrddlZeejdkr&ddlZejejjddlZejddZ e !dd d!d"#e !d$d%d!dd&'e !d(d)dd*+e !d,d-e"d./e #ejddZ$e$j%re$j&dnd0Z'ee$j%Z%e(d1e(ee%ee%e'Z)e(d2e(e)ee)Z*e(d3e(ee*e%e*ksJe(d4e(ee e%e'e(d5e(eee%e'e$j+rdd6l,m-Z-e-e$j+Z+e+d7j.j/dZ0e0j1Z2e23D]BZ4e2e4Z5e56e5j7j'Z'ee5j%e'e8e5_%Ce$j8dd9l9m:Z:e:e$j+dd:;Z;ne$j8Z;e;r'e(dz"programToString..$s(,,qCFF,,,,,,)join)rs rprogramToStringr#s# 88,,G,,, , ,,rNcd}d}d}d}g}g}t|}|D]} t| ts|| .| dkrQ|Jd||z} |d} | | zdz} || dg|| d<t |} || | zdz z }| }| dkr!|d}t |t usJno|sm| dvrid }| d v}|r|t ||dz}nt |}|r5|d z|z r-|d}|d |gf| d vrV|r|d |f|| gf|d t|gfn|| |fg}|r|d |f|S)u\Takes a T2CharString program list and returns list of commands. Each command is a two-tuple of commandname,arg-list. The commandname might be empty string if no commandname shall be emitted (used for glyph width, hintmask/cntrmask argument, as well as stray arguments at the end of the program (🤷). 'getNumRegions' may be None, or a callable object. It must return the number of regions. 'getNumRegions' takes a single argument, vsindex. It returns the numRegions for the vsindex. The Charstring may or may not start with a width value. If the first non-blend operator has an odd number of arguments, then the first argument is a width, and is popped off. This is complicated with blend operators, as there may be more than one before the first hint or moveto operator, and each one reduces several arguments to just one list argument. We have to sum the number of arguments that are not part of the blend arguments, and all the 'numBlends' values. We could instead have said that by definition, if there is a blend operator, there is no width value, since CFF2 Charstrings don't have width values. I discussed this with Behdad, and we are allowing for an initial width value in this case because developers may assemble a CFF2 charstring from CFF Charstrings, which could have width values. FrblendNvsindex> hstemvstemendcharhmovetohstemhmrmovetovmovetovstemhmcntrmaskhintmaskT>r#r&>r(r)) iterrrr lentyper popnext)r getNumRegions seenWidthOpvsIndex lenBlendStacklastBlendIndexcommandsstackitrnumSourceFonts numBlends numBlendArgslenStackparitynumArgswidths rprogramToCommandsr@'sY,KGMNH E gB88%%%  LL     G   ,,,w!7!77Nb I$~59L%*L=>>%:$;E<-.. !5zzH Y1A5 5M%N  i  BiG==C''''' /5 - $ $ K44F %(#eNOO.D*E*EEe** /GaK61 / ! eW ... , , , -U ,,, OOUBK ( ( ( OOR$r((, - - - - OOUEN + + + %U $$$ Orcg}|D]W}t|tr+|||dB||X|S)Nr)rlistextendr )args token_listargs r_flattenBlendArgsrGspJ## c4  #   c " " "   g & & & &   c " " " " rcg}|D]Y\}}td|Drt|}|||r||Z|S)zqTakes a commands list as returned by programToCommands() and converts it back to a T2CharString program list.c3@K|]}t|tVdSrrrBrrFs rrz$commandsToProgram..,55z#t$$555555r)anyrGrCr )r6roprDs rcommandsToProgramrOszGD 55555 5 5 +$T**Dt   NN2    Nrc#Kt|}||zdkrt|td||D]}||||zVdS)z'Group the list el into groups of size nrN)r-r range)elnlis r_everyNrVsh BA1uzznn 1a^^QUmrc,eZdZedZedZedZedZedZedZ edZ edZ ed Z ed Z ed Zed Zed ZdS)!_GeneralizerDecombinerCommandsMapc#ZKt|dkrt|d|fVdS)Nr*r%r-r rDs rr%z)_GeneralizerDecombinerCommandsMap.rmovetos: t99>>T"" "$rc#jKt|dkrt|d|ddgfVdSNrr%rrZr[s rr#z)_GeneralizerDecombinerCommandsMap.hmovetosB t99>>T"" "47A,''''''rc#jKt|dkrt|dd|dgfVdSr]rZr[s rr&z)_GeneralizerDecombinerCommandsMap.vmovetosB t99>>T"" "1d1g,''''''rc#^K|st|t|dD]}d|fV dS)Nr*rlinetor rVr[s rr`z)_GeneralizerDecombinerCommandsMap.rlinetosS #T"" "D!$$ $ $Dd# # # # # $ $rc#K|st|t|} dt|dgfVddt|gfV+#t$rYdSwxYwNTr`rr r,r0 StopIterationrDr8s rhlinetoz)_GeneralizerDecombinerCommandsMap.hlinetos #T"" " $ZZ  1 488Q-0000 1d2hh-0000 1    DD ,A AAc#K|st|t|} ddt|gfVdt|dgfV+#t$rYdSwxYwrcrdrfs rvlinetoz)_GeneralizerDecombinerCommandsMap.vlinetos #T"" " $ZZ  1 1d2hh-0000 488Q-0000 1    DD rhc#^K|st|t|dD]}d|fV dS)N rrcurvetorar[s rrmz+_GeneralizerDecombinerCommandsMap.rrcurvetosS #T"" "D!$$ & &D% % % % % & &rc#LKt|}|dks |dzdkrt||dzdkr4d|d|d|d|d|ddgfV|dd}t|dD]&}d|dd|d|d|ddgfV'dSNrr*rmrr-r rVrDrTs r hhcurvetoz+_GeneralizerDecombinerCommandsMap.hhcurvetos II q55AEAIIT"" " q5A::a$q'47DGT!Wa PQ Q Q Q8DD!$$ L LDa!T!Wd1gtAw JK K K K K L Lrc #LKt|}|dks |dzdkrt||dzdkr4d|d|d|d|dd|dgfV|dd}t|dD]&}dd|d|d|dd|dgfV'dSrorsrts r vvcurvetoz+_GeneralizerDecombinerCommandsMap.vvcurvetos II q55AEAIIT"" " q5A::a$q'47DGQQ PQ Q Q Q8DD!$$ L LDDGT!Wd1gq$q' JK K K K K L Lrc#~Kt|}|dks|dzdvrt|d}|dzdkr|dzdk}|dd|dd}}t|d} t|}d |d d |d|dd |d gfVt|}d d |d |d|d|d d gfVg#t$rYnwxYw|r\|}|r,d |d d |d|d|d|d gfVdSd d |d |d|d|d |dgfVdSdS Nrp>rrrprrr*rrrTrmrrqr-r rVr0rerDrT last_args lastStraightr8s r hvcurvetoz+_GeneralizerDecombinerCommandsMap.hvcurvetos II q55AE--T"" " q5A::q5A:L"3B3ibcc)D T1    PBxx"T!Waa$q'1d1g$NOOOOBxx"QQa$q'47A$NOOOO  P     D   VD V"T!Waa$q'47DQRG$TUUUUUU"QQa$q'47DQRG$TUUUUUU  V V'A(C CCc#~Kt|}|dks|dzdvrt|d}|dzdkr|dzdk}|dd|dd}}t|d} t|}d d |d |d|d|d d gfVt|}d |d d |d|dd |d gfVg#t$rYnwxYw|r\|}|r,d d |d |d|d|d |dgfVdSd |d d |d|d|d|d gfVdSdSryr|r}s r vhcurvetoz+_GeneralizerDecombinerCommandsMap.vhcurveto s II q55AE--T"" " q5A::q5A:L"3B3ibcc)D T1    PBxx"QQa$q'47A$NOOOOBxx"T!Waa$q'1d1g$NOOOO  P     D   VD V"QQa$q'47DQRG$TUUUUUU"T!Waa$q'47DQRG$TUUUUUU  V Vrc#Kt|}|dks |dzdkrt||dd|dd}}t|dD]}d|fV d|fVdS)Nrzrlr*rmr`rsrDrTr~s r rcurvelinez,_GeneralizerDecombinerCommandsMap.rcurveline%s II q55AEQJJT"" "ss)T"##YiD!$$ & &D% % % % %)$$$$$$rc#Kt|}|dks |dzdkrt||dd|dd}}t|dD]}d|fV d|fVdS)Nrzr*rir`rmrsrs r rlinecurvez,_GeneralizerDecombinerCommandsMap.rlinecurve/s II q55AEQJJT"" "ss)T"##YiD!$$ $ $Dd# # # # #I&&&&&&rN)__name__ __module__ __qualname__ staticmethodr%r#r&r`rgrjrmrurwrrrrrrrXrXs}  \ ((\( ((\( $$\$   \   \ &&\& LL\LLL\LVV\V0VV\V0%%\%''\'''rrXc td|Dr d|D}n|}|d}|dd}t|}||zdz | dzz|kst|d|d|D}||dt} fdtd| D}dt ||D}|S) Nc8g|]}t|tSrrJrKs r z)_convertBlendOpToArgs..?s" 7 7 7cJsD ! ! 7 7 7rcfg|].}t|trt|n|gD]}|/SrrrB_convertBlendOpToArgs)rerUs rrz)_convertBlendOpToArgs..@s^   2.Zs555SC5555rc*g|]}||zSrr)rrU deltaArgs numRegionss rrz)_convertBlendOpToArgs..]s4*+ !a*n$%rrc&g|]\}}||zdgzS)rr)rabs rrz)_convertBlendOpToArgs..`s&FFF$!Q!a%1#+FFFr)rMr-r rQzip) blendListrDr:rT defaultArgsnumDeltaValues deltaList blend_argsrrs @@rrr:s5  7 7Y 7 7 788      RI 9D D Ai!#J a (A - -###55D)$4555KYZZ I^^N/4Q /S/SIGF#k9*E*EFFFJ rFc"g}t}|D]\}}td|DrQ d|D}nC#t$r6|r0|d|f|d|gfnYnwxYwt ||d}||||f ||D]}||#t$r6|r0|d|f|d|gfnYwxYw|S)Nc8g|]}t|tSrrJrKs rrz&generalizeCommands..is"666# 3%%666rcfg|].}t|trt|n|gD]}|/Srr)rrFrSs rrz&generalizeCommands..ks`6@d6K6KV-c222RUQV rr+)rXrMr r getattr)r6 ignoreErrorsresultmappingrNrDfunccommands rgeneralizeCommandsrds F/G""D 66666 7 7  #   MM2t*---MM2t*----.-  wD)) < MM2t* % % %  4:: ' ' g&&&& '     r4j))) rB4j))))*)   Ms! 9=A98A9(#C  =D  D c Rttt||fi|Sr)rOrr@rr1kwargss rgeneralizeProgramr2 ,WmDDOOOO  rc|ds |ds d|ddfSd|ddfS|ds d|ddfSd|fS)a Takes X,Y vector v and returns one of r, h, v, or 0 depending on which of X and/or Y are zero, plus tuple of nonzero ones. If both are zero, it returns a single zero still. >>> _categorizeVector((0,0)) ('0', (0,)) >>> _categorizeVector((1,0)) ('h', (1,)) >>> _categorizeVector((0,2)) ('v', (2,)) >>> _categorizeVector((1,2)) ('r', (1, 2)) rr0Nvhrr)rs r_categorizeVectorrsg Q4 t "1": !"": t "1": 6Mrc6|dkr|S|dkr|S||kr|SdS)Nrrrrs r_mergeCategoriesrs1CxxCxxAvv 4rc2|dkrdS|dkrdS|dvsJ|S)Nrr0rr)rs r_negateCategoryrs0CxxsCxxs 9999 Hrc,t|}d}g}d}||krw||}|dz }t|ts|||dz }n2|}t|dz }|g}|d|zz }||kr}t||trb||ztkrT||||dz }||z }||kr)t||tr||ztkTt|} g} |D]}| |d|D]-}|ddksJ| |dd.| | || || z}||kw|S)Nrrr)r-rrBr rrC) rDnum_args stack_usenew_argsrUrFprev_stack_use num_sources blendlist num_blendsrs r_convertToBlendCmdsrs4yyHIH A h,,1g Q#t$$+ 4 OOC NII&N c((Q,KI [ (IXtAw-- +m;;  a)))Q[( XtAw-- +m;;YJJ  * *!!#a&))))  - -2w!||||!!#ad),,,,   j ) ) ) OOJ ' ' '&3I] h,,` Orct|trt|trtt|t|ks|d|dkrtdt |dd|ddD|dgzS||}}t|tr0|ddksJt |d|g|ddzS||zS)Nrc4g|]\}}t||Sr)_addArgs)rvavbs rrz_addArgs..s&GGGRHR$$GGGrrr)rrBr-r rrrs rrrs!T a   1vvQ1R5AbE>> ll"GG3q"vq"v3F3FGGG1R5'Q QaqA!T+uzzzz1q!!"QqrrU** q5Lrcd}d}|D]I}t|tur,t||t|z}||dz }D|dz }Jt||S)Nrrr)r.rBmax _argsStackUse)rDstackLenmaxLenrFs rrr ssH F 99  M#,>,>!>??F B HH MHH x  rT0c|rt||}nt|}tt|dz ddD]}d||dcxkr||dz dkren-||dz d||d}}dt |d|dt |d|dgf||dz <||=tt|D]}||\}} |dvr%t | \} } | |ddz| f||<6|dkrPt | dd\} } t | d d\} }| | zd z| | dd z|zf||<|stt|dz ddD]}||\}} |d kr;t| d ksJt | dd \} } | dz}|| f||<|dkr||=X|r|dvr|||dz dkrs||dz \}}t| dkrt|dksJ t | d|dg}n#t $rYwxYw||f||dz <||=tdt|dz D]3}||\}} ||dz d||dzd}}|dvrM||cxkrdkr@nn=t| dksJ|ddkr d| dgn | ddg} d| f||<|ddd krt| dkr||cxkrdkrn|ddk|ddkz sJ|ddkrd}n |ddkrd}n|ddkrd }nd}| d|t| dz| |dz} d| f||<35|rt|ddnd}tt|dz ddD]}||dz \}} ||\}}d}||hddhkr1||kr|}nt|}|dkr |dkrd}n|dkrd}n||fdvr|}n||hddhkr|}nd |ddcxkr|ddkrnn|dd\}}|dd\}}|dks|dks||cxkrdkrnnt||}||dkrt||}|d|zd z}nL|dkr*t|t|}|"|dzd z}nt||}|?||zd z}t| }t|t| |z} |r| |kr|| |zf||dz <||=| }|}tt|D]'}||\}} |dvrd|ddz| f||<%|ddd kr|dddvrt| }|dd\}!}|!dk|dkz r |dzdksJ|!d krd}!|d krd}|!dkr|}!|dkrt|!}|!|hddhks J|!|f|dzr]|!|kr1|!dk|d!zdkz r | dd | ddz| d dz} n&|!dkr | dd| ddz| ddz} |!|zd z| f||<')tt|D]:}||\}} td"| Dr|t| f||<;|S)#N)rrrrr%>r`r%rmr*rcurvetorp 00curvetorqlineto0lineto>rgrj>rrgrjr`rrrr)rrlrr>r`rrmrrjrg>r0movetor>hhhvrrvhvvrrzc3@K|]}t|tVdSrrJrKs rrz%specializeCommands..>rLr)rrBrQr-rrr r.rrrrrMr)"r6rgeneralizeFirstpreserveTopologymaxstackrUv1v2rNrDcc1args1c2args2_ other_argsrprvnxtposstackUseop1op2new_oprTd0d1d2d3d args1StackUsecombinedStackUseop0s" rspecializeCommandsrs P"%h\JJJ>>3x==1$a , ,  A < < < <(1q5/!*< < < < < <a!e_Q'!QB"Q%A''"Q%A)?)?@HQUO `3x== ! !  A;D ' ' ''--GAtbf*d*HQK    )$rr(33IB)$rss)44IBr'I-utAaCy/@5/HHHQK  6 s8}}q("b11  A{HB[  4yyA~~~~+D1I664\ $h YQK  R111rXa!e_Q=O7O7O (Q :4yyA~~#j//Q*>*>*>> (a*Q- @ @AHH!H#%x.QQK1c(mma' ( (A;DAE?1%xAq'9S 2 2 2sc7N7N7N7NY7N7N7N7N7Nt99>>>>#%a5C<>cS6O6O6O6OK6O6O6O6O6OqESLRUc\2 2 22!u||A#A#: T 4 0 004:=D&-HQK 2:@}Xb\!_---qH 3x==1$a , ,9%9%a!e_ Ua[ U :)[1 1 1czzJJ+%%!q&&)FF!VV)F3ZS S SFF3ZIy1 1 1FF #abb' , , , ,SW , , , , ,!WFB!WFBSyyB#IIrS R((AySyy$Q++9q9,s%b/!*<*<==:cI-%b"--:a)+&e,, }c%jj8.CDD  %&11%uu}5HQUO 'HH$HH3x== ! !""A;D ' ' '122,,HQK  abb6Y  2bqb61O#O#OD A"1"vHCs scz* "1uzzzzczzczzczzczz%c**:#s+++c3Z+++1u ?#::s q1uz2C#CRCy494tBrE{Bczz#AaCy483d122h>)i/5HQK 3x== ! !88A;D 55555 5 5 81$777HQK Os I** I76I7c Rttt||fi|Sr)rOrr@rs rspecializeProgramrDrr__main__rzfonttools cffLib.specializerz&CFF CharString generalizer/specializer) descriptionrr*z Commands.)metavarnargshelpz --num-regions NumRegionsz5Number of variable-font regions for blend opertaions.)rrdefaultrz--fontFONTFILEzCFF2 font to specialize.)rrrz-oz --output-filezOutput font file name.)r.rcHttj|dn|S)Nr)r options num_regions)r3s rr ss##AAgF""rzProgram:z Commands:zProgram from commands:zGeneralized program:zSpecialized program:)TTFontCFF2)r)makeOutputFileNamez .specialized) overWritesuffixSavingr)F)FTFr)=__doc__fontTools.cffLibrrrr@rGrOrVobjectrXrrrrrrrrrrrrsysr-argvdoctestexittestmodfailedargparseArgumentParserparser add_argumentr parse_argsrrr r1printr6program2fontfontTools.ttLibr cff topDictIndexcff2 CharStrings charstringskeys glyphName charstring decompileprivate output_filefontTools.misc.cliToolsr outfilesaverrrr1se  +*****    ---YYYYx   S'S'S'S'S'S'S'S'l'''T&&&&R 6   777t    ! ! !  kkkk\   zJJJ s38}}"")***OOO $X $&<F  9CkRRR  D   '      %  --GJ"* D "/'/22 j oog&&'''$$Wm<< k h$$X.. &''' ooh''(((("""" $%%% oo//GGHHIII $%%% oo//GGHHIII|******vgl##F|,Q/& $))++  I$Y/J  " " "&.