Cells and cell styles had no first-baseline setting, so every cell set its first line by the
Ascent offset (the font's typographic ascender). IDML documents that set FirstBaselineOffset on a
cell style (CapHeight is common, often through a table style's body region) composed every row
taller than the document asked for. With a font whose typographic ascender is a full em (Avenir),
each row grew about 2.6 pt and long tables overset, losing their last rows.
- doc: Cell.first_baseline / first_baseline_min; CellStyle.first_baseline / first_baseline_min,
applied by CellStyle::apply_to and carried through resolve_cell_style's BasedOn chain.
- idml: FirstBaselineOffset and MinimumFirstBaselineOffset read and written on cells and cell styles.
- compose: a cell's text frame uses the cell's first baseline offset and minimum.
- engine: table.setCell, style.cell.create/edit take firstBaseline / firstBaselineMin; table.get
reports them; style.cell.create fromSelection captures them.
- tests: import through BasedOn and a table style's body region, a cell's own override, IDML round
trip; composer cap height vs ascent and a fixed minimum; command parameters and validation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Graphic literals (cli perf, doc assets/item, engine datamerge/export/file/links/mathexpr/media/table/sample, epub, format, pdf, pptx, render, tools, ui-egui properties, and tests): name the branch's clip and wrap (#561, #381) and the PR's fill.
crates/doc/src/item.rs: Graphic keeps wrap and gains fill.
crates/idml/src/import.rs: read the image swatch, then the branch's styled FrameFittingOption lookup; the graphic keeps its wrap.
crates/idml/src/tests/assets.rs: keep both new tests.
crates/render/src/lib.rs: keep #362's crop-box sizing of placed PDFs and colour the resulting pixmap.
crates/render/tests/colorize.rs, crates/epub/tests/grouped_reading_order.rs, crates/compose/src/tests.rs: literals name the branch's Asset and Graphic fields.
crates/pdf/src/export.rs: the soft mask interpolates by the standard's raster mode (the branch has no per-exporter interpolate switch).
docs/gaps.md, docs/target-app-parity.md: status lines list both sides' changes; gap text keeps the clipping-path items and adds the image swatch.
Past the estimated line slots the breaker assumes the whole column; the
rebreak check compares against that fallback too, so lines beside a wrap
object stay inside their segments.
(cherry picked from commit 94a06ed881)
Conflicts:
- crates/compose/src/shape.rs: typed figures and page-number markers both go through #1012's digit_mode; the batch's inline digits block and its second mapping of the marker text are gone.
- crates/compose/src/lib.rs: the list label keeps the batch's label_chars and prepend_label; it takes the Digits of the paragraph's first run unless the number's character style sets its own.
- crates/compose/src/tests.rs: kept page_numbers_take_the_digits_option and added #1012's test.
- crates/ui-egui/src/i18n.rs: kept the batch's French strings and added the Digits: row.
- crates/ui-egui/src/panels/properties.rs: the always-shown Digits row is followed by the batch's two-column Size, Kerning, Baseline, Leading and Tracking layout.
Conflicts:
- docs/target-app-parity.md: kept the batch's rows and added Greek to the hyphenation list.
- docs/typography-parity.md: kept the batch's Justification and Hyphenation rows and added Greek (hyph-el-monoton).
Greek text set unhyphenated however narrow the column: `Lang::for_language`
resolves a language through `hypher::Lang::from_iso`, which answers only for a
language whose patterns were compiled in, and `greek` was not among the features
the compose crate asks for. So `for_language("Greek")` was None and every Greek
word stayed whole.
The feature is asked for now. Nothing else was needed: the lookup is already by
ISO code, so "Greek", "Greek: Greece", "el" and "el-GR" all resolve, and
ανθρωπος breaks αν-θρω-πος as hyph-el gives it.
The patterns are `hyph-el-monoton.tex` 5.0 from hyph-utf8, Copyright (C)
2008-2011 Dimitrios Filippou, available under the LPPL or MIT and taken here
under MIT; NOTICE carries the licence, as it does for the other languages. The
published `hypher` crate ships compiled tries rather than the pattern files, so
that came from the file in hyph-utf8 rather than from the dependency.
They are the **monotonic** patterns, which is what `hypher` maps `el` to, so
polytonic text hyphenates by them too. Written into the module's documentation
rather than left to be discovered.
`gaps.md` 13, `target-app-parity.md` and `typography-parity.md` each listed the
four languages that hyphenate; they list five.
Only these two dialogs read bare numbers in the ruler unit; other dialogs keep their meaning.
Apply to: this page, both pages of the spread, or all pages. Parent edits default to the whole parent spread.
Replace unchecked indexing in inherited_guides and marginsAndColumns with get().
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRYQ5eieuUrtxhdbh6goq
Conflicts:
- crates/compose/src/lib.rs: kept main's line placement (line_metrics with first
baseline tops, baseline grid snap) and this branch's leading model and Aki Below
advance. The Hyphenation Zone check uses Composer::single_line(), so the Japanese
single-line composer gets the zone too.
- crates/idml/src/tests.rs: kept both tests at the conflict (composer kinds, text
stroke alignment).
Also resolved:
- crates/idml/src/import.rs: removed the package scan for a Japanese composer and the
drop of [No paragraph style]'s leading model; the import keeps the file's leading
model and the composer kind, and compose applies the model per paragraph.
- crates/idml/src/tests.rs: the default-leading-model test lays out the document and
checks Roman spacing under the non-Japanese composers and the Aki Below spacing
under the Japanese ones; a new test round-trips a Japanese composer document.
A story that ends with a paragraph return has an empty last paragraph. When
it didn't fit, DesignCraft marked the story overset at the end of its text
(Preflight: "Overset text: 0 characters"; the out port turned red).
InDesign doesn't: Montilla Design's Flex Layout file has a caption ending
with a return, fitted to its three lines, and InDesign reports no errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign sets a text line when its baseline fits in the frame; the
descenders may hang below the frame's bottom. DesignCraft required the
baseline plus the descent to fit, so a frame sized to a heading's caps
oversets: Zero2Graphic's magazine tutorial draws 2.7682 cm frames for
103 pt headings (control bar, 4:12–5:44), and all three were overset.
The keep-lines IDML fixture's frames are now 236 pt tall, so they hold the
same 19 lines under either rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Selecting an empty paragraph (a blank line) puts a collapsed caret on its
hidden paragraph mark, the only character on that line. Previously
type.char either deferred the formatting to the next typed character (in
a non-empty story) or dropped it on the floor for composition, so there
was no way to change a blank line's height — matching InDesign's ability
to select the pilcrow and adjust leading.
- engine/cmd/text.rs: recognize an empty paragraph's own caret position
(empty_para_mark) and apply character attributes straight to that
byte's run instead of deferring to typing format.
- compose/lib.rs: an empty paragraph has no glyphs of its own, so resolve
the hidden mark's run (if overridden) for the paragraph's base leading
instead of always falling back to the paragraph's plain default.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add multi-click text selection, pending caret formatting and clipboard support, text-aware colour controls, guide/grid snapping, and frame threading with loaded-port interactions.
Include the layout, drop-cap and IDML updates carried from #83, with safeguards for generated and linked stories, external text references, local IDs, locked frames and atomic colour edits.
Fixes#23.
Co-authored-by: Sean Hammond <sean.hammond@und.edu>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge current main into the text editing and layout work, retaining the original contributor commits. Preserve generated and linked stories, incoming text references, local IDs and locked frames when threading.
Keep pending formatting and text colours consistent, isolate deferred control clipboard input, and handle inherited IDML frame properties with bounded column allocations. Add focused state-preservation and round-trip regressions and correct the socket and swatch test fixtures.
M2; refs #84.
Start options were skipped for a paragraph at the top of a frame. That is
right for Next Page, Next Frame and Next Column (there is nothing to break
away from), but a Next Odd Page paragraph that lands at the top of an even
page stayed there, as did Next Even Page at the top of an odd page, and the
same went for odd and even page break characters. A part or chapter opener
whose previous section ended exactly at the bottom of an odd page therefore
opened on a left-hand page.
Cursor::start_at_top now moves such a paragraph to the next page of the
asked parity, for paragraphs, tables and break characters alike. Other
start options at the top of a frame are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cross-reference index composed its destination stories through
the cache. One with a running header asked for the running-header
index, which composed the story holding the cross-reference, which
asked for the cross-reference index again: the stack overflowed and
the app aborted. Destination stories with a running header are now
composed without it, like those with cross-references already were.
The paragraph composer counted a trailing space (or several) before the
paragraph end or a forced line break in the line's width, so "2 VOOR " in a
frame exactly as wide as "2 VOOR" broke before "VOOR" and the frame went
overset. InDesign lets those spaces hang past the edge. They now add no
width; the line's visible range already left them out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>