L iadZddlmZdZdZd;dZdZdZd ZGd d e Z d Z dddZ e jCdddd !e jCd"d#ddd$%e jCd&d'dd()e jCd*d+e"d,-e jGej2ddZ$e$jJre$jLdnd.Z'ee$jJZ%e(d/e(ee%ee%e'Z)e(d0e(e)ee)Z*e(d1e(ee*e%e*k(sJe(d2e(ee e%e'e(d3e(eee%e'e$jVrdd4l,m-Z-e-e$jVZ+e+d5j\j^dZ0e0jbZ2e2jgD]GZ4e2e4Z5e5jme5jnjNZ'ee5jJe'e6e5_%Ie$jpdd7l9m:Z:e:e$jVdd89Z;n e$jpZ;e;re(d:e;e+jye;yyyy)>aZT2CharString operator specializer and generalizer. PostScript glyph drawing operations can be expressed in multiple different ways. For example, as well as the ``lineto`` operator, there is also a ``hlineto`` operator which draws a horizontal line, removing the need to specify a ``dx`` coordinate, and a ``vlineto`` operator which draws a vertical line, removing the need to specify a ``dy`` coordinate. As well as decompiling :class:`fontTools.misc.psCharStrings.T2CharString` objects into lists of operations, this module allows for conversion between general and specific forms of the operation. ) maxStackLimitct|tr|j}g}|D]} t|}|j |!|S#t$r t |}n#t$rYnwxYwYz"programToString..$s,qCF,s)join)rs rprogramToStringr#s 88,G, ,,Ncd}d}d}d}g}g}t|}|D]@} t| ts|j| &| dk(r@|Jd||z} |d} | | zdz} || dg|| dt |} || | zdz z }| }k| dk(r|d}t |t us\J|sX| dvrTd }| d v}|r|t ||dz}n t |}|r-|d z|z r%|jd}|jd |gf| d vrF|r|jd |f|j| gf|jd t|gfn|j| |fg}C|r|jd |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@'s,KGMNH E gB8%% LL   G  , ,,w!77Nb I$~59L%*L=>%:$;E<-. !5zH Y1A5 5M%N  i BiG=C' ''5 - $ K44F(#eNO.D*EEe*GaK61 ! eW . , ,U , OOUBK ( OOR$r(, - OOUEN +q8r U $ Orcg}|D]F}t|tr#|j||jd6|j|H|S)Nr)rlistextendr )args token_listargs r_flattenBlendArgsrGsRJ# c4   c "   g &   c " # rcg}|D]G\}}td|Dr t|}|j||s7|j|I|S)zqTakes a commands list as returned by programToCommands() and converts it back to a T2CharString program list.c3<K|]}t|tywrrrBrrFs rrz$commandsToProgram..5z#t$5)anyrGrCr )r6roprDs rcommandsToProgramrPsVGD 55 5$T*Dt NN2   Nrc#Kt|}||zdk7r t|td||D] }||||zyw)z'Group the list el into groups of size nrN)r-r range)elnlis r_everyNrWsK BA1uzn 1a^QUms<>ceZdZedZedZedZedZedZedZ edZ edZ ed Z ed Z ed Zed Zed Zy)!_GeneralizerDecombinerCommandsMapc#JKt|dk7r t|d|fyw)Nr*r%r-r rDs rr%z)_GeneralizerDecombinerCommandsMap.rmovetos' t9>T" "$s!#c#TKt|dk7r t|d|ddgfywNrr%rr[r\s rr#z)_GeneralizerDecombinerCommandsMap.hmovetos/ t9>T" "47A,''&(c#TKt|dk7r t|dd|dgfywr^r[r\s rr&z)_GeneralizerDecombinerCommandsMap.vmovetos/ t9>T" "1d1g,''r_c#TK|s t|t|dD]}d|f yw)Nr*rlinetor rWr\s rrbz)_GeneralizerDecombinerCommandsMap.rlinetos5T" "D!$ $Dd# # $r_c#K|s t|t|} dt|dgfddt|gf##t$rYywxYwwNrbrr r,r0 StopIterationrDr8s rhlinetoz)_GeneralizerDecombinerCommandsMap.hlinetoscT" " $Z  48Q-00 1d2h-00   "A$A A  A A  Ac#K|s t|t|} ddt|gfdt|dgf##t$rYywxYwwrerfrhs rvlinetoz)_GeneralizerDecombinerCommandsMap.vlinetoscT" " $Z  1d2h-00 48Q-00   rjc#TK|s t|t|dD]}d|f yw)N rrcurvetorcr\s rroz+_GeneralizerDecombinerCommandsMap.rrcurvetos5T" "D!$ &D% % &r_c#Kt|}|dks|dzdkDr t||dzdk(r d|d|d|d|d|ddgf|dd}t|dD]}d|dd|d|d|ddgfywNrr*rorr-r rWrDrUs r hhcurvetoz+_GeneralizerDecombinerCommandsMap.hhcurvetos I q5AEAIT" " q5A:a$q'47DGT!Wa PQ Q8DD!$ LDa!T!Wd1gtAw JK K LA6A8c #Kt|}|dks|dzdkDr t||dzdk(r d|d|d|d|dd|dgf|dd}t|dD]}dd|d|d|dd|dgfywrqrurvs r vvcurvetoz+_GeneralizerDecombinerCommandsMap.vvcurvetos I q5AEAIT" " q5A:a$q'47DGQQ PQ Q8DD!$ LDDGT!Wd1gq$q' JK K Lrxc#Kt|}|dks|dzdvr t|d}|dzdk(r|dzdk(}|dd|dd}}t|d} t|}d|d d |d|dd |d gft|}dd |d |d|d|d d gfG#t$rYnwxYw|r<|}rd|d d |d|d|d|d gfydd |d |d|d|d |dgfyyw Nrr>rrrrrtr*rrtrorrsr-r rWr0rgrDrU last_args lastStraightr8s r hvcurvetoz+_GeneralizerDecombinerCommandsMap.hvcurvetosW I q5AE-T" " q5A:q5A:L"3Bibc)D T1  Bx"T!Waa$q'1d1g$NOOBx"QQa$q'47A$NOO      D"T!Waa$q'47DQRG$TUU"QQa$q'47DQRG$TUU &A C$AB B"C$!B""AC$c#Kt|}|dks|dzdvr t|d}|dzdk(r|dzdk(}|dd|dd}}t|d} t|}dd |d |d|d|d d gft|}d|d d |d|dd |d gfG#t$rYnwxYw|r<|}rdd |d |d|d|d |dgfyd|d d |d|d|d|d gfyywr|rrs r vhcurvetoz+_GeneralizerDecombinerCommandsMap.vhcurveto sW I q5AE-T" " q5A:q5A:L"3Bibc)D T1  Bx"QQa$q'47A$NOOBx"T!Waa$q'1d1g$NOO      D"QQa$q'47DQRG$TUU"T!Waa$q'47DQRG$TUU rc#Kt|}|dks|dzdk7r t||dd|dd}}t|dD]}d|f d|fyw)Nr}rnr*rorbrurDrUrs r rcurvelinez,_GeneralizerDecombinerCommandsMap.rcurveline%sl I q5AEQJT" "s)T"#YiD!$ &D% % &)$$A Ac#Kt|}|dks|dzdk7r t||dd|dd}}t|dD]}d|f d|fyw)Nr}r*rirbrorurs r rlinecurvez,_GeneralizerDecombinerCommandsMap.rlinecurve/sl I q5AEQJT" "s)T"#YiD!$ $Dd# # $I&&rN)__name__ __module__ __qualname__ staticmethodr%r#r&rbrirlrorwrzrrrrrrrYrYs   (( (( $$     && LLLLVV0VV0%%''rrYc .t|Dcgc]}t|tc}r5|Dcgc]'}t|tr t|n|gD]}|)}}}n|}|d}|dd}t |}||zdz }||dzz|k(s t ||d|Dcgc]}|g}}||d} t | } t d| |Dcgc] }| |||z } }t|| D cgc]\} } | | zdgz}} } |Scc}wcc}}wcc}wcc}wcc} } wNrrr)rNrrB_convertBlendOpToArgsr-r rRzip) blendListrFerVrDr:rU numRegions defaultArgs deltaArgsnumDeltaValues deltaListab blend_argss rrr:sa  Y 7cJsD ! 78 2,B8*B>C88B>>4C54C584D0/D0c @ttt||fi|Sr)rPrr@rr1kwargss rgeneralizeProgramr$ ,WmDOO rcR|ds|dsd|ddfSd|ddfS|dsd|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_categorizeVectorrsR Q4t"1: !": t"1: 6Mrc.|dk(r|S|dk(r|S||k(r|Sy)Nrr)rrs r_mergeCategoriesrs)CxCxAv rc*|dk(ry|dk(ry|dvsJ|S)Nrr0rr)rs r_negateCategoryrs'CxCx 99 Hrct|}d}g}d}||kr.||}|dz }t|ts|j||dz }n|}t|dz }|g}|d|zz }||krbt||trO||ztkrC|j|||dz }||z }||kr t||tr ||ztkrCt|} g} |D]}| j|d|D] }|ddk(sJ| j |dd"| j| |j| || z}||kr.|S)Nrrr)r-rrBr rrC) rDnum_args stack_usenew_argsrVrFprev_stack_use num_sources blendlist num_blendsrs r_convertToBlendCmdsrs4yHIH A h,1g Q#t$ OOC NI&N c(Q,KI [ (IXtAw- +m;  a)Q[( XtAw- +m;YJJ  *!!#a&) *  -2w!|#|!!#a), -   j ) OOJ '&3I] h,` Orct|trvt|trbt|t|k7s |d|dk7r tt |dd|ddDcgc]\}}t ||c}}|dgzS||}}t|tr |ddk(sJt |d|g|ddzS||zScc}}wr)rrBr-r r_addArgs)rrvavbs rrrs!T a 1vQ1R5AbE> l"36q"vq"v3FGRHR$G1R5'Q QaqA!Tuzz1q!"QqrU** q5L Hs"B<cd}d}|D]9}t|tur!t||t|z}||dz }5|dz };t||S)Nrrr)r.rBmax _argsStackUse)rDstackLenmaxLenrFs rrr scH F 9 M#,>!>?F B H MH  x  rTc* |rt||}n t|}tt|dz ddD]b}d||dcxk(r||dz dk(sn!||dz d||d}}dt |d|dt |d|dgf||dz <||=dtt|D]h}||\}} |dvrt | \} } | |ddz| f||<+|dk(s1t | dd\} } t | d d\} }| | zd z| | dd z|zf||<j|stt|dz ddD]}||\}} |d k(r-t| d k(sJt | dd \} } | dz}|| f||<|dk(r||=F|sI|dvsN|||dz dk(s]||dz \}}t| dk(rt|dk(sJ t | d|dg}||f||dz <||=tdt|dz D]}||\}} ||dz d||dzd}}|dvr<||cxk(rdk(r1nn.t| dk(sJ|ddk(rd| dgn| ddg} d| f||<a|ddd k(sjt| dk(sy||cxk(rdk(sn|ddk(|ddk(z sJ|ddk(rd}n|ddk7rd}n |ddk(rd }nd}| d|t| dz| |dz} d| f||<|rt|ddnd}tt|dz ddD]D}||dz \}} ||\}}d}||hddhkr(||k(r|}nt|}|dk(r|dk(rd}n|dk(rd}n||fdvr|}n||hddhk(r|}nd |ddcxk(r|ddk(rnn|dd\}}|dd\}}|dk(s|dk(s||cxk(rdk(rnnt||}||dk(rt||}|d|zd z}n=|dk(r!t|t|}||dzd z}nt||}|||zd z}t| }t|t| |z} |r| |kr|| |zf||dz <||=| }C|}Gtt|D]}||\}} |dvrd|ddz| f||<|ddd k(s&|dddvs.t| }|dd\}!}|!dk(|dk(z r |dzdk(sJ|!d k(rd}!|d k(rd}|!dk(r|}!|dk(r t|!}|!|hddhks J|!|f|dzr;|!|k7r |!dk(|d!zdk(z r(| dd | ddz| d dz} n|!dk(r| dd| ddz| ddz} |!|zd z| f||<tt|D]-}||\}} td"| Ds|t| f||</|S#t $rY]wxYw)#N)rrrrr%>rbr%ror*rcurvetorr 00curvetorslineto0lineto>rirl>rrirlrbrrtr)rrnrr>rbrrorrlri>r0movetor>hhhvrrvhvvrr}c3<K|]}t|tywrrJrKs rrz%specializeCommands..>rLrM)rrBrRr-rrr r.rrrrrNr)"r6rgeneralizeFirstpreserveTopologymaxstackrVv1v2rOrDcc1args1c2args2_ other_argsrprvnxtposstackUseop1op2new_oprUd0d1d2d3d args1StackUsecombinedStackUseop0s" rspecializeCommandsrsP%h\J>3x=1$a ,  A <(1q5/!*< <a!e_Q'!QB"Q%A'"Q%A)?@HQUO n3x= ! A;D ' ''-GAtbf*d*HQK   )$r(3IB)$rs)4IBr'I-utAay/@5/HHHQK  F s8}q("b1 A{HB[ 4yA~%~+D1I64\ $h YQK R11rXa!e_Q=O7O (Q :4yA~#j/Q*>>> (a*Q- @AH$&x.QQK; B1c(ma' (A;DAE?1%xAq'9S 2 2sc7NY7Nt9> !>#%a5CcS6OK6OqESLRUc\2 22!u|A#A#: T 4 004:=D&-HQK /42:}Xb\!_-qH 3x=1$a ,9%a!e_ Ua[ U :)[1 1czJ+%!q&)F!V)F3ZS SF3ZIy1 1F #ab' ,SW ,!WFB!WFBSyB#IrS R(AySy$Q+9q9,s%b/!*<=:cI-%b"-:a)+&e, }c%j8.CD &1%uu}5HQUO 'H$Hs9%x3x= !"A;D ' '12,,HQK  ab6Y 2bq61O#OD A"1vHCs scz*1uz!zczczczcz%c*:#s+ 7c3Z 7+1u#:s q1uz2#CRy494tBr{Bcz#Aay483d12h>)i/5HQK E"J3x= !8A;D 55 51$77HQK8 OS"s;V VVc @ttt||fi|Sr)rPrr@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.rcNttj|dS|S)Nr)r options num_regions)r3s rrss*##AF">EF"rzProgram:z Commands:zProgram from commands:zGeneralized program:zSpecialized program:)TTFontCFF2)r)makeOutputFileNamez .specialized) overWritesuffixSavingr)F)FTF0)=__doc__fontTools.cffLibrrrr@rGrPrWobjectrYrrrrrrrrrrrrsysr-argvdoctestexittestmodfailedargparseArgumentParserparser add_argumentr parse_argsrrrr1printr6program2fontfontTools.ttLibrcff topDictIndexcff2 CharStrings charstringskeys glyphName charstring decompileprivate output_filefontTools.misc.cliToolsroutfilesaverrrr+s9 +  -Yx S'S'l'T&R 6 7t  !  k\   z 388}"))* $X $ $&<F  9CkR  D   '      %  -G""*  "'//2 j og&'$Wm< k h$X. &' oh'((""" $% o/GHI $% o/GHI||*gll#F|,,Q/&& $))+ I$Y/J  "&..<