L iBdZddlmZmZddlmZddlmZmZgdZ Gdde Z Gdd e Z Gd d Z Gd d e ZGddee ZGddeZGddeZGddeZdZdZGddeZedk(r|edZej3dej5dej7ddd dej9edZej;ddd!d"dej9yy)#afontTools.pens.basePen.py -- Tools and base classes to build pen objects. The Pen Protocol A Pen is a kind of object that standardizes the way how to "draw" outlines: it is a middle man between an outline and a drawing. In other words: it is an abstraction for drawing outlines, making sure that outline objects don't need to know the details about how and where they're being drawn, and that drawings don't need to know the details of how outlines are stored. The most basic pattern is this:: outline.draw(pen) # 'outline' draws itself onto 'pen' Pens can be used to render outlines to the screen, but also to construct new outlines. Eg. an outline object can be both a drawable object (it has a draw() method) as well as a pen itself: you *build* an outline using pen methods. The AbstractPen class defines the Pen protocol. It implements almost nothing (only no-op closePath() and endPath() methods), but is useful for documentation purposes. Subclassing it basically tells the reader: "this class implements the Pen protocol.". An examples of an AbstractPen subclass is :py:class:`fontTools.pens.transformPen.TransformPen`. The BasePen class is a base implementation useful for pens that actually draw (for example a pen renders outlines using a native graphics engine). BasePen contains a lot of base functionality, making it very easy to build a pen that fully conforms to the pen protocol. Note that if you subclass BasePen, you *don't* override moveTo(), lineTo(), etc., but _moveTo(), _lineTo(), etc. See the BasePen doc string for details. Examples of BasePen subclasses are fontTools.pens.boundsPen.BoundsPen and fontTools.pens.cocoaPen.CocoaPen. Coordinates are usually expressed as (x, y) tuples, but generally any sequence of length 2 will do. )TupleDict)LogMixin)DecomposedTransformIdentity) AbstractPenNullPenBasePenPenErrordecomposeSuperBezierSegmentdecomposeQuadraticSegmentceZdZdZy)r z#Represents an error during penning.N__name__ __module__ __qualname____doc__\/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/fontTools/pens/basePen.pyr r 6s-rr c eZdZy)OpenContourErrorN)rrrrrrrr:srrc eZdZdeeefddfdZdeeefddfdZdeeefddfdZdeeefddfdZdd Z dd Z d e d eeeeeeefddfd Z d e d e dee efddfdZy)rptreturnNct)zBegin a new sub path, set the current point to 'pt'. You must end each sub path with a call to pen.closePath() or pen.endPath(). NotImplementedErrorselfrs rmoveTozAbstractPen.moveTo?s "!rct)z4Draw a straight line from the current point to 'pt'.rrs rlineTozAbstractPen.lineToEs!!rpointsct)aDraw a cubic bezier with an arbitrary number of control points. The last point specified is on-curve, all others are off-curve (control) points. If the number of control points is > 2, the segment is split into multiple bezier segments. This works like this: Let n be the number of control points (which is the number of arguments to this call minus 1). If n==2, a plain vanilla cubic bezier is drawn. If n==1, we fall back to a quadratic segment and if n==0 we draw a straight line. It gets interesting when n>2: n-1 PostScript-style cubic segments will be drawn as if it were one curve. See decomposeSuperBezierSegment(). The conversion algorithm used for n>2 is inspired by NURB splines, and is conceptually equivalent to the TrueType "implied points" principle. See also decomposeQuadraticSegment(). rr r$s rcurveTozAbstractPen.curveToIs &"!rct)a\Draw a whole string of quadratic curve segments. The last point specified is on-curve, all others are off-curve points. This method implements TrueType-style curves, breaking up curves using 'implied points': between each two consequtive off-curve points, there is one implied point exactly in the middle between them. See also decomposeQuadraticSegment(). The last argument (normally the on-curve point) may be None. This is to support contours that have NO on-curve points (a rarely seen feature of TrueType outlines). rr&s rqCurveTozAbstractPen.qCurveTo^s "!rcy)zwClose the current sub path. You must call either pen.closePath() or pen.endPath() after each sub path. Nrr s r closePathzAbstractPen.closePatho rcy)zEnd the current sub path, but don't close it. You must call either pen.closePath() or pen.endPath() after each sub path. Nrr+s rendPathzAbstractPen.endPathur-r glyphNametransformationct)aAdd a sub glyph. The 'transformation' argument must be a 6-tuple containing an affine transformation, or a Transform object from the fontTools.misc.transform module. More precisely: it should be a sequence containing 6 numbers. rr r0r1s r addComponentzAbstractPen.addComponent{s "!rlocationct)zAdd a VarComponent sub glyph. The 'transformation' argument must be a DecomposedTransform from the fontTools.misc.transform module, and the 'location' argument must be a dictionary mapping axis tags to their locations. AttributeErrorr r0r1r5s raddVarComponentzAbstractPen.addVarComponents r)rN)rrrrfloatr!r#r'r)r,r/strr4rrr:rrrrr>s"ue|,"" "ue|,"""uUE\2"t"*"eUl 3"""  " "eUE5%FG "  "  , sEz"   rrc@eZdZdZdZdZdZdZdZdZ dZ d Z y ) r zA pen that does nothing.cyNrrs rr!zNullPen.moveTo rcyr?rrs rr#zNullPen.lineTor@rcyr?rr&s rr'zNullPen.curveTor@rcyr?rr&s rr)zNullPen.qCurveTor@rcyr?rr+s rr,zNullPen.closePathr@rcyr?rr+s rr/zNullPen.endPathr@rcyr?rr3s rr4zNullPen.addComponentr@rcyr?rr9s rr:zNullPen.addVarComponentr@rN) rrrrr!r#r'r)r,r/r4r:rrrr r s-"        rr ceZdZdZy) LoggingPenzHA pen with a ``log`` property (see fontTools.misc.loggingTools.LogMixin)NrrrrrIrIsRrrIceZdZdZy)MissingComponentErrorzGIndicates a component pointing to a non-existent glyph in the glyphset.NrrrrrKrKsQrrKc>eZdZdZdZeZdddfd ZdZdZxZ S) DecomposingPena<Implements a 'addComponent' method that decomposes components (i.e. draws them onto self as simple contours). It can also be used as a mixin class (e.g. see ContourRecordingPen). You must override moveTo, lineTo, curveTo and qCurveTo. You may additionally override closePath, endPath and addComponent. By default a warning message is logged when a base glyph is missing; set the class variable ``skipMissingComponents`` to False if you want all instances of a sub-class to raise a :class:`MissingComponentError` exception by default. TNF)skipMissingComponentsreverseFlippedctt| |i|||_||jj n||_||_y)aTakes a 'glyphSet' argument (dict), in which the glyphs that are referenced as components are looked up by their name. If the optional 'reverseFlipped' argument is True, components whose transformation matrix has a negative determinant will be decomposed with a reversed path direction to compensate for the flip. The optional 'skipMissingComponents' argument can be set to True/False to override the homonymous class attribute for a given pen instance. N)superrM__init__glyphSet __class__rNrO)r rSrNrOargskwargsrTs rrRzDecomposingPen.__init__sL$ nd,d=f=  %, NN 0 0& " -rcjddlm} |j|}|}|tk7r |||}|jr(|dd\}}}} || z||zz } | dkrddlm} | |}|j|y#t$r8|js t||jjd|zYywxYw)z=Transform the points of the base glyph and draw it onto self.r) TransformPenN)ReverseContourPenz,glyph '%s' is missing from glyphSet; skipped) fontTools.pens.transformPenrXrSrrO fontTools.pens.reverseContourPenrZdrawKeyErrorrNrKlogwarning) r r0r1rXglyphpenabcddetrZs rr4zDecomposingPen.addComponents< MM),E C)"37"",BQ/ 1a!ea!em7R+C0C JJsO# Y--+I66 HH  KiW X YsA11>B21B2ctr?r7r9s rr:zDecomposingPen.addVarComponentsr) rrrrrNrKrRr4r: __classcell__rTs@rrMrMs- !1 # -62rrMcreZdZdZdfd ZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZxZS)r zBase class for drawing pens. You must override _moveTo, _lineTo and _curveToOne. You may additionally override _closePath, _endPath, addComponent, addVarComponent, and/or _qCurveToOne. You should not override any other methods. c:tt| |d|_yr?)rQr rR_BasePen__currentPoint)r rSrTs rrRzBasePen.__init__s gt%h/"rctr?rrs r_moveTozBasePen._moveTo!!rctr?rrs r_lineTozBasePen._lineTorprctr?r)r pt1pt2pt3s r _curveToOnezBasePen._curveToOnerprcyr?rr+s r _closePathzBasePen._closePathr@rcyr?rr+s r_endPathzBasePen._endPath"r@rc|j\}}|\}}|\}}|d||z zz} |d||z zz} |d||z zz} |d||z zz} |j| | f| | f|y)zThis method implements the basic quadratic curve type. The default implementation delegates the work to the cubic curve function. Optionally override with a native implementation. gUUUUUU?N)rmrw) r rtrupt0xpt0ypt1xpt1ypt2xpt2ymid1xmid1ymid2xmid2ys r _qCurveToOnezBasePen._qCurveToOne%s (( d d d*dTk::*dTk::*dTk::*dTk:: %%=rc|jS)zrReturn the current point. This is not part of the public interface, yet is useful for subclasses. )rmr+s r_getCurrentPointzBasePen._getCurrentPoint5s"""rc2|jd|_yr?)ryrmr+s rr,zBasePen.closePath;s "rc2|jd|_yr?)r{rmr+s rr/zBasePen.endPath?s "rc4|j|||_yr?)rormrs rr!zBasePen.moveToC R rc4|j|||_yr?)rrrmrs rr#zBasePen.lineToGrrcLt|dz }|dk\sJ|dk(r|j||d|_y|dkDr2|j}t|D]\}}}||||||_y|dk(r|j|y|dk(r|j |dyt d)Nrzcan't get there from here)lenrwrmr r)r#AssertionError)r r$nrwrtrurvs rr'zBasePen.curveToKs K!OAv v 6 D  f %"(*D  U**K! # ##!!>:#rr ct|dz }|dkDsJg}|ddd}}}td|dzD]}t|d||z dz}td|D]z}||z } ||dz } ||dz } | d| | d| dz zz| d| | d| dz zzf} || }Ed|d| dzzd|d| dzzf}|j|||f| dd}}}||j||d|df|S) aSplit the SuperBezier described by 'points' into a list of regular bezier segments. The 'points' argument must be a sequence with length 3 or greater, containing (x, y) coordinates. The last point is the destination on-curve point, the rest of the points are off-curve points. The start point should not be supplied. This function returns a list of (pt1, pt2, pt3) tuples, which each specify a regular curveto-style bezier segment. rrNrrrr)rrangeminappend) r$rbezierSegmentsrtrurvi nDivisionsjfactortemp1temp2temps rr r s] F aA q5L5N1ItTcC 1a!e_1Aq1uqy) q*% 1A^F1q5ME1q5MEa6U1Xa%899a6U1Xa%899D{c!ftAw./Aa8H1IJ%%sCo6 $dD#S 11"3r F2J78 rct|dz }|dkDsJg}t|dz D];}||\}}||dz\}}d||zzd||zzf}|j|||f=|j|d|df|S)aSplit the quadratic curve segment described by 'points' into a list of "atomic" quadratic segments. The 'points' argument must be a sequence with length 2 or greater, containing (x, y) coordinates. The last point is the destination on-curve point, the rest of the points are off-curve points. The start point should not be supplied. This function returns a list of (pt1, pt2) tuples, which each specify a plain quadratic bezier segment. rrrrr)rrr) r$r quadSegmentsrrrrr impliedPts rr r s F aA q5L5L 1q5\4ay1ABAF^SAF^4 VAY 23 4 VBZ01 rc(eZdZdZdZdZdZdZy)_TestPenz,Test class that prints PostScript to stdout.c2t|dd|ddy)Nr rz movetoprintrs rroz_TestPen._moveTo 1r!u-.rc2t|dd|ddy)Nrrrz linetorrs rrrz_TestPen._lineTorrcbt|dd|dd|dd|dd|dd|dd y)Nrrrz curvetor)r bcp1bcp2rs rrwz_TestPen._curveToOnes5 AwQa$q'2a5"Q% A rctdy)N closepathrr+s rryz_TestPen._closePaths  krN)rrrrrorrrwryrrrrrs6// rr__main__N)rr)rd)2K)<r)r)rr)rr)rtypingrrfontTools.misc.loggingToolsrfontTools.misc.transformrr__all__ Exceptionr rrr rIr^rKrMr r r rrrbr!r#r'r,r)rrrrs$L0B .y. x UUp k 8 ; RHRHZHV{#n{#| F,w& z 4.CJJvJJxKK(Hf5MMO 4.CLL:x>MMOr