A canvas you draw on in your own coordinates - #80
Merged
Conversation
The third slice of #64, and the one the issue calls the most valuable. `BrailleCanvas` works in pixels. The primitives are good, but the caller does every unit conversion, which means a drawing written for one panel size is wrong in the next -- and there is no way to say "this line runs from (0, 0) to (10, 10) in my units" without doing the arithmetic by hand every frame. ui.shapes({ shapes: [ { type: "rect", x: 1, y: 1, width: 4, height: 4 }, { type: "circle", x: 7, y: 5, radius: 2 }, { type: "polyline", points: [[0, 8], [3, 9], [6, 7], [9, 9]] }, ], x: { min: 0, max: 10 }, y: { min: 0, max: 10 }, }); Bounds per axis, five shapes placed inside them, and a colour per shape. The existing `canvas` is untouched: it is still there for anyone who wants the pixel grid. Four decisions worth the words: Y goes up. A canvas is for drawing things that have their own geometry -- a plot, a map, a diagram -- and making the caller flip every y would be handing them back the conversion this exists to take away. There is a test asserting that y = max lands on the top row. A radius is scaled, not projected. It is a distance rather than a position, and the two axes rarely scale alike in a terminal cell, so a circle is measured against the x span. A rectangle is a corner and a size in the caller's own direction, so a positive height goes up, because their y does. Each shape is blitted before the next is drawn. A shared canvas would let the last colour win everywhere two shapes overlap; a test renders two lines in two colours and counts them. The C++ Braille class had only `pixel`, `line` and `blit`, so `rect`, `fill_rect`, `circle`, `hline`, `vline` and the span helper are new there, written against the reference rather than invented -- which is why all five canvas fixtures matched on the first run. Six ports, five fixtures, all additive. Not added to the widget gallery: the existing canvas is not in it either, because it is a graphics primitive rather than a widget, and `plot` is in the same position. Verified: 331 TS tests under bun and node; 86 widget scenes matching the reference in Rust, Go, Python, Zig and C++; 11/11 ctest; the galleries; the site builds. Part of #64 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Df2FNu5DhinMV2soRz3cy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The third slice of #64, and the one the issue calls the most valuable.
BrailleCanvasworks in pixels. The primitives are good, but the caller does every unit conversion, which means a drawing written for one panel size is wrong in the next — and there is no way to say "this line runs from (0, 0) to (10, 10) in my units" without doing the arithmetic by hand every frame.Bounds per axis, five shapes placed inside them, and a colour per shape. The existing
canvasis untouched: it is still there for anyone who wants the pixel grid.Four decisions worth the words
Y goes up. A canvas is for drawing things that have their own geometry — a plot, a map, a diagram — and making the caller flip every y would be handing them back the conversion this exists to take away. There is a test asserting that
y = maxlands on the top row.A radius is scaled, not projected. It is a distance rather than a position, and the two axes rarely scale alike in a terminal cell, so a circle is measured against the x span.
A rectangle is a corner and a size in the caller's own direction, so a positive height goes up, because their y does.
Each shape is blitted before the next is drawn. A shared canvas would let the last colour win everywhere two shapes overlap; a test renders two lines in two colours and counts them.
The C++ side needed primitives first
The C++
Brailleclass had onlypixel,lineandblit, sorect,fill_rect,circle,hline,vlineand the span helper are new there — written against the reference rather than invented, which is why all five canvas fixtures matched on the first run.Scope
Six ports, five fixtures, all additive. Not added to the widget gallery: the existing canvas is not in it either, because it is a graphics primitive rather than a widget, and
plotis in the same position. This is one slice of #64; Shadow is still open there, which is why this closes nothing.Verified
bun testandnode --test, typecheck cleannext buildfor the site🤖 Generated with Claude Code
https://claude.ai/code/session_017Df2FNu5DhinMV2soRz3cy