# class `Canvas`

Canvas is an abstract class representing something that can be drawn upon. It may represent an area of the screen, an offscreen pixmap, or something else such as a printed page.

The drawing model of a Canvas is based on the Postscript drawing model. In this model, drawing is performed by first building up a geometric description of a path, and then stroking the path with a pen or filling the path with a colour, or both. Paths can also be used to define a clipping region to which subsequent drawing is restricted.

The Postscript model is extended with the additional drawing operations:

- Erasing is filling the path with a background colour. On platforms supporting alpha transparency, the background colour completely replaces the colour in the existing image, instead of being blended with it as is the case for the other drawing operations.
- Framing is similar to stroking, except that the pen is moved around the inside of the path instead of being centred on the path. It is equivalent to stroking a path displaced inwards by half the pen size.

Higher-level operations are also provided for convenient drawing of common shapes such as rectangles, ellipses, arcs and polygons.

## Graphics state

Each canvas maintains a graphics state consisting of the following items:

- A pen colour and pen size for stroking and framing operations.
- A fill colour for filling operations.
- A text colour for drawing text.
- A background colour for erasing operations.
- A font for drawing text.
- A current point used in path construction and text drawing.
- A clipping region to which all drawing operations are restricted.

The canvas also maintains a graphics state stack. The current graphics state can be saved by pushing it onto the stack with gsave, and restored by popping it from the stack with grestore.

## Current path

Each canvas has a current path. The current path consists of a collection of path segments, each of which is a sequence of straight lines and/or Bezier curves. Each path segment can be either open or closed. Some operations expect closed path segments, in which case an open segment is treated as though it were closed by a line connecting its last point to its first point.
Paths are constructed using the `newpath`,`moveto`,`lineto`,`rmoveto`,`rlineto`,`curveto`,`rcurveto`,`arc` and `closepath` methods. There are also some higher-level methods for adding commonly-used geometric shapes to the path.
Once constructed, a path can be used in the following ways:

- It can be stroked with the current pen colour and size using the `stroke` method.
- It can be filled with the current fill colour using the `fill` method.
- It can be both filled and stroked using the fill_stroke method.
- It can be erased with the current background colour using the erase method.
- It can be used to restrict the current clipping region (see below) using the `clip` method.

Note that the current path is not part of the state saved on the graphics state stack, and is unaffected by gsave and grestore.

### Overlapping path elements

If the lines and curves making up a path intersect, or the regions they enclose overlap, the region enclosed by the path as a whole is determined using the even-odd winding number rule. Under this rule, the overlapping regions behave as though they were "exclusive-or"ed together. Thus, you can create a region with a hole in it using one segment for the outer boundary and another one for the boundary of the hole.
Note that this only works for segments belonging to a single path. Segments of different paths are independent and do not exclusive-or together.

## Current point

Path construction makes use of the current point. When a line or curve is added to a path, the current point is used as the first point of the element, and the last point of the element becomes the new current point. The current point is also used by certain other operations such as text drawing.
Under certain circumstances, the current point may be undefined. The current point is undefined when a new path has been started using newpath, and after a path segment has been closed using closepath or by calling one of the higher-level methods that adds a closed shape to the path. The current point becomes defined when moveto or rmoveto is called, or a line or curve is added to the path.
Some methods require the current point to be defined. The result of calling these methods when the current point is undefined is platform-dependent.

## Drawing text

Text is drawn using the `show_text` method, which draws a string in the current font and text colour, starting at the current point. The current point is then advanced to the end of the string, ready for drawing another string.

## Drawing Images

Images and Pixmaps can also be drawn on Canvases, using methods provided by those classes. See ImageBase for details.

## Clipping

Each canvas has a clipping region to which all drawing is clipped. The initial clipping region depends on the type of canvas and the circumstances under which it was created. For a canvas passed to a view's `draw` method, it is the region of the view requiring drawing. For a canvas obtained by calling a view's `with_canvas` method, it is the viewed rectangle.
The clipping region can be modified by the clip and rectclip methods, which set the clipping region to the intersection of the current clipping region and a path or rectangle. There is no explicit way of enlarging the clipping region, so modifications to the clipping region should normally be made within a gsave/grestore pair to restore the previous clipping region afterwards.

## Higher-level operations

In addition to the primitive operations making up the drawing model, there are a number of higher-level drawing methods which provide more convenient ways of drawing commonly-used shapes.
The available shapes are:

- Rectangle
- Oval - an ellipse defined by a bounding rectangle.
- Arc - a circular arc defined by a centre point, radius and start and end angles.
- Wedge - a "pie slice" shape consisting of a circular arc together with two radial lines from the centre point to the endpoints of the arc.
- Polyline - a connected sequence of straight lines.
- Polygon - a sequence of straight lines forming a closed polygon.
- Polycurve - an open sequence of connected Bezier curves.
- Loop - a closed sequence of connected Bezier curves.

Note that the Arc, Polyline and Polycurve are considered open shapes, even if the starting and ending points coincide. For corresponding closed shapes, use an Oval, Poly or Loop respectively.
Operations are provided both for adding these shapes to a path, and for drawing them directly without having to construct a path first.

### Summary of Operations

The following matrix of higher-level operations is supported.

| Add to Path | Fill | Stroke | Frame | Fill and Stroke | Fill and Frame | Erase
Path |  | fill | stroke |  | fill_stroke |  |
Rectangle | rect | fill_rect | stroke_rect | frame_rect | fill_stroke_rect | fill_frame_rect | erase_rect
Oval | oval | fill_oval | stroke_oval | frame_oval | fill_stroke_oval | fill_frame_oval | erase_oval
Arc | arc |  | stroke_arc | frame_arc |  |  |
Wedge | wedge | fill_wedge | stroke_wedge |  | fill_stroke_wedge |  | erase_wedge
Polyline | lines |  | stroke_lines |  |  |  |
Polygon | poly | fill_poly | stroke_poly |  | fill_stroke_poly |  | erase_poly
Polycurve | curves |  | stroke_curves |  |  |  |
Loop | loop | fill_loop | stroke_loop |  | fill_stroke_loop |  | erase_loop

Note: There are no filling or erasing operations for Arcs, Polylines and Polycurves because they are open shapes.
Note: There are currently no framing operations for Polygons and Loops because there is no straightforward way of determining an "inwards" direction in which to displace the pen.

## Properties

`pencolor`
  Colour to be used for stroking and framing operations.
fillcolor
  Colour to be used for filling operations.
textcolor
  Colour to be used for drawing text.
`backcolor`
  Colour to be used for erasing operations.
forecolor
  Write-only. Setting this property sets the pen, fill and text colours to the same colour.

`pensize`
  Width of the pen used for stroking and framing.

`font`
  Font to be used in text drawing operations.
current_point
  Read-only. The current point. If the current point is undefined, the result is platform-dependent.
printing
  Read-only. True if the canvas is producing output for a printer or other non-display destination.

## Primitive methods

`newpath()`
  Clears the current path.
`moveto(`x`,` y`)`
  Moves the current point to (x, y). A subsequent call to `lineto`,`rlineto`,`curveto`,`rcurveto` or `arc` will start a new segment of the current path.
`lineto(`x`,` y`)`
  Adds a straight line to the the current path from the current point to (x, y), and then makes (x, y) the current point.
`rmoveto(`dx`,` dy`)`
`rlineto(`dx`,` dy`)`
  The same as `moveto` and `lineto`, except that the coordinates are measured relative to the current point.
curveto(cp1, cp2, ep)
  Adds a Bezier curve to the current path segment starting at the current point, having control points cp1 and cp2, and ending at the point ep. The end point of the curve becomes the new current point.
rcurveto(cp1, cp2, ep)
  The same as curveto except that cp1, cp2 and ep are measured relative to the current point.
`closepath()`
  Closes the last segment of the current path by adding a straight line from its last point to its first point. A subsequent call to `lineto`,`rlineto`,`curveto`,`rcurveto` or `arc` will start a new segment of the current path.

`fill()`
  Fills the interior of the current path with the current fill color. The interior of the path is determined using the even-odd winding number rule.
`stroke()`
  Draws a line along the current path using the current pen size and pen colour. The width of the line is distributed as evenly as possible either side of the path. The treatment of joins between lines is implementation-dependent.
fill_stroke()
  Fills and then strokes the current path.

`erase()`
  Fills the interior of the current path with the current background color.

`show_text(`string`)`
  Draws the given text using the current font and foreground color. The left end of the baseline of the text starts at the current point. After drawing, the current point is advanced rightwards along the baseline by the width of the characters drawn. The effect on the current path is undefined. If the current point is not defined when this method is called, the result is platform-dependent.

`clip()`
  Replaces the current clipping region with the intersection of the current clipping region and the interior of the current path. The interior of the path is determined using the even-odd winding number rule.

`gsave()`
  Pushes the current graphics state onto the graphics state stack.

`grestore()`
  Pops the most recently saved graphics state from the graphics state stack and makes it the current graphics state.
`initgraphics()`
  Sets all the elements of the current graphics state to default values.

## Higher-level path methods

rect(rect)
  Adds a new closed segment to the current path in the shape of a rectangle.
oval(rect)
  Adds a new closed segment to the current path in the shape of an ellipse bounded by the given rectangle.
arc(centre, radius, start_angle, end_angle)
  Adds a circular arc to the current path segment with the given centre and radius. The arc is drawn clockwise from the start angle to the end angle. Both angles are in degrees clockwise from the positive x-axis. If the current point is defined, a straight line is added from the current point to the start point of the arc. The end point of the arc becomes the new current point.
wedge(centre, radius, start_angle, end_angle)
  Adds a new closed segment to the current path in the shape of a wedge. The wedge is defined as for arc.
lines(points)
  Adds a new open segment to the current path consisting of a sequence of straight lines. Equivalent to calling moveto for the first point and then lineto for each subsequent point.
linesto(points)
  Adds a connected sequence of straight lines to the current path segment. Equivalent to calling lineto for each point.
poly(points)
  Adds a new closed segment to the current path in the shape of a polygon.
curves(points)
  Adds a new open segment to the current path consisting of a sequence of connected Bezier curves. Equivalent to calling moveto for the first point and then curveto for each subsequent group of 3 points.
curvesto(points)
  Adds a sequence of connected Bezier curves to the current path segment. Equivalent to calling curveto for each consecutive group of 3 points.
loop(points)
  Adds a new closed segment to the current path consisting of a sequence of connected Bezier curves. Equivalent to calling curves followed by closepath.
`rectclip(`rect`)`
  Replaces the current clipping region with the intersection of the current clipping region and the given rectangle. The effect on the current point and current path are undefined.

## Higher-level drawing methods

Note: The effect of these methods on the current path is undefined.

> `fill_rect(`rect`)
> `
> stroke_rect(rect)`
> frame_rect(`rect`)
> fill_stroke_rect``(`rect`)`
> `fill_frame_rect(`rect`)
> erase_rect``(`rect`)`
>   Performs the indicated operation on the given rectangle.
> `fill_oval(`rect)
> stroke_oval(rect)
> `frame_oval(`rect`)
> `fill_stroke_oval`(`rect)
> fill_frame_oval`(`rect)
> erase_oval`(`rect)
>   Performs the indicated operation on an ellipse bounded by the specified rectangle.
> `stroke_arc`(centre, radius, start_angle, end_angle`)
> `
> `frame_arc`(centre, radius, start_angle, end_angle`)`
>   Performs the indicated operation on a circular arc. The arc is defined as for the arc method.

> `fill_wedge(`centre, radius, start_angle, end_angle`)
> ` `stroke_wedge``(`centre, radius, start_angle, end_angle`)`
> `fill_stroke_wedge(`centre, radius, start_angle, end_angle`)
> ` `erase_wedge``(`centre, radius, start_angle, end_angle`)`
>   Performs the indicated operation on a pie-shaped wedge. The wedge is defined as for the arc method.
> stroke_line `s(`points`)`
>   Strokes a sequence of connected line segments.
> `fill_poly``(`points`)`
> `stroke_poly(`points`)
> ` `fill_stroke_poly``(`points`)`
> `erase_poly``(`points`)`
>   Performs the indicated operation on a closed polygon.
> `fill_loop``(`points`)`
> `stroke_loop(`points`)
> ` `fill_stroke_loop``(`points`)`
> `erase_loop``(`points`)`
>   Performs the indicated operation on a closed sequence of Bezier curves. See loop.

---