uctx

2D vector graphics for micropython with ctx

The micropython binding for ctx is experimental - when running out of resources it should render garbage/interrupted canvases/simplified geometry; but it will perhaps instead crash - for basic use the resource consumption is modest and does not seem to be a problem. The best way to experiment with memory resource usage is the below wasm version of micropython+ctx, switch from applet to IDE mode with the dropdown.

For downloads of sources and firmwares for RP2040 and ESP32, see bottom of page.

..
..

ctx API

Normally you get a context to operate on by doing:

import canvas
  ctx = canvas.ctx

  .. do things with ctx ..

canvas.ctx contains the code to create and intagrate with a platform to provide display and events. This is API for this is documented towards the end of this file.

save()
saves graphics state, which includes clipping path, color/gradient and most attributes, should be paired with a corresponding restore()
restore()
restores graphics state.
gray(value)
sets a grayscale value as paint source, range 0.0 black to 1.0 white
rgb(red,green,blue)
sets an RGB paint source with full opacity, values normally ranging 0.0-1.0
rgba(red,green,blue,alpha)
sets an RGBA paint source, same as rgb but specifying opacity in range 0.0-1.0
linear_gradient(x0,y0,x1,y1)
specifies that the paint source is a linear gradient, before any color stops are added a gradient from black to white is used. The initial value of the gradient applies at coordinates x0,y0 and the final color of the gradient applies at x1,y1.
radial_gradient(x0,y0,radius0,x1,y1,radius1)
specifies that the paint source is a radial gradient, before any color stops are added a gradient from black to white is used. The initial value of the gradient applies at the circle specified by x0,y0,radius0 and the final color at x1,y1,radius1.
add_stop(pos,color,alpha)
the color type needs rework, incorporating color-model.
begin_path()
might be renamed to clear_path()
close_path()
close the current path
move_to(x,y)
move the pen, without creating a path trace to a place, then put the pen down
line_to(x,y)
create a line to the given coordinates
curve_to(cx0,cy0,cx1,cy1,x,y)
create a bezier line to x, y using the other arguments as curve control points.
quad_to(cx0,cy0,x,y)
do a quad curve segment.
rel_line_to(x,y)
create a straight line segment moving the relative amounts x and y along those axes.
rel_move_to(x,y)
lift the pen move it relative x,y on respective axes and put it down.
rel_curve_to(cx0,cy0,cx1,cy1,x,y)
create a relative bezier segment, all coordinates specified are relative to the current x and y coordinates.
rel_quad_to(cx0,cy0,x,y)
create a relative quadratic curve segment, all coordinates specified are relative to the current x and y coordinates.
rectangle(x,y,width,height)
create a rectangle
round_rectangle(x,y,width,height,radius)
create a rectangle with corners rounded to the given radius. arc(x,y,radius,radians1,radians2,direction)
arc(x,y,radius,radians1,radians2,direction)
add an arc segment formed by a circle centered at x,y with the given radius going from radians1 to radians2 in a given direction.
fill()
fill the current path
stroke()
stroke the current path
clip()
create a clip from current subsequent drawing operations will not effect bits outside the current clip. Clips with pixel and axis aligned rectangles are faster than other clips.
paint()
draws to the whole device extent with current drawing source, clips apply.
in_fill(x,y)
reports of the coordinates are in the current fill, depending on ctx this might be approximated with a bounding box.
text(string)
render the string using the current paint and font settings, word wrapping and alignment might apply depending on attributes set on context.
text_width(string)
reports the width of the string
rotate(radians)
rotates the current user to device transform by the specified radians.
scale(x,y)
scale the current user to device transform, values larger than 1.0 makes the drawn content larger.
translate(x,y)
changes the origin by x and y. apply_transform(a,b,c,d,e,f,g,h,i)
apply_transform(a,b,c,d,e,f,g,h,i)
applies an arbitrary 3x3 transform
start_frame()
start a new frame, should be followed with end_frame when done rendering.
end_frame()
end a frame, this causes ctx to update the display and process any events that might have arrived or arrives during the update of the display.
line_dash(dash_pattern)
sets line dashes, perhaps this should be turned into an attribute? texture(buffer,format,width,height,stride)
texture(buffer,format,width,height,stride)
listen(event_mask,cb[,userdata=None])
event_mask is one of or a combination of PRESS, MOTION, RELEAE, TAP, TAP_AND_HOLD, DRAG_PRESS, DRAG_MOTION, DRAG_RELEASE, SCROLL, MESSAGE and DROP cb(event) is a function to handle the event.
add_key_binding(keycombo,cb,action=None,label=None)
adds a response to a keybinding, the keybinding can include example keycombos include "control-up", "alt-control-down" "escape", "q".
get_font_name(font_no)
gets the fontname at font_no position, to get a list of all available fonts start at 0 and increment until not getting a string.
parse(string)
parses a string according to the ctx protocol.
tinyvg_get_size(tvg)
returns a tuple of width,height of the tinyvg document in tvg
tinyvg_draw(tvg)
draw the tinyvg document contained in tvg
logo(x,y,size)
draw the ctx logo, used in the demos/examples.

Attributes:

x
current position for placing text and constructing paths
y
current position for placing text and constructing paths
width
width of canvas
height
height of canvas
image_smoothing
1 bilinear 0 nearest neighbor
compositing_mode
one of SOURCE_OVER (default), COPY, SOURCE_IN, SOURCE_OUT, SOURCE_ATOP, CLEAR, DESTINATION_OVER, DESTINATION, DESTINATION_IN, DESTINATION_OUT, DESTINATION_ATOP, not all modes currentl work as expected.
blend_mode
NORMAL (default), MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, COLOR_DODGE, COLOR_BURN, HARD_LIGHT, SOFT_LIGHT, DIFFERENCE, EXCLUSION, HUE, SATURATION, COLOR, LUMINOSITY, DIVIDE, ADDITION, SUBTRACT,
line_cap
one of NONE, ROUND and SQUARE
line_join
one of BEVEL, ROUND and MITER
fill_rule
WINDING or EVEN_ODD
miter_limit
miter limit for stroking.
line_width
width used for stroking lines
line_dash_offset
offset for dash pattern
global_alpha
reduces the alpha of all drawing operations
font
the font to use, sample string: "Mono" "Courier Bold" "Times" "Roboto Thin", which fonts are available depends on the installation; ctx tries to do some reasonable fallback choices when presented with input strings.
font_size
size of text, in user dimensions
text_align
one of START (default), END, CENTER, LEFT, RIGHT
text_baseline
one of ALPHABETIC (default), TOP, HANGING, MIDDLE, IDEOGRAPHIC and BOTTOM
line_height
The scaling factor applied to font_size when encountering newline characters in text to layout.
wrap_left
When wrap_left and wrap_right differ they are used as word-wrapping margins during text layout.
wrap_right
The x coordinate limit at which words wrap by setting the current position to wrap_left, current_y + line_height * font_size. Todo: implement text_height method to go with text_width for wrapped layout.
need_redraw
not currently used with micropython, used elsewhere to limit frame rate to actual changes.
flags
An ored combination/sum of LOWFI GRAY2 GRAY4 GRAY8 RGB332 HASH_CACHE INTRA_UPDATE and STAY_LOW. Used by the cb-backend to to adaptive latency/quality tradeoffs.

Platform integration API:

For someone writing code using uctx, this is only visible making the integration with display/events work. For the web version, and running the linux binary, this is not neccesary.

ctxmodule.Context(width=0,height=0,stride=0,format=0,buffer=NULL,memory_budget=24*1024,flags=0,set_pixels=NULL,update=NULL)
Creates a new ctx context, with some backends no arguments at all provides platform defaults and provide a usable context. With an external SPI display we need to provide width, height, format, flags (can still be 0), set_pixels and an optional update handler, for details on flags see the flags attribute. To create a context for an in memory buffer provide width, height, stride and format. Events can be injected, in the form of on-screen keyboards or additional pointer input devices interleaved with the existing (or missing) events in canvas.py pointer_motion(x,y,device_no,time)
pointer_motion(x,y,device_no,time)
inject a pointer event use device_no 0 for general mouse/resistive touch, and individual touch points for multi-touch. time can be 0 for ctx to use the time of the event coming in.
pointer_press(x,y,device_no,time)
indicates that the device no is down and touching the screen
pointer_release(x,y,device_no,time)
indicates that the device is up and no longer touching the screen
key_down(keycal,string,time)
inject a key event, the order is down, press (once or more, if doing autorepeat outside ctx), then release
key_press(keycal,string,time)
registers a key press, if string is missing then keyval is used as a hardware keycode to create the string, the string can also be a utf8 string, suitable when the outside events know of unicode.
key_up(keycal,string,time)

Building

For building, first build micropython, Then augment the build using the instructions on compiling cmodule extensions to micropython.

License

The uctx bindings are licensed under MIT, the copy of ctx which is includes is licensed under LGPLv3+.

Downloads

uctx-examples.tar.gz 16K python source samples - for use with all ports
uctx-x86-64 580K static x86-64 linux binary
uctx.bin.gz 1.3M ESP32 firmware image
uctx.tar.gz 572K uctx cmodule source snapshot
uctx.uf2.gz 580K RP2040 firmware image