openpencil/crates/op-host-web
Eslam Ahmad 7f8340f2a0 fix(renderer): shape complex scripts instead of painting them in storage order (#194)
Native `draw_text` painted every run through `Canvas::draw_str`, which maps
to Skia's `drawSimpleText` — a plain cmap lookup with no bidi reordering and
no contextual glyph selection. Arabic therefore rendered in storage order
with isolated letterforms. CanvasKit's `drawText` has the same limitation on
web, and `drawScriptRun` there segmented a run by script before drawing the
segments left to right, so bidi was resolved inside each segment and then
undone across them.

The paragraph shaper was bypassed natively on purpose: jian's
`draw_text_paragraph` builds a fresh `FontCollection` on every call, which
is what produced the ~605ms chrome frames noted in crates/CLAUDE.md. That
cost is avoidable rather than inherent — `ParagraphBaseline` already keeps a
generation-guarded collection — so this caches the collection and routes
only the runs that genuinely need a shaper. Latin and CJK stay on the cmap
fast path, leaving the frame budget and their rendered output untouched.

Measurement moves with paint. `measure_text_*` summed isolated-glyph
advances, so wrap decisions and caret geometry were computed against widths
the painter never used and text overflowed its boxes. The routing predicate
lives in op-editor-core so the two hosts cannot disagree about which runs
are shaped, and so paint and measure within a host cannot drift apart.

Hebrew is deliberately out of scope and stays on the fast path.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 19:18:50 +08:00
..
assets/canvaskit fix(web): use browser fonts in canvaskit shell 2026-06-19 02:39:34 +08:00
pkg-ck fix(web): expand browser font fallback stack 2026-06-19 07:30:34 +08:00
pkg-webgl refactor(renderer): consolidate web shell on CanvasKit, retire skia path 2026-06-18 09:34:37 +08:00
smoke test(web): add rust web browser smoke 2026-06-20 19:24:59 +08:00
src fix(renderer): shape complex scripts instead of painting them in storage order (#194) 2026-08-02 19:18:50 +08:00
tests fix(renderer): shape complex scripts instead of painting them in storage order (#194) 2026-08-02 19:18:50 +08:00
.gitignore
Cargo.toml refactor: dedupe cross-crate code and converge hardcoded literals 2026-07-26 11:24:22 +08:00