Google

Sections:

  1. class Canvas
  2. class Color
  3. class Font
  4. Interactive Callbacks
  5. class StateSaver


Canvas

    piddle.Canvas is the base class for any drawing canvas. Derived classes will implement a particular drawing backend. The general approach to drawing with PIDDLE is as follows:

    1. instantiate a class derived from piddle.Canvas
    2. call drawing methods on that object, such as drawLine or drawString
    3. flush the canvas's buffer (updates the file, screen, or whatever)

    The Canvas methods are shown below. Note that the first parameter (self) is implied, just as it would be when calling such a method on a Canvas instance.

    .isInteractive()

      This method returns 1 if onClick and onOver events are possible, 0 otherwise. Your app can use this to check whether the particular Canvas you're using is interactive (e.g., screen graphics) or not (e.g., drawing to a PostScript file).

    .canUpdate()

      This method returns 1 if the drawing can be meaningfully updated over time (e.g., screen graphics), 0 otherwise (e.g., drawing to a file). Note that for some Canvases, updates might be possible but grow expensive -- for example, each drawing command might be stored in a list, and if you continue to draw for hours, performance will suffer or memory will be exhausted. Such a canvas may return 0.5 for canUpdate(). In that case, your app may want to call .clear() whenever possible, as that should reset things.

    .clear()

      Call this method to clear and reset the Canvas. For screen graphics, the drawing area should be erased; for file Canvases, the file should be emptied or reset to the beginning, or possibly start a new page if the Canvas supports multipage files; and so on. Some types of Canvases may not be able to meaningfully clear(), and may raise an exception if you try.

    .flush()

      Call this method whenever you're done drawing or pausing long enough that you want the drawing to be updated. Screen Canvases will then make sure the screen is up to date; file canvases will flush their file buffers; etc. Some Canvases have no need to flush(), and will simply do nothing, but you should always call this method just to be safe.

    .setInfoLine(s)

    • s: a string to display

      This method applies only to interactive Canvases, and is used to display a string to the user in a non-blocking way. Generally it will appear in a one-line display at the top or bottom of the window or screen. Appropriate uses are showing coordinates, or providing a bit of help or instruction to the user. The string given is not saved and is completely ignored by noninteractive renderers, so it's OK to call this function frequently (e.g., whenever the mouse moves), but don't use it for any information you would want stored to a printout or file.

    .drawLine(x1, y1, x2, y2, [color], [width])

    • x1: horizontal (right) coordinate of the starting point
    • y1: vertical (down) coordinate of the starting point
    • x2: horizontal (right) coordinate of the ending point
    • y2: vertical (down) coordinate of the ending point
    • color: Color of the line to draw; defaults to the Canvas's defaultLineColor
    • width: width of the line to draw; defaults to the Canvas's defaultLineWidth

      This function draws a straight line between the points x1,y1 and x2,y2. Thick lines will be centered on the given coordinates. Line end style varies with the particular canvas, and is more noticable with thick lines.

    .drawLines(lineList, [color], [width])

    • lineList: a list of line coordinates, each an (x1,y1,x2,y2) tuple or list
    • color: Color of the line to draw; defaults to the Canvas's defaultLineColor
    • width: width of the line to draw; defaults to the Canvas's defaultLineWidth

      This function draws a set of lines of uniform color and width. When drawing a large number of lines (e.g., a grid), this function is likely to be more efficient than calling drawLine() for each one. Note that the lines are not joined together; each one is drawn separately. The final result should look the same as if drawLine() had been called for each element of lineList.

    .drawString(s, x, y, [font], [color], [angle])

    • s: the string to draw
    • x: horizontal (right) coordinate of the starting position for the text
    • y: vertical (down) coordinate of the starting position for the text
    • font: font face and style for drawing; defaults to the Canvas's defaultFont
    • color: Color of the drawn text; defaults to the Canvas's defaultLineColor
    • angle: angle (degrees counter-clockwise from +X) at which the text should be drawn; defaults to 0

      This method draws a string. The starting position is the left side of the first character, on the baseline (e.g., the bottom-left pixel in an "m"). Carriage returns ('\n') in the string will cause the drawing "pen" to move to the next line, at the normal single-spaced line spacing for the font. (If you need more control over line spacing, justification, etc., then break the string into lines yourself, measure the strings to be drawn, and draw them in position one line at a time.)

      angle is used to draw rotated text. It should be noted that on some backends, rotated text may be rather slow, but it should always be supported.

    .drawPolygon(pointlist, [edgeColor], [edgeWidth], [fillColor], [closed])

    • pointlist: a list of (x,y) tuples defining the edges of the polygon
    • edgeColor: color of the polygon edges; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the polygon edges; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the polygon interior; defaults to the Canvas's defaultFillColor
    • closed: if 1, adds an extra segment smoothly connecting the first vertex to the last; defaults to 0

      This method draws a polygon, and is a real workhorse; it forms the basis of the default implementations of most other drawing methods. New piddle backends must implement this method, and do so carefully, keeping in mind the following points.

      Filling: we use the "odd-even" rule of filling. As a result, if you make a five-pointed star, the center pentagon is not filled.

      Closure: the filling of a polygon is automatically "closed" in that there will be a straight line of color from the last vertex to the first. The "closed" parameter applies to the edge; if true, then there will also be an edge drawn between those points.

      Users should use the "closed" parameter rather than passing a vertex list with the first and last vertices the same. This allows high-resolution backends (like postscript) to make sure all the edges join together properly.

      Finally, note that when thick edges are drawn, the exact shape of the corners is undefined and may vary from one piddle implementation to another.

    .drawRect(x1, y1, x2, y2, [edgeColor], [edgeWidth], [fillColor], [closed])

    • x1: left side of rectangle to draw
    • y1: top of rectangle to draw
    • x2: right side of rectangle to draw
    • y2: bottom of rectangle to draw
    • edgeColor: color of the rectangle edges; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the rectangle edges; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the rectangle interior; defaults to the Canvas's defaultFillColor

      This function draws a rectangle, aligned with to the coordinate system (i.e., top and bottom are horizontal, sides are vertical). x1 should be less than x2, and y1 should be less than y2. This call is functionally equivalent to:
      	.drawPolygon([(x1,y1),(x2,y1),(x2,y2),(x1,y2)],
      	             edgeColor, edgeWidth, fillColor, closed=1)
      
      But using drawRect is easier to read, and may be considerably faster in some implementations, so its use is recommended whenever possible.

    .drawRoundRect(x1, y1, x2, y2, [rx], [ry], [edgeColor], [edgeWidth], [fillColor], [closed])

    • x1: left side of rectangle to draw
    • y1: top of rectangle to draw
    • x2: right side of rectangle to draw
    • y2: bottom of rectangle to draw
    • rx: horizontal radius of corner ellipse; defaults to 8
    • ry: vertical radius of corner ellipse; defaults to 8
    • edgeColor: color of the roundrect edges; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the roundrect edges; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the roundrect interior; defaults to the Canvas's defaultFillColor

      This function draws a rectangle with rounded corners. The horizontal straight edges stop rx units away from the vertical sides, and the vertical sides stop ry units away from the top and bottom. The gaps are joined with arcs having radii rx and ry.

    .drawEllipse(x1, y1, x2, y2, [edgeColor], [edgeWidth], [fillColor], [closed])

    • x1: leftmost point of ellipse to draw
    • y1: topmost point of ellipse to draw
    • x2: rightmost point of ellipse to draw
    • y2: bottommost point of ellipse to draw
    • edgeColor: color of the ellipse edges; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the ellipse edges; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the ellipse interior; defaults to the Canvas's defaultFillColor

      This functions draws an ellipse inscribed within the rectangle x1,y1, x2,y2. Note that the same restrictions on coordinates which apply to drawRect, also apply to drawRoundRect, drawOval, and drawArc.

    .drawArc(x1, y1, x2, y2, [startAng], [extent], [edgeColor], [edgeWidth], [fillColor], [closed])

    • x1: leftmost point of ellipse to draw
    • y1: topmost point of ellipse to draw
    • x2: rightmost point of ellipse to draw
    • y2: bottommost point of ellipse to draw
    • startAng: angle at which the arc begins; defaults to 0 (zero)
    • extent: angle covered by the arc; defaults to 360
    • edgeColor: color of the arc edge; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the arc edge; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the wedge; defaults to the Canvas's defaultFillColor

      This functions draws part of an ellipse. Angles are given in degrees, where 0 (zero) is to the right at location (x2,(y1+y2)/2), and increase counter-clockwise. When filled, the filled portion is a wedge, like a slice of pie.

    .drawFigure(partList, [edgeColor], [edgeWidth], [fillColor], [closed])

    • partList: list of lines, curves, and arcs (see below)
    • edgeColor: color of the arc edge; defaults to the Canvas's defaultLineColor
    • edgeWidth: width of the arc edge; defaults to the Canvas's defaultLineWidth
    • fillColor: color of the wedge; defaults to the Canvas's defaultFillColor
    • closed: if 1, adds an extra segment smoothly connecting the first vertex to the last; defaults to 0

      This method is used to define a complex figure, much like a polygon, but the sides of which may be arcs or curves. The required parameter partList is a list of tuples, each tuple having one of the following formats:

        (figureLine, x1, y1, x2, y2)
        (figureArc, x1, y1, x2, y2, startAng, extent)
        (figureCurve, x1, y1, x2, y2, x3, y3, x4, y4)

      figureLine, figureArc, and figureCurve are constants defined in piddle.py, and the remaining elements are numerical parameters defining the line, arc, or curve respectively. These elements are joined by straight lines, from the end of one to the start of the next. The resulting figure can be filled like a polygon, or just outlined.

      This method is likely to be slower for screen graphics than separate calls to drawArc, drawCurve, and drawLine (where applicable). On the other hand, drawFigure is likely to produce a higher-quality result for high-resolution renderers such as PostScript and PDF.

    .drawImage(image, x1, y1, [x2], [y2])

    • image: a Python Imaging Library Image object
    • x1: leftmost edge of destination rectangle
    • y1: topmost edge of destination rectangle
    • x2: rightmost edge of destination rectangle (defaults to x1 plus the image width)
    • y2: bottom of destination rectangle (defaults to y1 plus the image height)

      Use this method to plot a pixel image, in the form of a PIL Image object. If you just specify x1 and y1, the image will be drawn with with its top-left corner at that location, without scaling. If you also specify x2 and y2, then the image will be scaled as needed to fit the given rectangle.

      Note that there is no way in piddle to plot a subregion of an image; however, PIL itself provides ways to create a new image as a subregion of an existing one.


Color

    piddle.Color is an encapsulation of the red/green/blue color space, used for specifying all colors in PIDDLE. Member variables red, green, and blue are public and may be safely read or modified.

    You can also use standard arithmatic operators (+, -, *, /) to modify colors; e.g., if you have a color "aqua", then "aqua/2" would be half as intense.

    Colors have a comparison function; two colors are considered equal if their red, green, and blue components are all equal. Otherwise, the colors are ordered first by red, then by green, and finally by blue.

    Colors are hashable. So if, for example, you use a color as a key in a dictionary, another color equal to it will map to the same entry, even if it is a different Color object in memory.

    Colors may be constructed by passing the red, green, and blue values to the constructor, e.g.:

      myColor = Color(1, 0.6, 0)      # light brown
    Alternatively, a factory function called HexColor may be used. This converts a hex string (such as "AABBCC") or an integer (such as 0xAABBCC) into a color. Each byte (in our example, "AA" for red, "BB" for blue, and "CC" for green) is mapped to a color component value between 0 and 1 inclusive. This is the way colors are defined in HTML, and is often a convenient means of specification.

    Color Constants

    PIDDLE defines a large number of color constants, mostly taken from the HTML standard. The predefined color constants are shown in the table below.
    aliceblue
    antiquewhite
    aqua
    aquamarine
    azure
    beige
    bisque
    black
    blanchedalmond
    blue
    blueviolet
    brown
    burlywood
    cadetblue
    chartreuse
    chocolate
    coral
    cornflower
    cornsilk
    crimson
    cyan
    darkblue
    darkcyan
    darkgoldenrod
    darkgray
    darkgreen
    darkkhaki
    darkmagenta
    darkolivegreen
    darkorange
    darkorchid
    darkred
    darksalmon
    darkseagreen
    darkslateblue
    darkslategray
    darkturquoise
    darkviolet
    deeppink
    deepskyblue
    dimgray
    dodgerblue
    firebrick
    floralwhite
    forestgreen
    fuchsia
    gainsboro
    ghostwhite
    gold
    goldenrod
    gray (or grey)
    green
    greenyellow
    honeydew
    hotpink
    indianred
    indigo
    ivory
    khaki
    lavender
    lavenderblush
    lawngreen
    lemonchiffon
    lightblue
    lightcoral
    lightcyan
    lightgoldenrodyellow
    lightgreen
    lightgrey
    lightpink
    lightsalmon
    lightseagreen
    lightskyblue
    lightslategray
    lightsteelblue
    lightyellow
    lime
    limegreen
    linen
    magenta
    maroon
    mediumaquamarine
    mediumblue
    mediumorchid
    mediumpurple
    mediumseagreen
    mediumslateblue
    mediumspringgreen
    mediumturquoise
    mediumvioletred
    midnightblue
    mintcream
    mistyrose
    moccasin
    navajowhite
    navy
    oldlace
    olive
    olivedrab
    orange
    orangered
    orchid
    palegoldenrod
    palegreen
    paleturquoise
    palevioletred
    papayawhip
    peachpuff
    peru
    pink
    plum
    powderblue
    purple
    red
    rosybrown
    royalblue
    saddlebrown
    salmon
    sandybrown
    seagreen
    seashell
    sienna
    silver
    skyblue
    slateblue
    slategray
    snow
    springgreen
    steelblue
    tan
    teal
    thistle
    tomato
    turquoise
    violet
    wheat
    white
    whitesmoke
    yellow
    yellowgreen

    "Transparent"

    There is a special predefined color used to indicate where no drawing should be done. It is called transparent and is defined as Color(-1, -1, -1). Specify this as the fill color for shapes you don't want filled, or the line color for shapes you don't want outlined.


Font

    Font encapsulates a font and font style. It is used to tell PIDDLE what font should be used for drawing text; it does not contain the actual font definition (which is specific to the backend), but only a request for a certain font and style. It contains the following public data members:

    • face: this is a font name (e.g., "helvetica"), or a list of font names (e.g., ["times", "helvetica", "serif"]). When a list is given, PIDDLE will use the first name on the list which matches a font available in the backend. All PIDDLE canvases should support at least the following fonts:
      • times
      • helvetica
      • courier
      • symbol
      • monospaced (often equivalent to courier)
      • serif (often equivalent to times)
      • sansserif (often equivalent to helvetica)

      Thus, it's advisable to always end your list of fonts with one of the six names above, which should always be available.

    • bold: indicates that the font should be drawn in boldface.
    • italic: indicates that the font should be italicized.
    • underline: indicates that the font should be underlined.
    • size: the size of the font, in points; roughly equal to the distance between baselines if two lines of text were drawn such that the descenders of one line touch the tall letters of the next.

    It's important to note that the attributes above are merely requests to the PIDDLE backend. Font handling and capability varies widely among various backends; some options may not be supported.


Interactive Callbacks

    Some PIDDLE canvases may be interactive; that is, they provide support not only for drawing, but also for receiving input from the user. Such interaction takes place through callbacks: functions you define and attach to your canvas, to be called by the canvas whenever an event occurs.

    onClick(canvas, x, y)

    • canvas: the Canvas which was clicked
    • x: the distance between the point clicked and the left side of the canvas
    • y: the distance between the point clicked and the top of the canvas

      This callback is invoked when the user clicks the primary mouse button on the canvas. Your function receives a reference to the canvas clicked, and the x,y coordinates of the location clicked (in canvas coordinates, i.e., the same coordinate system used for drawing).

    onOver(canvas, x, y)

    • canvas: the Canvas the mouse cursor is over
    • x: the distance between the mouse cursor and the left side of the canvas
    • y: the distance between the mouse cursor and the top of the canvas

      This callback is invoked whenever the mouse cursor is moved into or within a Canvas. Your function receives a reference to the canvas the cursor is over, and cursor's x,y coordinates.

    onKey(canvas, key, modifiers)

    • canvas: the Canvas receiving a keypress
    • key: the character of the key pressed
    • modifiers: modifier keys also pressed (see below)

      This callback is invoked when a key is pressed while your canvas is "active" (the exact meaning of which depends on the particulars of the backend and its environment). The key parameter is generally the character of the key pressed; e.g., "a" if the user presses the "a" key. Special keys will be indicated with one of the following constants defined in piddle.py:
      		keyBksp = '\010'		# (erases char to left of cursor)
      		keyDel = '\177'			# (erases char to right of cursor)
      		keyLeft = '\034'		# arrow keys...
      		keyRight = '\035'
      		keyUp = '\036'
      		keyDown = '\037'
      		keyPgUp = '\013'		# page-up
      		keyPgDn = '\014'		# page-down
      		keyHome = '\001'		# "home" (top of document)
      		keyEnd = '\004'			# "end" (bottom of document)
      		keyClear = '\033'		# "clear" (clear all data)
      		keyTab = '\t'			# tab key
      
      Keys which are not printable and not one of the above special cases, (e.g., "F6") may not be reported by the canvas -- certainly, they cannot be reported in a portable manner.

      The modifiers parameter is an integer, and may be any combination of the following two constants:

      		modShift = 1		# shift key was also held
      		modControl = 2		# control key was also held
      
      Note, however, that "shift key" and "control" key may not be literal; certain platforms may need to use other keys ("Alt", "Meta", "Command", etc.) instead. Users of such backends will need to consult the notes which come with that particular Canvas type.

StateSaver

    This is a little utility class for saving and restoring the default drawing parameters of a canvas. To use it, add a line like this before changing any of the parameters:
    		saver = StateSaver(myCanvas)
    
    then, when "saver" goes out of scope, it will automagically restore the drawing parameters of myCanvas.


Last Updated: 16 January 2000