41 Commits

Author SHA1 Message Date
alonso.torres
f44e13df70 ✨ Make horizontal Japanese justify and squeeze follow vertical JLREQ
Horizontal Japanese justification spread each line's slack evenly over
all character gaps, while vertical columns widen gaps in JLREQ pair-table
order. Squeezing also differed: horizontal squeezed only under push-in
first, while vertical also squeezes under push-out first when push-out
cannot resolve a kinsoku break.

Move the axis-free part of the vertical allocator into text_allocation:
jlreq_expansion_gap classifies a gap from the pair table and
jlreq_ordered_expansion widens word spaces, then Japanese/Western gaps,
then solid kana and kanji, then spreads any rest. Vertical columns and
horizontal lines both use it. Horizontal collects real characters from
the laid-out lines; inserted joiners and spacing belong to the gap
between their neighbours. The last line, distribution and the warichu,
joiner and Western-word skips stay as they were.

Under push-out first, horizontal now squeezes a line when the break would
move back over more than MAX_KINSOKU_SHIFT kinsoku pairs, the limit
vertical oidashi uses, now shared from jlreq. A cheap scan for such runs
gates the pass, so other text keeps its layout cost. Push-out only never
squeezes.

This changes existing horizontal justified Japanese layouts on purpose:
punctuation aki and gaps beside ruby bases no longer widen, and a line
with no expandable gap stays short, as vertical columns do. No existing
test needed changes beyond the new line adjustment argument.

AI-assisted-by: claude-opus-5-5
2026-11-05 17:49:00 +01:00
alonso.torres
cc6f183a90 🐛 Let vertical Chinese and Korean ruby overhang its neighbours
The pairwise vertical path (Chinese, Korean and plain text) grew ruby
bases without first computing overhang rooms, so a long Pinyin reading
always spread its base. Horizontal text, and vertical Japanese, let the
reading hang over an adjacent kana, comma, full stop or middle dot.

Run set_ruby_overhang_rooms before grow_ruby_bases on that path too. It
uses ruby_overhang_room, the rule horizontal applies to every language,
so Han neighbours still take no overhang and ruby-overhang none keeps
the old growth. A comment at the early return notes that warichu never
splits there: only Japanese renders warichu.

AI-assisted-by: claude-opus-5-5
2026-11-05 17:49:00 +01:00
alonso.torres
31115ab29a 🐛 Make horizontal emphasis mark bounds match where the mark paints
The mark box used the mark's em box (half the base size, square), while
painting placed the shaped mark by its tight rect: advance wide, ascent
plus descent tall. Text bounds, selection and export therefore disagreed
with the canvas; over marks could paint above the bounds.

Shape each span's mark once in HorizontalEmphasisMark and place that
measured box for paint, text bounds and position data alike. Position
data keeps an em box, now centred on the painted mark, because SVG
export draws the mark at a font size equal to the box width.

Tests that built synthetic placements now pass the mark ink explicitly;
their assertions are unchanged. Vertical marks had no mismatch: paint
and position data centre on the same point.

AI-assisted-by: claude-opus-5-5
2026-11-05 17:49:00 +01:00
alonso.torres
619f136587 ♻️ Split the vertical pairwise flow out of the JLREQ passes
text_vertical/flow.rs held both the JLREQ column passes and the planner
the plain, Chinese and Korean policies use. Move the pairwise planner,
spacing and alignment to flow/pairwise.rs; the JLREQ passes stay in
flow/mod.rs with the flow types both share.

Also list the CJK renderer modules and their new names in
docs/cjk-layout.md.

AI-assisted-by: claude-opus-5-5
2026-11-05 17:49:00 +01:00
alonso.torres
2b888f712b ♻️ Make the text layout policy one language decision
TextLayoutPolicy had nine flat variants that mixed language, Chinese
region and Korean wrap. It is now Plain, Japanese, Chinese(ChineseRegion)
or Korean(KoreanWrap), and the layout code asks it named questions
(uses_jlreq, plans_breaks, keeps_overlong_units, reopens_overlong_words,
bounded_justify, needs_joiner, normalizes_western_spaces,
uses_clreq_positions, ...) instead of comparing variants.

Paragraph parses its language once, when the language or the Korean wrap
changes, and copies the policy to its spans. Span code no longer builds a
policy from the tag with a dummy Korean wrap, and the emphasis and
underline positions take the policy instead of a Chinese flag.

A LanguageTag parser now serves both the layout policy and the CJK font
choice. It also accepts '_' as a separator, as the font choice did, so
a tag such as "ja_JP" now selects the Japanese policy.

The korean-wrap byte decodes through a new exported RawKoreanWrap enum
(Syllable=0, SpacesOnly=1, KeepWords=2) with the same byte values.

AI-assisted-by: claude-opus-5-5
2026-11-05 17:49:00 +01:00
alonso.torres
809441762b 🐛 Preserve emphasis across adjacent ruby spans
Recover merged annotation styles on the base character's own line, using
separate UTF-16 line anchors and UTF-8 style keys. Include emphasis marks
in horizontal text bounds so standalone exports keep each mark whole.

Add regression coverage for adjacent readings, wrapped text, emoji line
anchors, raster output and export bounds across all text grow modes.
Verify 670 renderer tests, formatting and both WASM builds. Add four
editable showcase examples and check their layout and exports.

AI-assisted-by: GPT-6
2026-11-05 17:48:59 +01:00
alonso.torres
d06570c010 🐛 Keep indivisible CJK units together in narrow text boxes
Retain legal line starts at the original wrap width before allowing an
indivisible punctuation or annotation unit to overflow together. Share the
layout plan and alignment offset across painting, editing and exports.

Cover mixed styles, nonbreaking controls, graphemes, annotations, alignment,
strokes and resize. All 666 renderer tests and both WASM builds pass.

AI-assisted-by: GPT-6
2026-11-05 17:48:59 +01:00
alonso.torres
5d63967cf8 ✨ Add Mandarin Zhuyin reading layout
Add typed one-character Zhuyin readings with upright right-side symbols
and separate neutral and non-neutral tones in both writing modes.
Persist the mode through the editor, WASM bridge and Plugin API. Preserve
annotation clearance and canvas, PNG, PDF and SVG geometry.

Validate syntax and selection boundaries, and cover schema, bridge,
rendering, UI and API behavior. Native IME and reader review remain open.

AI-assisted-by: gpt-6
2026-11-05 17:48:59 +01:00
alonso.torres
ff18d2bd34 ✨ Add Chinese emphasis and underline positions
Carry optional span positions through the schema, WASM header, editor,
Plugin API and CSS output. Expose Chinese controls with language defaults
and independent overrides for horizontal and vertical text.

Reserve automatic clearance per side and stack underlines, ruby and
emphasis. Preserve reading groups during decoration edits and retain
canonical position values in DOM editor style data.

Add protocol, geometry, editing and API tests, including the prior Japanese
mixed-font gutter behavior. Verify both WASM targets and live exports.

AI-assisted-by: GPT-6
2026-11-05 17:48:59 +01:00
alonso.torres
30fe8abf63 ✨ Add Chinese Pinyin reading controls
Support typed character and group readings through the shared ruby model.
Expose Chinese labels, presentation controls and selection guards without
changing Japanese controls or generating pronunciation.

Preserve complete source ranges for glyphs sharing a combining cluster.
Add pinned horizontal and vertical tone-mark fixtures and editor tests.

AI-assisted-by: GPT-6
2026-11-05 17:48:59 +01:00
alonso.torres
b5ff9ce59f ✨ Add Chinese regional and Korean word layout
Add named Chinese punctuation presets and a Korean keep-words mode for
horizontal and vertical layout. Preserve the saved spaces-only mode and
keep source offsets stable through safe emergency wrapping.

Apply bounded CJK spacing and justification, expose the new choices in the
sidebar, and document preset bounds and remaining release checks.

Verify renderer, frontend, common and exporter tests, both WASM builds,
and sample save/reload plus PNG, PDF and SVG exports. Existing CI failures
remain documented in the layout notes.

AI-assisted-by: GPT-6
2026-11-05 17:48:59 +01:00
Alejandro Alonso
ec5a1edbed
✨ Make export follow the active renderer only (#11910)
Drop the separate :wasm-export flag and wasm-export/v1 feature. Single
export, clipboard PNG, plugins, and batch :is-wasm now key off
render-wasm/v1 alone. The exporter trusts :is-wasm for headless WASM
and always keeps a worker pool ready.
2026-09-25 12:40:56 +02:00
Elena Torró
0533be100d
🐛 Fix text selection render overlay and double/triple click flash (#11512) 2026-09-04 12:38:31 +02:00
Elena Torró
b458dc764e
🔧 Set wasm export by flag instead of team feature (#11449) 2026-09-01 12:47:05 +02:00
Elena Torró
30bc2a4bc3
🔧 Add FF to enable wasm export at team level (#11130) 2026-08-07 12:36:52 +02:00
Elena Torró
6ebefa2c16
✨ Add single-file export to PDF using the WebGL render (#9860) 2026-06-11 10:41:21 +02:00
John Eismeier
c156559f2c
📚 Fix several typos on code comments and messages (#9946)
Signed-off-by: John E <jeis4wpi@outlook.com>
2026-06-01 09:43:07 +02:00
Andrey Antukh
12e5d8d8c4 Merge remote-tracking branch 'origin/staging-render' into develop 2026-02-12 11:00:56 +01:00
Elena Torro
a14c36e996 📚 Add embedded text editor MVP documentation 2026-02-12 09:34:20 +01:00
Andrey Antukh
dc44156b53 🐛 Fix text editor wasm playground 2026-01-22 13:55:41 +01:00
Alejandro Alonso
479ce99b32 ✨ Improve setting svg attrs in wasm 2025-10-24 10:35:30 +02:00
Belén Albeza
e4d610d503
♻️ Decouple shapes serialization from model (rust) (#7328)
* ♻️ Move shape type serialization to wasm module

* ♻️ Refactor serialization of constraints and vertical alignment into wasm module

* ♻️ Refactor serialization and model of shape blur

* ♻️ Refactor bool serialization to the wasm module

* ♻️ Split wasm::layout into submodules

* ♻️ Refactor serialization of AlignItems, AlignContent, JustifyItems and JustifyContent

* ♻️ Refactor serialization of WrapType and FlexDirection

* ♻️ Refactor serialization of JustifySelf

* ♻️ Refactor serialization of GridCell

* ♻️ Refactor serialization of AlignSelf

* 🐛 Fix AlignSelf not being serialized

* ♻️ Refactor handling of None variants in Raw* enums

* ♻️ Refactor serialization of grid direction

* ♻️ Refactor serialization of GridTrack and GridTrackType

* ♻️ Refactor serialization of Sizing

* ♻️ Refactor serialization of ShadowStyle

* ♻️ Refactor serialization of StrokeCap and StrokeStyle

* ♻️ Refactor serialization of BlendMode

* ♻️ Refactor serialization of FontStyle

* ♻️ Refactor serialization of GrowType
2025-09-22 13:47:54 +02:00
Belén Albeza
e5e11b6383
🔧 Autogenerate serialization values for wasm enums (#7296)
* 🔧 Autogenerate serialization values for wasm enums

* 🔧 Add serializer values to the wasm api

* ✨ Avoid converting to a clojure map the serializer js object

* 🔧 Update watch script for autoserialized enums

* 🐛 Fix missing serializer values
2025-09-16 12:29:14 +02:00
Elena Torro
b78e3159d1 📚 Add wasm playground internal docs 2025-08-28 15:10:56 +02:00
Elena Torro
9a44bd0967 📚 Add schemas and links to render-wasm README 2025-06-17 14:06:46 +02:00
Elena Torró
4869373a43
🔧 Add methods to render text as path (#6624)
* 🔧 Refactor text strokes drawing

* 🔧 Add text to path methods for future usage

* 📚 Add text as paths internal documentation
2025-06-16 13:37:29 +02:00
Belén Albeza
afdbb5cf2f 📚 Add documentation specific for wasm visual regression tests 2025-06-09 17:46:18 +02:00
Elena Torro
4c10aeefe6 📚 Add texts documentation 2025-06-02 16:36:25 +02:00
Aitor Moreno
e9edebbbb5
📚 Add tile rendering documentation (#6568) 2025-05-28 09:41:07 +02:00
Belén Albeza
6323031b40 📚 Add serialization docs for fills 2025-05-06 14:41:40 +02:00
Alonso Torres
83d41dba6f
✨ Serialization of grid layout data (#6148)
* ✨ Add serializators for grid layout properties

* ✨ Extract serializers for wasm api module
2025-03-26 12:10:31 +01:00
Alonso Torres
fa0da3a695
✨ Flex layout modifiers wasm implementation
* ✨ Flex layout modifiers wasm implementation

* ✨ Flex auto modifiers propagation
2025-03-17 10:46:32 +01:00
Belén Albeza
eb6d2fb0eb
🎉 Store custom fonts (ttfs) and use them to write texts (wasm) (#6050) 2025-03-14 12:45:15 +01:00
alonso.torres
ba4554da79 🐛 Fix problem with reverse config in flex 2025-03-07 09:23:07 +01:00
alonso.torres
80d5272248 ✨ Serialize layout data 2025-02-25 15:43:12 +01:00
Alonso Torres
6cb1aa24cd
✨ Add constraints calculation on WASM (#5894)
* ✨ Add constraints calculation on WASM

* ✨ Fix after review
2025-02-19 10:40:04 +01:00
Alejandro
09131f7533
🎉 Render drop shadows (wasm) (#5693)
Co-authored-by: Belén Albeza <belen@hey.com>
2025-01-28 15:10:06 +01:00
Alejandro Alonso
7cc33b1a1a 🎉 Render wasm blur support 2025-01-13 07:48:11 +01:00
Belén Albeza
4e5f67676c 🎉 Implement boolean operations (wasm) 2025-01-09 17:14:48 +01:00
Alejandro Alonso
13ec04dd65 🎉 Stroke caps support for wasm render 2025-01-09 11:58:36 +01:00
Belén Albeza
ef32acdfab 📚 Add serialization docs for gradient stops and path data 2024-12-11 13:08:49 +01:00