Commit c0cd045
authored
## Summary
Ships the Canvas 2D half of Tier-1 #8 of #446. This is the surface
`idaptik-ums` (App.res: 1178 LoC of DOM + canvas) and every non-Pixi UI
in the estate has been waiting for; WebGL / WebGL2 / WebGPU stays at `○`
until a consumer surfaces a concrete need.
## What lands
`stdlib/Canvas.affine` (+170 lines, new module): 1 extern type (`Ctx2D`)
+ 26 extern fns covering the full idaptik-ums-relevant Canvas 2D
surface:
| Surface | Externs |
|---|---|
| Context acquisition | `canvasGetContext2D` |
| Styles | `canvasFillStyle` / `StrokeStyle` / `LineWidth` /
`GlobalAlpha` |
| Rectangles | `canvasFillRect` / `StrokeRect` / `ClearRect` |
| Paths | `canvasBeginPath` / `ClosePath` / `MoveTo` / `LineTo` / `Arc`
/ `Fill` / `Stroke` |
| Transform stack | `canvasSave` / `Restore` / `Translate` / `Rotate` /
`Scale` |
| Text | `canvasFont` / `TextAlign` / `TextBaseline` / `FillText` /
`StrokeText` / `MeasureText` |
| Images | `canvasDrawImage` / `canvasDrawImageScaled` |
`lib/codegen_deno.ml` (+58 lines): 26 `__as_canvas*` prelude helpers +
26 dispatch entries adjacent to the Ipc block.
`tests/codegen-deno/canvas_smoke.{affine,harness.mjs}` (+160 lines
combined): 5 distinct smoke functions exercise every shipped extern. The
`MockCtx2D` records every method call as a typed-op tuple so the test
asserts call order + arguments, not just side-effects. The
`canvasMeasureText` round-trip exercises the `Json`-return shape (the
`TextMetrics`-shaped object).
`docs/bindings-roadmap.adoc` row #8 status promoted `○ → ◑`; deferred
items captured (WebGL, gradients/patterns, ImageData, curve primitives,
compositing/clip).
## Design notes
**Why is `HTMLCanvasElement` not its own extern type?** The
canvas-creation entry point is host-dependent — browser
`document.createElement("canvas")` vs idaptik's pre-existing DOM tree vs
jsdom-under-Deno. Treating the canvas as opaque `Json` defers the typed
wrapper to the natural follow-up once `affinescript-dom` lands runtime
support (currently blocked on the wasm-codegen `for-in` / `while` gap,
issue #255).
**Why fix `arc` counter-clockwise to `false`?** The 6-arg shape (`ccw`
boolean) would force every call site to pass a literal `false`. The
5-arg shape covers the overwhelming majority of consumers; a typed
wrapper with the `ccw` flag is a follow-up if a consumer surfaces the
need.
**Why two separate `drawImage` externs instead of one with optional
args?** AffineScript doesn't have JS-style variadic functions; making
`w` and `h` `Option<Float>` would force every natural-size call to
thread `None`s. The two-extern split keeps each call site simple.
**Why open-string `eventMode` / `textAlign` / `textBaseline`?** Same
rationale as the PixiJS expansion (#502) — Pixi 8's `eventMode` and
Canvas's text-alignment values are open enumerations, and a sum-type
binding would either freeze the set or require tagged-variant codegen
that doesn't exist on the Deno-ESM backend yet (deferred to json.affine
v0.3). Consistency with existing patterns.
## Test plan
- [x] `dune build bin/main.exe` — clean (only the expected parser
warnings)
- [x] `dune runtest --force` — 356 tests pass (was 354 pre-PR; +2 from
new Canvas + Ipc modules' AOT smoke)
- [x] `tools/run_codegen_deno_tests.sh` — all 19 harnesses including the
new `canvas_smoke.harness.mjs` OK
- [ ] CI build job
- [ ] CI `tools/run_codegen_deno_tests.sh` job
- [ ] CI governance + Hypatia (6 baselines per repo CLAUDE.md may be red
— pre-existing on main, not regressions)
## Refs
- Umbrella: #446 (Tier 1 — idaptik blockers)
- Tier-1 sub-issue: #450
- Row updated: `docs/bindings-roadmap.adoc` row #8
- Pattern siblings shipped this session: #502 (PixiJS Container
expansion), #506 (Ipc.affine)
- Adjacent / future: `affinescript-dom` (gated on #255), WebGL/WebGPU
(Tier 3 axis, not surfaced as need yet)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent 7ada658 commit c0cd045
5 files changed
Lines changed: 413 additions & 3 deletions
File tree
- docs
- lib
- stdlib
- tests/codegen-deno
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
94 | | - | |
95 | | - | |
96 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
354 | 354 | | |
355 | 355 | | |
356 | 356 | | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
357 | 390 | | |
358 | 391 | | |
359 | 392 | | |
| |||
602 | 635 | | |
603 | 636 | | |
604 | 637 | | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
605 | 667 | | |
606 | 668 | | |
607 | 669 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
0 commit comments