Canvas API¶
The Canvas class is the core drawing utility in Inkycal.
Every module generates its visual output using a Canvas instance, which provides:
- High-level text rendering (
write()) - Automatic text wrapping
- Automatic font scaling
- Icon rendering with pixel-accurate centering
- Preview rendering (black + red composite)
- Helper utilities for borders, sizing, and layout
This document describes the full public API of the Canvas class.
Overview¶
A Canvas maintains two separate Pillow images:
image_black→ The black layerimage_colour→ The colour layer (used for red pixels on supported displays)
Each write() or draw_icon() operation may write to one or both layers, depending on the colour parameter.
Creating a Canvas¶
from inkycal.utils.canvas import Canvas
from inkycal.utils.enums import FONTS
canvas = Canvas(
im_size=(800, 480),
font=FONTS.default,
font_size=24
)
Class Reference¶
Canvas.__init__(im_size, font, font_size)¶
Initializes a drawing context.
| Parameter | Type | Description |
|---|---|---|
im_size |
tuple(int, int) | (width, height) of the canvas |
font |
FONTS enum |
Default font to use |
font_size |
int | Initial font size |
Creates two internal images:
image_blackimage_colour
Both begin as white RGB canvases.
write(xy, box_size, text, ...)¶
High-level function to draw single-line or multi-line text inside a bounding box.
Supports:¶
\nmanual line breaks- Automatic line breaking (
text_wrap) - Automatic font scaling (
autofit=True) - Vertical + horizontal centering
- Rotated text
- Colour or black rendering
Signature¶
write(
xy: Tuple[int, int],
box_size: Tuple[int, int],
text: str,
*,
alignment: Literal["center", "left", "right"] = "center",
autofit: bool = False,
colour: Literal["black", "colour"] = "black",
rotation: Optional[float] = None,
fill_width: float = 1.0,
fill_height: float = 0.8,
)
Example¶
canvas.write(
xy=(20, 20),
box_size=(200, 80),
text="Hello World",
autofit=True,
alignment="center",
)
text_wrap(text, max_width)¶
Splits text into a list of wrapped lines based on rendered pixel width.
lines = canvas.text_wrap("some long text", max_width=180)
This is used internally by write() but may also be useful when building complex layouts.
auto_fontsize(max_height, sample_text="Ag", target_ratio=0.8)¶
Automatically increases font size until the rendered height of a sample string reaches a ratio of the bounding height.
Used internally by write(autofit=True).
get_line_height(sample_text="Ag")¶
Returns the true pixel height (ascent + descent) of the active font.
This is extremely useful for:
- Vertical spacing
- Multi-line layouts
- Event list rendering
- Calendar modules
Example:
line_height = canvas.get_line_height()
get_text_width(text)¶
Returns the width in pixels of the given text using the current font.
Icon Rendering¶
draw_icon(xy, box_size, icon, ...)¶
Draws a weather icon or glyph centered inside a bounding box.
Features:¶
- Pixel-accurate centering via alpha analysis
- Automatic icon sizing (
fill_ratio) - Optionally writes to colour layer
- Supports rotation
Signature¶
draw_icon(
xy: Tuple[int, int],
box_size: Tuple[int, int],
icon: str,
colour: Literal["black", "colour"] = "black",
rotation: Optional[float] = None,
fill_ratio: float = 0.90,
font: Optional[FONTS] = None,
)
Example:
canvas.draw_icon(
xy=(100, 100),
box_size=(80, 80),
icon="\uf00d",
colour="colour"
)
This is used heavily in the Weather module.
Preview Rendering¶
The preview system converts the internal black + colour layers into a pure black + red composite image for display in the WebUI or debugging.
_optimize_for_red_preview(img)¶
Internal cleanup step that removes grey pixels introduced by anti-aliasing.
You should not call this manually.
color_to_red(img)¶
Converts all dark pixels in the colour layer to pure red with alpha transparency, used by the preview generator.
get_preview_image()¶
Returns a composite image where:
image_black= black baseimage_colour= converted to red overlay- Both layers are merged
Used by:
- The WebUI
- Debug output
- Local previews
preview = canvas.get_preview_image()
preview.show()
Properties¶
Canvas.image_black¶
A Pillow RGB image containing all black-layer content.
Canvas.image_colour¶
A Pillow RGB image containing all colour-layer content (will appear red on preview or e-paper).
Canvas.font¶
Current font enum (type FONTS).
Canvas.font_size¶
Current font size.
Canvas.size¶
Returns the full (width, height) of the canvas.
When to Use Canvas¶
Use Canvas whenever your module needs to:
✔ Render text¶
✔ Draw icons¶
✔ Draw calendar grids¶
✔ Generate multi-column layouts¶
✔ Render a chart or image annotation¶
✔ Produce a composite preview¶
✔ Handle black + red layer separation¶
The Canvas class abstracts away:
- Pixel-level centering
- Font sizing
- Text wrapping
- Dual-layer rendering
- Red preview logic
So module authors can focus purely on layout and content.
Example: Building a Module with Canvas¶
class HelloWorld(InkycalModule):
def generate_image(self):
canvas = Canvas(
im_size=(self.width, self.height),
font=self.font,
font_size=self.fontsize
)
canvas.write(
xy=(0, 0),
box_size=(self.width, 100),
text="Hello World!",
autofit=True,
alignment="center"
)
return canvas.image_black, canvas.image_colour
Summary¶
The Canvas class is the core drawing abstraction for Inkycal.
It provides everything needed for:
- Text rendering
- Wrapping
- Automatic font fitting
- Clean black/colour separation
- Accurate icon rendering
- Red preview generation
Most modules rely heavily on Canvas — understanding it unlocks the ability to create rich visual layouts.