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> |
||
|---|---|---|
| .. | ||
| assets/canvaskit | ||
| pkg-ck | ||
| pkg-webgl | ||
| smoke | ||
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.toml | ||