An infinite-canvas drawing app for pen tablets on Wayland, built with Rust (winit + wgpu + octotablet). Pen pressure maps to stroke width, the canvas pans and zooms without bounds, and everything persists to a single file.
- Pressure-sensitive pen strokes with smooth ribbon tessellation
- Infinite pan/zoom at the cursor, zoom range 1e-12 to 1e12
- Named bookmarks:
Bsaves the current view (world center + zoom relative to the window width) with a custom name,Gopens a fuzzy finder to jump back — the view centers and fills the same fraction at any window size - Eraser tool with ink-distance hit testing
- Fill tool (
f): click inside any enclosed region bounded by stroke ink to fill it. The region is found vectorially — nearby strokes (quadtree search, starting close and expanding, scale-filtered to the current zoom) are split at their intersections and the click's face is traced through the connection graph, so a click between two nested circles fills the ring with the inner circle cut out. Clicking an existing fill removes it. Fills stay associated with the strokes that bound them: erasing or deleting a boundary stroke removes the fill, and pin-editing a boundary stroke refills the shape on release (recomputing connectedness — a stroke dragged off so the loop breaks removes the fill) - Marquee selection, move tool, and local copy/paste of selections
- Themed colors from a JSON config
- Autosave (debounced) plus save on exit, atomic writes
- Line rider: press
Lto drop a sled-and-rider character at the cursor that rides your strokes (gravity only, no line friction) while the camera follows;Lagain restores the previous view
With the nix flake:
nix run # run the packaged app
nix build # build the binary (result/bin/infiquill)
nix develop # dev shell with cargo, rustc, rust-analyzer
Without nix, cargo run works; the winit/wgpu runtime needs Wayland and
Vulkan libraries on LD_LIBRARY_PATH.
- Document:
$XDG_CONFIG_HOME/infiniquill/notes.iniq(override withINFIQUILL_FILE). On a non-master git branch the file isnotes.<branch>.iniqso feature-branch runs never touch the canonical document; saves back up the previous file tonotes.iniq.bak, and an unreadable document is preserved asnotes.iniq.corruptinstead of being overwritten - Theme and settings:
$XDG_CONFIG_HOME/infiniquill/config.json:
{
"theme": {
"background": "#191724",
"foreground": "#e0def4",
"cursor": "#e0def4",
"eraser": "#eb6f92",
"selection": "#c4a7e7",
"export_color": "#000000"
}
}
The `export_color` key sets the stroke color baked into SVG copies
(defaults to black, independent of the theme).- Text is rendered from Mynerve (
assets/Mynerve/Mynerve-Regular.ttf; override with$INFIQUILL_FONT). The glyph atlas is rasterized at the window's target text size and re-rasterized on resize, so text is pixel-crisp and scales from 720p to 4k. - A status bar at the bottom-left fades in (0.5s) on camera actions and fades out (5s)
afterwards. Panning shows the camera coordinates in shorthand (
x 1.23k y 4.5M), updated per frame; zooming shows the level (125%). New events appear at the anchor and bump older ones up.
| Key | Action |
|---|---|
| Pen contact | Draw (pressure maps to width) |
| Space (held) + pen | Pan the canvas; coasts on release |
| Shift (held) + pen | Zoom in/out anchored at the pen |
| Middle mouse drag | Pan |
0 |
Center on origin; press again quickly to reset zoom to 1.0 |
| Ctrl+Z | Undo |
| Ctrl+Shift+Z / Ctrl+Y | Redo |
[ / ] |
Pen size smaller / larger |
f |
Toggle fill tool (click inside an enclosed region to fill; click a fill to remove it) |
v / d |
Toggle move tool. With an empty selection, every stroke shows three grab pins (start / mid-arc / end); dragging one bends the stroke smoothly between the anchors (one undo step per drag). Alt+drag an end pin locks it to the stroke's original axis — pure stretch/shrink, no rotation. With a marquee selection, drags translate the group |
| Ctrl+C | Copy the selected strokes to the clipboard (viewport-relative; paste scales with the current zoom) |
| Ctrl+Shift+C | Copy the selected strokes as SVG (viewBox = the current window view) |
| Ctrl+X | Cut the selected strokes and images (one undo step) |
| Ctrl+V | Paste (our stroke text, a system image, or the local selection) |
| Delete | Delete the selected strokes and images |
B |
Bookmark the current view (location + zoom) with a custom name |
G |
Fuzzy-find saved bookmarks; Up/Down select, Enter jumps, Esc closes |
| Escape | Save and quit |
Infiquill is licensed under the GNU Affero General Public License v3.0 (see
LICENSE.md). The line-rider character sprites in assets/rider/ are copied
from the GPL-3.0 project linerider-advanced;
see THIRD_PARTY.md for attribution and compatibility notes.