Drawing Tools System
Relevant source files
The following files were used as context for generating this wiki page:
The Drawing Tools System in Dotorixel provides the core logic and interaction patterns for manipulating pixel data on a canvas. It is architected as a cross-platform system where heavy-duty tool algorithms are implemented in a Rust core, while high-level interaction logic and visual previews are managed within the application shells (TypeScript/Svelte and SwiftUI).
This system handles a variety of operations ranging from basic freehand drawing and erasing to geometric shape generation (lines, rectangles, ellipses), flood filling, color picking, and content translation.
Sources: CLAUDE.md, tasks/records/020-line-tool.md
Architecture and Interaction Patterns
The system utilizes a hybrid architecture to balance performance and developer ergonomics. Core algorithms (like Bresenham's line algorithm or flood fill) reside in the Rust core for performance and cross-platform consistency. The TypeScript shell manages the gesture lifecycle and provides real-time feedback.
Snapshot-Restore Preview
For tools requiring a preview (Line, Rectangle, Ellipse, Move), the system employs a snapshot-restore pattern. This avoids the complexity of a separate preview rendering layer at the current maximum canvas dimensions (up to 512x512).
- Pointer Down: The system captures a snapshot of the current pixel buffer.
- Pointer Move: The system restores the snapshot and then applies the tool's logic based on the current pointer position.
- Pointer Up: The final state is committed to the pixel buffer and history.
Sources: tasks/records/020-line-tool.md, src/lib/canvas/shape-handler.ts:4-30
Tool Handling Logic
The TypeScript implementation organizes tool logic into specific handlers to keep the EditorState clean and maintainable.
The diagram shows how EditorState acts as a central dispatcher, delegating complex shape logic to ShapeHandler while managing simple tools inline. Sources: tasks/records/026-tool-handler-refactoring.md, src/lib/canvas/editor-state.svelte.ts
Core Tool Types
The system supports several distinct categories of tools, defined by their implementation and interaction requirements.
| Tool Type | Logic Location | Preview Pattern | Description |
|---|---|---|---|
| Pencil | Rust Core | Immediate | Sets pixels to foreground color via interpolation. |
| Eraser | Rust Core | Immediate | Sets pixels to transparent (or background color). |
| Line | Rust Core / TS | Snapshot-Restore | Draws a straight line between two points. |
| Rectangle | Rust Core / TS | Snapshot-Restore | Draws a rectangular outline. |
| Ellipse | Rust Core / TS | Snapshot-Restore | Draws an elliptical outline. |
| Flood Fill | Rust Core | N/A | Fills a contiguous area of the same color. |
| Eyedropper | TypeScript | N/A | Samples color from a specific pixel. |
| Move | TypeScript | Snapshot-Restore | Translates canvas content by a relative offset. |
Sources: src/lib/canvas/tool-types.ts:1-11, tasks/records/020-line-tool.md, tasks/records/059-move-tool.md
Implementation Details
ShapeHandler
The ShapeHandler class encapsulates the snapshot-restore cycle for geometric tools. It manages the shapeStart coordinates and the previewSnapshot buffer during a drag gesture.
The sequence shows the lifecycle of a shape drawing operation where the snapshot ensures the "live" preview doesn't permanently overwrite the canvas until the gesture is finished. Sources: src/lib/canvas/shape-handler.ts, tasks/records/026-tool-handler-refactoring.md
Move Tool
The Move tool differs from drawing tools as it translates existing data rather than generating new pixels. It uses a pure TypeScript shiftPixels function for row-by-row bulk copying with clipping.
- Logic:
shiftPixels(source, width, height, dx, dy) - Performance: Sufficient for canvas sizes up to 256x256 (~1MB buffer).
- Shortcut: Bound to
KeyM.
Sources: tasks/records/059-move-tool.md, src/lib/canvas/editor-state.svelte.ts:470-485
Rust Core Algorithms
The Rust core (crates/core/src/tool.rs) defines the ToolType enum and the pixel-level application logic.
pub enum ToolType {
Pencil = 0,
Eraser = 1,
Line = 2,
Rectangle = 3,
Ellipse = 4,
FloodFill = 5,
}
impl ToolType {
pub fn apply(&self, canvas: &mut PixelCanvas, x: i32, y: i32, color: Color) {
// Pixel application logic...
}
}
Sources: crates/core/src/tool.rs:5-15
Keyboard Shortcuts
The system integrates a unified shortcut map within EditorState to allow rapid tool switching.
| Key | Tool |
|---|---|
| P | Pencil |
| E | Eraser |
| L | Line |
| R | Rectangle |
| C | Ellipse |
| F | Flood Fill |
| I | Eyedropper |
| M | Move |
Sources: src/lib/canvas/editor-state.svelte.ts:50-60, tasks/records/059-move-tool.md
Summary
The Drawing Tools System is a modular architecture that separates high-frequency interaction logic (TypeScript) from heavy computational algorithms (Rust). By utilizing patterns like the Snapshot-Restore preview and centralized tool handlers, the system provides a responsive drawing experience that is consistent across web and native platforms while maintaining a high degree of extensibility for future tool additions.