canvas — Vector Graphics

Introduction

The canvas module contains functions for creating non-interactive, 2D vector graphics on iOS. It is suitable for drawing simple graphs/diagrams or line art.

All functions work on a single canvas that is shown in the output area of Pythonista. Images created this way can be exported to the device’s photo library or copied to the clipboard, though it is currently not possible to do this programmatically.

The coordinate system has its origin in the bottom-left corner, coordinates are floats. Colors are generally represented as RGB(A) with components in the range 0.0 - 1.0.

Minimal example that draws a red circle:

#Draw a red circle filling the entire canvas
import canvas
w = h = 512
canvas.set_size(w, h)
canvas.set_fill_color(1, 0, 0)
canvas.fill_ellipse(0, 0, w, h)

Configuring the Canvas

The following functions can be used to configure the overall drawing behavior of the canvas. You typically begin any drawing by calling set_size().

If you want to improve the performance of your drawing, you might want to add a call to begin_updates() before you start drawing, balanced by a call to end_updates() at the end. This will basically avoid showing intermediate results, which speeds things up, but it might also often be helpful to see these intermediate results while working on your drawing code.

canvas.clear()

Clears the canvas. You can also clear the canvas with the set_size() function, which also resets all graphics state (e.g. transformations, fill color, etc.).

canvas.get_size()

Return the size of the canvas as a tuple of width and height.

canvas.set_size(width, height)

Set the size of the canvas (min. 16x16, max. 2048x2048) and reset all graphics state (e.g. transformations, fill color, etc.).

canvas.begin_updates()

Begins a group of drawing operations. Results will not be visible until end_updates() is called. This can significantly improve performance.

canvas.end_updates()

Forces all buffered drawing to be displayed on the screen

(see also begin_updates())

canvas.save_png(filename)

Save the current content of the canvas to a PNG file.

Setting Drawing Parameters

Using these functions affects any drawing operations that follow. For example, calling set_fill_color() with a red color will make any following call to fill_rect() draw a red rectangle, until you set a different color.

canvas.set_aa_enabled(flag)

Enables or disables antialiasing.

canvas.set_alpha(alpha)

Sets the global alpha value.

(see also set_blend_mode())

canvas.set_blend_mode(mode)

Sets the active blend mode. Can be one of the constants listed under Blend Modes.

(see also set_alpha())

canvas.set_fill_color(r, g, b[, a])

Sets the fill color.

canvas.set_line_width(width)

Sets the line width.

(see also set_stroke_color())

canvas.set_stroke_color(r, g, b[, a])

Sets the active stroke color.

(see also set_line_width())

Vector Drawing Functions

The following functions are used for drawing vector paths and shapes.

The canvas always has a current path that can be manipulated with the add_... functions. You can construct arbitrarily complex paths using add_line(), add_curve(), etc. and then fill or stroke the path with fill_path() or draw_path(). If you intend to fill a path, you might want to close it first with close_path().

Filling or drawing a path has the side effect of clearing the current path.

The following example draws a star shape with some configurable parameters:

#Draw a star
import canvas
from math import sin, cos, pi

def draw_star(x, y, inner_r, outer_r, jags):
    canvas.move_to(w / 2, h / 2 + inner_r)
    for i in range(jags * 2):
        angle = (2 * pi / jags) * i / 2
        r = inner_r if i % 2 == 0 else outer_r
        x = w / 2 + r * sin(angle)
        y = h / 2 + r * cos(angle)
        canvas.add_line(x, y)
    canvas.close_path()
    canvas.set_line_width(3)
    canvas.draw_path()

w = h = 600
jags = 7 #Number of jags
inner_r = 120 #Inner radius
outer_r = 250 #Outer radius
canvas.set_size(w, h)
draw_star(w/2, h/2, inner_r, outer_r, jags)
canvas.add_curve(cp1x, cp1y, cp2x, cp2y, x, y)

Adds a cubic bezier curve to (x, y) to the current path, with the control points (cp1x, cp1y) and (cp2x, cp2y).

(see also begin_path(), draw_path(), fill_path())

canvas.add_ellipse(x, y, width, height)

Adds an ellipse to the current path.

(see also begin_path(), draw_path(), fill_path())

canvas.add_line(x, y)

Adds a straight line to the current path.

(see also begin_path(), draw_path(), fill_path(), move_to())

canvas.add_quad_curve(cpx, cpy, x, y)

Adds a quadratic bezier curve to (x, y) to the current path with (cpx, cpy) as the control point.

(see also begin_path(), draw_path(), fill_path())

canvas.add_rect(x, y, width, height)

Adds a rectangle to the current path.

(see also begin_path(), draw_path(), fill_path())

canvas.begin_path()

Begins a new path. Use add_line(), add_rect(), etc. to add shapes to this path and draw_path() or fill_path() to make it visible.

canvas.clip()

Clips subsequent drawing to the current path.

(see also begin_path())

canvas.close_path()

Closes the current path.

(see also begin_path(), draw_path(), fill_path())

canvas.draw_ellipse(x, y, width, height)

Draws an ellipse in a rectangle

(see also set_stroke_color(), set_line_width())

canvas.draw_line(x1, y1, x2, y2)

Draws a line between two points

(see also set_stroke_color(), set_line_width())

canvas.draw_path()

Draws the outline of the current path with the active line width and color.

(see also begin_path(), fill_path(), set_stroke_color(), set_line_width())

canvas.draw_rect(x, y, width, height)

Draws the outline of a rectangle

(see also set_stroke_color(), set_line_width())

canvas.fill_ellipse(x, y, width, height)

Fills an ellipse in a rectangle

(see also draw_ellipse())

canvas.fill_path()

Fills the current path with the active fill color.

(see also begin_path(), draw_path(), set_fill_color())

canvas.fill_pixel(x, y)

Fills a pixel with the current fill color

canvas.fill_rect(x, y, width, height)

Fills a rectangle

canvas.move_to(x, y)

Moves the “pen” to a given point.

(see also add_line())

Transforms

Using the following transformation functions, you can manipulate the current transformation matrix (CTM) of your canvas. This can for example be used to draw rotated or scaled shapes. When you transform the canvas, you’re essentially changing the coordinate system which affects all drawing that follows this change.

It is often useful to be apply a transformation only temporarily. This can be done with the save_gstate() and restore_gstate() functions. save_gstate() takes a snapshot of the current transformation (and other graphics state parameters, such as fill color) and puts it on a stack. Calling restore_gstate() afterwards restores the last state that was put on the stack.

In case you want to completely reset any transformations, but you didn’t save the graphics state, you can use the set_size() function.

The following example draws a clock face with rotated labels:

# Draw a clock face
import canvas
from math import pi

canvas.set_size(600, 600)
canvas.set_fill_color(0.7, 0.7, 0.7)
canvas.fill_ellipse(0, 0, 600, 600)
canvas.set_fill_color(0, 0, 0)
canvas.fill_ellipse(290, 290, 20, 20)

for i in range(12):
    canvas.save_gstate()
    canvas.translate(300, 300)
    canvas.rotate(-2 * pi / 12.0 * i)
    canvas.set_fill_color(0, 0, 0)
    s = 40
    fnt = 'Helvetica-Bold'
    n = str(12 if i == 0 else i)
    w, h = canvas.get_text_size(n, fnt, s)
    canvas.draw_text(n, -w/2, 240, fnt, s)
    canvas.restore_gstate()
canvas.restore_gstate()

Sets the current graphics state to the state most recently saved with save_gstate().

canvas.rotate(angle)

Rotates the current transformation matrix.

(see also save_gstate(), restore_gstate())

canvas.save_gstate()

Pushes a copy of the current graphics state (transformation, selected colors etc.) onto the graphics state stack.

(see also restore_gstate())

canvas.scale(sx, sy)

Scales the current transformation matrix.

(see also save_gstate(), restore_gstate())

canvas.translate(tx, ty)

Translates the current transformation matrix.

(see also save_gstate(), restore_gstate())

Drawing Bitmap Images

Although it is primarily designed for vector graphics, the canvas module also has some functions for drawing bitmap images, similar to the scene module. You can draw named images or the current contents of the clipboard.

canvas.draw_image(image_name, x, y[, width, height])

Draws the image with the given name in a rectangle. If width and height are omitted, the image is drawn at its natural size.

canvas.draw_clipboard(x, y, width, height)

Draw the image in the clipboard in a given rectangle.

canvas.get_clipboard_size()

Return the size of the image in the clipboard as a tuple of width and height, in points. On a retina screen, one point corresponds to two pixels. Returns (0,0) if the clipboard is empty.

canvas.get_image_size(image_name)

Returns the size of the image with the given name as a tuple of width and height, in points. On a retina screen, one point corresponds to two pixels. Returns (0, 0) if no image with this name exists.

Drawing Text

The canvas module has two simple functions for drawing and measuring text.

The color of the text that is drawn with draw_text() is determined by previous calls to set_fill_color().

canvas.draw_text(text, x, y, font_name='Helvetica', font_size=16.0)

Draw a single line of text at a given point. The point represents the origin of the line, i.e. its lower-left corner.

canvas.get_text_size(text, font_name='Helvetica', font_size=16.0)

Get the size of a line of text as it was drawn by the draw_text() function as a tuple of (width, height).

Blend Modes

The following blend modes can be used with set_blend_mode():

canvas.BLEND_NORMAL
canvas.BLEND_MULTIPLY
canvas.BLEND_DIFFERENCE
canvas.BLEND_SCREEN
canvas.BLEND_OVERLAY
canvas.BLEND_DARKEN
canvas.BLEND_LIGHTEN
canvas.BLEND_COLOR_DODGE
canvas.BLEND_COLOR_BURN
canvas.BLEND_SOFT_LIGHT
canvas.BLEND_HARD_LIGHT
canvas.BLEND_DIFFERENCE
canvas.BLEND_EXCLUSION
canvas.BLEND_HUE
canvas.BLEND_SATURATION
canvas.BLEND_COLOR
canvas.BLEND_LUMINOSITY
canvas.BLEND_CLEAR
canvas.BLEND_COPY
canvas.BLEND_SOURCE_IN
canvas.BLEND_SOURCE_OUT
canvas.BLEND_SOURCE_ATOP
canvas.BLEND_DESTINATION_OVER
canvas.BLEND_DESTINATION_ATOP
canvas.BLEND_XOR
canvas.BLEND_PLUS_DARKER
canvas.BLEND_PLUS_LIGHTER