
    jkec=                        d Z ddlmZmZ ddlmZ ddlmZ g dZ G d de	      Z
 G d d	e
      Z G d
 d      Z G d de      Z G d dee      Z G d de      Z G d de      Z G d de      Zd Zd Z G d de      Zedk(  r| ed      Zej1                  d       ej3                  d       ej5                  ddd d       ej7                           ed      Zej9                  ddd!d"d       ej7                          yy)#a  fontTools.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.
    )TupleDict)LogMixin)DecomposedTransform)AbstractPenNullPenBasePenPenErrordecomposeSuperBezierSegmentdecomposeQuadraticSegmentc                       e Zd ZdZy)r
   z#Represents an error during penning.N__name__
__module____qualname____doc__     8/usr/lib/python3/dist-packages/fontTools/pens/basePen.pyr
   r
   6   s    -r   r
   c                       e Zd Zy)OpenContourErrorN)r   r   r   r   r   r   r   r   :   s    r   r   c            
           e Zd Zdeeef   ddfdZdeeef   ddfdZdeeef   ddfdZdeeef   ddfdZdd	Z	dd
Z
dedeeeeeeef   ddfdZdededeeef   ddfdZy)r   ptreturnNc                     t         )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().
        NotImplementedErrorselfr   s     r   moveTozAbstractPen.moveTo?   s
     "!r   c                     t         )z4Draw a straight line from the current point to 'pt'.r   r   s     r   lineTozAbstractPen.lineToE   s    !!r   pointsc                     t         )a  Draw 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().
        r   r   r#   s     r   curveTozAbstractPen.curveToI   s
    & "!r   c                     t         )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).
        r   r%   s     r   qCurveTozAbstractPen.qCurveTo^   s
     "!r   c                      y)zwClose the current sub path. You must call either pen.closePath()
        or pen.endPath() after each sub path.
        Nr   r   s    r   	closePathzAbstractPen.closePatho        	r   c                      y)zEnd the current sub path, but don't close it. You must call
        either pen.closePath() or pen.endPath() after each sub path.
        Nr   r*   s    r   endPathzAbstractPen.endPathu   r,   r   	glyphNametransformationc                     t         )a  Add 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.
        r   r   r/   r0   s      r   addComponentzAbstractPen.addComponent{   s
     "!r   locationc                     t         )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.
        AttributeErrorr   r/   r0   r4   s       r   addVarComponentzAbstractPen.addVarComponent   s
     r   )r   N)r   r   r   r   floatr    r"   r&   r(   r+   r.   strr3   r   r   r9   r   r   r   r   r   >   s    "ue|, " ""ue|, " ""uUE\2 "t "*"eUl 3 " ""
"
" eUE5%FG
" 
	
" , sEz"	
 
r   r   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)r   zA pen that does nothing.c                      y Nr   r   s     r   r    zNullPen.moveTo       r   c                      y r>   r   r   s     r   r"   zNullPen.lineTo   r?   r   c                      y r>   r   r%   s     r   r&   zNullPen.curveTo   r?   r   c                      y r>   r   r%   s     r   r(   zNullPen.qCurveTo   r?   r   c                      y r>   r   r*   s    r   r+   zNullPen.closePath   r?   r   c                      y r>   r   r*   s    r   r.   zNullPen.endPath   r?   r   c                      y r>   r   r2   s      r   r3   zNullPen.addComponent   r?   r   c                      y r>   r   r8   s       r   r9   zNullPen.addVarComponent   r?   r   N)r   r   r   r   r    r"   r&   r(   r+   r.   r3   r9   r   r   r   r   r      s-    "r   r   c                       e Zd ZdZy)
LoggingPenzHA pen with a ``log`` property (see fontTools.misc.loggingTools.LogMixin)Nr   r   r   r   rH   rH      s    Rr   rH   c                       e Zd ZdZy)MissingComponentErrorzGIndicates a component pointing to a non-existent glyph in the glyphset.Nr   r   r   r   rJ   rJ      s    Qr   rJ   c                   2     e Zd ZdZdZ fdZd Zd Z xZ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
    to raise a :class:`MissingComponentError` exception.
    Tc                 8    t         t        |           || _        y)zTakes a single 'glyphSet' argument (dict), in which the glyphs
        that are referenced as components are looked up by their name.
        N)superrL   __init__glyphSetr   rP   	__class__s     r   rO   zDecomposingPen.__init__   s     	nd,. r   c                     ddl m} 	 | j                  |   } || |      }|j                  |       y# t        $ r8 | j
                  st        |      | j                  j                  d|z         Y yw xY w)z=Transform the points of the base glyph and draw it onto self.r   )TransformPenz,glyph '%s' is missing from glyphSet; skippedN)	fontTools.pens.transformPenrT   rP   drawKeyErrorskipMissingComponentsrJ   logwarning)r   r/   r0   rT   glyphtPens         r   r3   zDecomposingPen.addComponent   sq    <	MM),E  n5DJJt  	Y--+I66HHKiWX	Ys   2 >A32A3c                     t         r>   r6   r8   s       r   r9   zDecomposingPen.addVarComponent   s    r   )	r   r   r   r   rX   rO   r3   r9   __classcell__rR   s   @r   rL   rL      s    
 !!r   rL   c                   r     e Zd ZdZd fd	Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Z xZS )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                 :    t         t        |   |       d | _        y r>   )rN   r	   rO   _BasePen__currentPointrQ   s     r   rO   zBasePen.__init__   s    gt%h/"r   c                     t         r>   r   r   s     r   _moveTozBasePen._moveTo       !!r   c                     t         r>   r   r   s     r   _lineTozBasePen._lineTo   re   r   c                     t         r>   r   )r   pt1pt2pt3s       r   _curveToOnezBasePen._curveToOne   re   r   c                      y r>   r   r*   s    r   
_closePathzBasePen._closePath   r?   r   c                      y r>   r   r*   s    r   _endPathzBasePen._endPath  r?   r   c                     | j                   \  }}|\  }}|\  }}|d||z
  z  z   }	|d||z
  z  z   }
|d||z
  z  z   }|d||z
  z  z   }| 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)rb   rl   )r   ri   rj   pt0xpt0ypt1xpt1ypt2xpt2ymid1xmid1ymid2xmid2ys                r   _qCurveToOnezBasePen._qCurveToOne  s    
 ((
d
d
d*dTk::*dTk::*dTk::*dTk::%%=r   c                     | j                   S )zrReturn the current point. This is not part of the public
        interface, yet is useful for subclasses.
        )rb   r*   s    r   _getCurrentPointzBasePen._getCurrentPoint  s     """r   c                 2    | j                          d | _        y r>   )rn   rb   r*   s    r   r+   zBasePen.closePath  s    "r   c                 2    | j                          d | _        y r>   )rp   rb   r*   s    r   r.   zBasePen.endPath   s    "r   c                 4    | j                  |       || _        y r>   )rd   rb   r   s     r   r    zBasePen.moveTo$      R r   c                 4    | j                  |       || _        y r>   )rg   rb   r   s     r   r"   zBasePen.lineTo(  r   r   c                 L   t        |      dz
  }|dk\  sJ |dk(  r | j                  |  |d   | _        y |dkD  r2| j                  }t        |      D ]  \  }}} ||||       || _         y |dk(  r | j                  |  y |dk(  r| j                  |d          y t        d      )N   r      zcan't get there from here)lenrl   rb   r   r(   r"   AssertionError)r   r#   nrl   ri   rj   rk   s          r   r&   zBasePen.curveTo,  s    K!OAvv6
 Df%"(*DU **K!<V!D *S#Cc*&)#* !VDMM6"!VKKq	" !<==r   c                 L   t        |      dz
  }|dk\  sJ |d   A|d   \  }}|d   \  }}d||z   z  d||z   z  f}|| _        | j                  |       |d d |fz   }|dkD  r0| j                  }t	        |      D ]  \  }	}
 ||	|
       |
| _         y | j                  |d          y )Nr   r   r         ?)r   rb   rd   r|   r   r"   )r   r#   r   xynxnyimpliedStartPointr|   ri   rj   s              r   r(   zBasePen.qCurveToI  s    K!OAvv": ":DAqAYFB!$BB @"3DLL*+CR[$5#77Fq5
  ,,L5f= *SS#&&)#* KKq	"r   r>   )r   r   r   r   rO   rd   rg   rl   rn   rp   r|   r~   r+   r.   r    r"   r&   r(   r^   r_   s   @r   r	   r	      sN    #"""
> ###!!>:#r   r	   c                    t        |       dz
  }|dkD  sJ g }| d   dd}}}t        d|dz         D ]  }t        |d||z
  dz         }t        d|      D ]z  }||z  }	| |dz
     }
| |dz
     }|d   |	|
d   |d   z
  z  z   |d   |	|
d   |d   z
  z  z   f}||}Ed|d   |d   z   z  d|d   |d   z   z  f}|j                  |||f       |dd}}}|  |j                  || d   | d   f       |S )	a  Split 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.
    r   r   Nr      r   r   r   )r   rangeminappend)r#   r   bezierSegmentsri   rj   rk   i
nDivisionsjfactortemp1temp2temps                r   r   r   f  s]    	FaAq5L5N1ItTcC1a!e_ 1Aq1uqy)
q*% 	1A^F1q5ME1q5MEa6U1Xa%899a6U1Xa%899D {c!ftAw./Aa8H1IJ%%sCo6 $dD#S	11" 3r
F2J78r   c                     t        |       dz
  }|dkD  sJ g }t        |dz
        D ];  }| |   \  }}| |dz      \  }}d||z   z  d||z   z  f}|j                  | |   |f       = |j                  | d   | d   f       |S )a  Split 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.
    r   r   r   r   r   )r   r   r   )	r#   r   quadSegmentsr   r   r   r   r   	impliedPts	            r   r   r     s     	FaAq5L5L1q5\ 4ay1ABAF^SAF^4	VAY	23	4
 VBZ01r   c                   (    e Zd ZdZd Zd Zd Zd Zy)_TestPenz,Test class that prints PostScript to stdout.c                 2    t        |d   d|d   d       y )Nr    r   z movetoprintr   s     r   rd   z_TestPen._moveTo      1r!u-.r   c                 2    t        |d   d|d   d       y )Nr   r   r   z linetor   r   s     r   rg   z_TestPen._lineTo  r   r   c                 b    t        |d   d|d   d|d   d|d   d|d   d|d   d       y )Nr   r   r   z curvetor   )r   bcp1bcp2r   s       r   rl   z_TestPen._curveToOne  s5    AwQa$q'2a5"Q%A	
r   c                     t        d       y )N	closepathr   r*   s    r   rn   z_TestPen._closePath  s
    kr   N)r   r   r   r   rd   rg   rl   rn   r   r   r   r   r     s    6//
r   r   __main__N)r   r   )r   d   )2   K   )<   r   )r      )r   r   )r   r   )r   typingr   r   fontTools.misc.loggingToolsr   fontTools.misc.transformr   __all__	Exceptionr
   r   r   r   rH   rW   rJ   rL   r	   r   r   r   r   penr    r"   r&   r+   r(   r   r   r   <module>r      s  $L  0 8.y .	x 	U Upk :	; 	RH R'Z 'T|#n |#~ F,w & z
4.CJJvJJxKK(Hf5MMO
4.CLL:x>MMO r   