)Ej4dZddlZddlmZddlmZddlmZddlm Z ddl m Z m Z m Z mZmZd d gZd Zd ZejeZeZd ZdZdZdZGddeZdZdZddZddZ ddZ ddZ!dZ"dZ#dS) aConverts cubic bezier curves to quadratic splines. Conversion is performed such that the quadratic splines keep the same end-curve tangents as the original cubics. The approach is iterative, increasing the number of segments for a spline until the error gets below a bound. Respective curves from multiple fonts will be converted at once to ensure that the resulting splines are interpolation-compatible. N) AbstractPen)PointToSegmentPen)ReverseContourPen)curves_to_quadratic)UnequalZipLengthsErrorIncompatibleSegmentNumberErrorIncompatibleSegmentTypesErrorIncompatibleGlyphsErrorIncompatibleFontsErrorfonts_to_quadraticfont_to_quadraticgMbP?z&com.github.googlei18n.cu2qu.curve_typecttd|Ddkr t|tt |S)zyEnsure each argument to zip has the same length. Also make sure a list is returned for python 2/3 compatibility. c34K|]}t|VdSNlen).0as EC:\PYTHON\MyICR_Suite\python\Lib\site-packages\fontTools/cu2qu/ufo.py zzip..<s($$!s1vv$$$$$$r)rsetrlist_zip)argss rzipr7sK  3$$t$$$ $ $%%**$d++ d  rc6|dkrt|ddS)Nrz must be greater than zero) ValueError)valuenames r_validate_positive_tolerancer"As) zzD<<<===zrc0|D]}t||dSr)r")valuesr!r s r_validate_positive_tolerancesr%Fs.22$UD111122rcPt||krt|ddS)Nz must match the number of inputs)rr)r$expectedr!s r_validate_lengthr(Ks2 6{{hDBBBCCCrcHeZdZdZdZdZdZdZdZdZ dZ d Z d Z d S) GetSegmentsPenzPen to collect segments into lists of points for conversion. Curves always include their initial on-curve point, so some points are duplicated between segments. c"d|_g|_dSr)_last_ptsegmentsselfs r__init__zGetSegmentsPen.__init__Ws  rc`|dvr |d|_|j||fdS)N)movelineqcurvecurve)r,r-append)r/tagrs r _add_segmentzGetSegmentsPen._add_segment[s9 5 5 5 HDM c4[)))))rc2|d|dS)Nr2r9r/pts rmoveTozGetSegmentsPen.moveTo` &"%%%%%rc2|d|dS)Nr3r;r<s rlineTozGetSegmentsPen.lineTocr?rc.|jd|jg|RdS)Nr4r9r,r/pointss rqCurveTozGetSegmentsPen.qCurveTofs'(DM;F;;;;;;rc.|jd|jg|RdS)Nr5rCrDs rcurveTozGetSegmentsPen.curveTois''4=:6::::::rc0|ddS)Ncloser;r.s r closePathzGetSegmentsPen.closePathls '"""""rc0|ddS)Nendr;r.s rendPathzGetSegmentsPen.endPathos %     rcdSr)r/ glyphNametransformations r addComponentzGetSegmentsPen.addComponentrs rN) __name__ __module__ __qualname____doc__r0r9r>rArFrHrKrNrSrPrrr*r*Ps *** &&&&&&<<<;;;###!!!     rr*cxt}t|d}|||jS)z6Get a glyph's segments as extracted by GetSegmentsPen.T)outputImpliedClosingLine)r*r drawPointsr-)glyphpenpointPens r _get_segmentsr^vs?   C!tDDDH X <rc||}|rt|}|D]\}}|dkr |j||dkr |j|'|dkr|j|dd@|dkr|j|ddY|dkr|t|dkr|td |zdS) z=Draw segments as extracted by GetSegmentsPen back to a glyph.r2r3r5rNr4rJrMzUnhandled segment type "%s") clearContoursgetPenrr>rArHrFrKrNAssertionError)r[r-reverse_directionr\r8rs r _set_segmentsrds  ,,..C%$$FF T &== CJ    F]] CJ    G^^ CKabb " " " H__ CL$qrr( # # # G^^ MMOOOO E\\ KKMMMM !>!DEE EFFrTctd|Ds Jdtd|D||}t|dtfd|ddDs Jdtd z }||ddz||<|sd kr d |DSd |DS) z2Return quadratic approximations of cubic segments.c3.K|]}|ddkVdS)rr5NrPrss rrz)_segments_to_quadratic..s*111qtw111111rzNon-cubic given to convertcg|] }|d S)rrPrgs r z*_segments_to_quadratic..s%=%=%=qad%=%=%=rrc3>K|]}t|kVdSrr)rrhns rrz)_segments_to_quadratic..s-33qs1vv{333333rrNzConverted incompatiblycg|]}d|fS)r4rPrps rrjz*_segments_to_quadratic..s222!1 222rcg|]}d|fS)r5rPrps rrjz*_segments_to_quadratic..s111! 111r)allrrstrget)r-max_errstats all_quadratic new_points spline_lengthrls @r_segments_to_quadraticr{s 11111 1 1OO3OOO 1$%=%=H%=%=%=w VVJ JqMA 3333JqrrN333 3 3MM5MMM 3AJJM 99]A66:E-2Q22z222211j1111rcdtD}|sdSfd|Dfd|D tdD}n#t$rtwxYwt |sdS|}g}i} t|D]\} } | ddt fd| dd Dsd | D| | <n$d krt | ||} |s| | krd }| } || |r0t|} t| D]\}} t|| || rt| |S)zDo the actual conversion of a set of compatible glyphs, after arguments have been set up. Empty glyphs (without contours) are ignored and passed through unchanged. Return True if the glyphs were modified, else return False. c>g|]\}}t|dk|Srr)rigs rrjz(_glyphs_to_quadratic..s'GGGtq!CFFQJJJJJrFc g|] }| SrPrP)rrglyphss rrjz(_glyphs_to_quadratic..s 3 3 3AfQi 3 3 3rc g|] }| SrPrP)rrrvs rrjz(_glyphs_to_quadratic..s555awqz555rc,g|]}t|SrP)r^)rrs rrjz(_glyphs_to_quadratic..s $F$F$F!]1%5%5$F$F$Frrc30K|]}|dkVdS)rNrP)rrhr8s rrz'_glyphs_to_quadratic..s+5511Q43;555555rrNcg|] }|d Sr~rPrgs rrjz(_glyphs_to_quadratic..s666qt666rr5T)r-) enumeraterrr anyrsr{r7rdr )rrvrcrwrxnon_empty_indicessegments_by_locationglyphs_modifiednew_segments_by_location incompatiblerr- new_segmentsnew_segments_by_glyphr[r8s`` @r_glyphs_to_quadraticrs HGy'8'8GGG u 3 3 3 3!2 3 3 3F5555#4555G5"$F$Fv$F$F$FG !555,V4445 # $ $u(O!L !566 2 2 8qk!n5555 55555 $66X666LOO G^^1'5-L '  8 8"&#H ''1111B #%= >#&v/D#E#E B B E< %/@ A A A AK+F\JJJJ s AA,Fc|i}| tdz}t|ttfr|}n|gt |z}t |t |dt |dt|||||S)aConvert the curves of a set of compatible of glyphs to quadratic. All curves will be converted to quadratic at once, ensuring interpolation compatibility. If this is not required, calling glyphs_to_quadratic with one glyph at a time may yield slightly more optimized results. Empty glyphs (without contours) are ignored and passed through unchanged. Return True if glyphs were modified, else return False. Raises IncompatibleGlyphsError if glyphs have non-interpolatable outlines. Nirv)DEFAULT_MAX_ERR isinstancertuplerr(r%r)rrvrcrwrx max_errorss rglyphs_to_quadraticrs }!D('D%=))- YV, ZVi888!*i888  -um  rc|rd|D}t|dkrRtt|} | dvrtddS| dkrn| S)aPConvert the curves of a collection of fonts to quadratic. All curves will be converted to quadratic at once, ensuring interpolation compatibility. If this is not required, calling fonts_to_quadratic with one font at a time may yield slightly more optimized results. Empty glyphs (without contours) are ignored and passed through unchanged. Return the set of modified glyph names if any, else return an empty set. By default, cu2qu stores the curve type in the fonts' lib, under a private key "com.github.googlei18n.cu2qu.curve_type", and will not try to convert them again if the curve type is already set to "quadratic". Setting 'remember_curve_type' to False disables this optimization. Raises IncompatibleFontsError if same-named glyphs from different fonts have non-interpolatable outlines. cNh|]"}|jtd#S)cubic)libruCURVE_TYPE_LIB_KEYrfs r z%fonts_to_quadratic..'s)MMM!quyy!3W==MMMrr) quadraticmixedz%Curves already converted to quadraticFrz'fonts may contain different curve typesNz4Only one of max_err and max_err_em can be specified.rv max_err_emc2g|]\}}|jj|zSrPinfo unitsPerEm)rres rrjz&fonts_to_quadratic..Hs&OOO1af'!+OOOrc.g|]}|jjzSrPr)rrrs rrjz&fonts_to_quadratic..Ks#DDDaf'*4DDDrc3>K|]}|VdSr)keysrs rrz%fonts_to_quadratic..Os*661affhh666666rzNew spline lengths: %sz, c32K|]}d||fzVdS)z%s: %dNrP)rlrws rrz%fonts_to_quadratic..fs0JJaQaM1JJJJJJrrr)rnextiterloggerrNotImplementedErrorwarning TypeErrorrrrrr(r%r"rrunionr7raddr errorr sortedrjoinrrur)fontsrrvrcrw dump_statsremember_curve_typerx curve_types curve_typermodified glyph_errorsr!rcur_max_errorsfontrexcspline_lengthsnew_curve_types ` ` rr r s: FMMuMMM {  q d;//00J333 CDDDuw&&)*555    ! ! NND E E E }'"5NOOOgo$ 'D%=)),#e**i888 %j)<<<<  $Wi888YU+ *tUm,,ESZZ>>>%j,???OOE:8N8NOOO  $Z>>>DDDDeDDD uuHL 666667%%uj11 - -KD%t|| d4j)))%%e,,, %#(95- # T"""& % % % LL   !$L       %3$\222 J  -- $yyJJJJ>JJJJJ L   > > >D&8'BBJ,9F[[wN^++/=+, Os=(I&& J0JJc t|gfi|S)zConvenience wrapper around glyphs_to_quadratic, for just one glyph. Return True if the glyph was modified, else return False. )r)r[kwargss rglyph_to_quadraticrrs w 1 1& 1 11rc t|gfi|S)zConvenience wrapper around fonts_to_quadratic, for just one font. Return the set of modified glyph names if any, else return empty set. )r )rrs rrrzs tf / / / //r)T)NFNT)NNFNFTT)$rWloggingfontTools.pens.basePenrfontTools.pens.pointPenr fontTools.pens.reverseContourPenrrerrorsrr r r r __all__rr getLoggerrTrrrr"r%r(r*r^rdr{rrr rrrPrrrs ......555555>>>>>>!!!!!! !4 5 =  8 $ $ >>> 222 DDD # # # # # [# # # L&FFF02222$1111jNRH  ffffR22200000r