Conflicts: compose lib.rs imports (both; Composer unused), idml tests.rs (both test modules), ui-egui
panels/mod.rs (next's ruler origin with the branch's graphic wrap for Direct Selection).
A placed graphic carries its own text wrap (Graphic.wrap). IDML import
reads TextWrapPreference on the Image/PDF element and export writes it
back there. Layout treats it as an obstacle around the part of the
graphic its frame shows, plus the offsets, and also collects wraps of
items inside groups. object.textWrap acts on the graphic when the
selection is the frame's content, and the Text Wrap panel shows its wrap.
- object.setLayer moves a group member's top-level group (and its members)
and rejects an unknown or missing layer; object.reorder sets the layer on
moved groups' members too.
- object.reorder returns without editing when the order and layers would
not change, so no undo step is recorded.
- Layers panel: locked and hidden layers take object and selection drops
only with Cmd/Ctrl held; the selection square drops the selected
members' top-level groups.
Conflicts: fonts fontdb.rs (the branch's em box with its from-BASE flag beside next's ICF cache); idml
tests.rs (the branch's copies of tests already on next, and the mojikumi test #129 replaced, dropped;
the Em Box Height test kept). German entry for Em Box Height.
The first baseline sits the em box top below the frame's top inset: the
font's BASE em box (idtp, else ideo + 1 em), else 0.88 em, for the
largest size on the first line. IDML FirstBaselineOffset="EmboxHeight"
imports and exports as itself; the footnote options list it and the
frame and footnote option commands take emboxHeight.
Conflicts: ui-egui dialogs.rs (next's numberingSection arm and the branch's cellOptions arm; the branch's
copies of the dialog test helpers already on next dropped, its cell options test kept); idml tests.rs and
the i18n tables appended at the end on both sides (both kept; the branch's Gap Tint: and Tint: rows that
next already had dropped).
style.cell.create/edit stroke and style.table.create/edit border use the
table.setCell stroke parser: type, gapColor (alias gapSwatch) and gapTint, with
the same validation. A bad value is an error and changes nothing.
- object.reorder {ids, above|below: id | index, layer?}: restacks sibling
objects in front of or behind a target, or at an index counted from the
top of a layer, moving them to that layer. Group members stay in their
group. Bad input is an error and leaves the document unchanged.
- layer.move rejects a missing id or an out-of-range index.
- Layers panel: drag a layer row to reorder layers, an object row to
restack it or move it to another layer, and a filled selection square
onto a layer to move the selection there; a line or box shows the drop.
Groups expand to list their members. Layers list top (frontmost) first,
matching the stacking order.
CellStroke and cell/table style edge attributes carry gap colour and gap tint
(IDML ...EdgeStrokeGapColor/GapTint, ...BorderStrokeGapColor/GapTint). The table
renderer and PDF export draw every stroke type on cell edges, with the gap colour
under dashes, dots and stripes.
table.setCell validates stroke values, takes gapColor/gapTint and an edges list
(top/left/bottom/right are the target range's outer sides; innerHorizontal and
innerVertical the lines between its rows and columns). table.getCellStroke reports
the shown values of the chosen edges, null where they differ.
Paste and Paste in Place always put the objects on the first spread,
whatever page was showing. They now go to the spread in view, or to
the one a caller names with `spread`. With facing pages the objects
keep their distance from the spine, so they stay on their side of the
spread, also on a first or last page that sits alone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflict: ROADMAP.md: next's FONT1-3 lines with the branch's CJK1 line
Conflict: docs/cjk.md: the branch's rows, with next's aki below and Japanese composer text kept in the leading model row
Conflict: crates/fonts/src/fontdb.rs: both fields (family/style aliases and the ICF cache)
Conflict: crates/compose/src/ruby.rs: the branch's ruby module; its PlacedGlyph (and kenten.rs's) carry next's rendered_char
Conflict: crates/compose/src/lib.rs: modules both; rtl and para_block both; the branch's grid placement (gyoudori, grid references) replaces next's snap, its paragraph-gyoudori span uses next's line_metrics with mark leading and #330's aki below advance; a wrap push moves the line by whole grid lines and its grid end with it; next's trimmed spaces and drop cap, then the branch's ruby and kenten annotation
Conflict: crates/compose/src/shape.rs: next's pieces loop and StyleRuns with the branch's auto tate-chu-yoko split (after marks join their base) and fit, and Upright mode in every shape_segment call; next's label fallback passes the mode on
Conflict: crates/compose/src/tests.rs: both sets of tests appended at the end
Conflict: crates/idml/src/export.rs: next's metadata and text variable writers, then the branch's CJK settings writers
Conflict: crates/idml/src/tests.rs: both tests
Conflict: crates/ui-egui/src/dialogs.rs: the branch's Ruby dialog default section (next's duplicate characterStyleOptions default dropped); next's section arms with the branch's style_cjk::section_ui
Conflict: crates/ui-egui/src/lib.rs: next's missing-fonts test; the branch's side repeated control_bar_shows_its_second_row (next's newer copy stays) and key_names_sent_as_text_are_dropped, whose IME version replaces next's copy in place
Conflict: crates/engine/src/cmd/file.rs: next's file.open params (InDesign .indd/.indt) with the branch's package-parts warnings
Conflict: crates/engine/src/cmd/interchange.rs: next's file.openIdml params (InDesign files) with the branch's warnings list; import_report reads the branch's Imported report, then next's resolve_pdf_crops; open_idml keeps next's .indd conversion and title, then takes import_report's warnings after the conversion's; next's comment on not saving over the .idml or .indd
Conflict: crates/engine/src/cmd/style.rs: both params notes in the paragraph style edit spec (startAt null, kinsoku null); create_para with next's set_json_over, continue_numbering and the branch's explicit_default_kinsoku; edit_para calls both helpers; both tests
Conflict: crates/ui-egui/src/dialogs.rs: next's section arms (advanced to bullets) and the branch's CJK section arm; next's paragraph helpers and paragraph_local before the branch's section_list (cjk flag, scrolling list; doc comment stays removed as on next)
The branch's "Lines:" row in the shared i18n table is dropped: next already has the key (drop caps).
Conflict: crates/engine/src/cmd/style.rs: next's create_para attrs (set_json_over) followed by the branch's continue_numbering
Conflict: crates/ui-egui/src/dialogs.rs: the branch's paragraph section helpers and sections before section_list (whose doc comment stays removed as on next); its tests, without its copy of paragraph_style_options_tabs_section_adds_a_stop_on_its_ruler (next has it from #343)
Conflict: crates/ui-egui/src/i18n.rs, i18n/it.rs, i18n/ja.rs: both blocks; the branch's [Default] rows dropped (next has the key from New Document)
The Tabs commands check the list (TabStop::checked_list) before they write it
and return that list, with the index of the stop they set in it, so the result
matches what the paragraph or style holds.
Conflict: ROADMAP.md: next's IDML interchange line with the branch's sentence on placed PDFs, $ID/ font names and packaged links appended; next's INDD line kept
Conflict: crates/engine/src/tests_idml.rs: next's drop cap test and the branch's two placed PDF tests
Conflict: crates/fonts/src/fontdb.rs: next's plausible/measured_top/typo_ascent and the branch's plain_family; next's canonical_family lookups, with plain_family in place of without_format_suffix in style_traits, face (two) and has_family; the branch's has_exact_family dropped (has_family uses canonical_family)
Conflict: crates/idml/src/import.rs: next's char_attrs (tab-split family and composite font names), falling back to names::font_family_in
Drop cap style through IDML as a Dropcap nested style, spaces after the cap, one-line caps, nested styles after the cap, own nested-style lists clearing an inherited drop cap style (cells and notes too), cleared styles round-tripping, tabs in right-to-left drop caps.
Conflict: ROADMAP.md: next's INDD, Interface language and Show CJK Features lines (the PR's main-merge resolution, already on next)
Conflict: crates/compose/src/lib.rs: next's warichu placement followed by the trimmed trailing spaces
Conflict: crates/compose/src/tests.rs: next's side; the PR's side repeats helpers and tests next already has
Conflict: crates/idml/src/import.rs: next's range_format
Conflict: crates/idml/src/tests.rs: next's side, with the PR's drop_caps_import_and_round_trip and its new drop_cap_fixture and nested-style clearing tests in place of next's older drop cap test
The style path of the Tabs commands writes its list through
ParaAttrs::set_json_over, the same call format_paras makes for
paragraphs, so TabStop::checked_list sees every list a Tabs command
writes.
guide.add takes orientation: both with point: [x, y] and adds a
horizontal guide through y and a vertical guide through x in one edit.
Cmd-drag from the ruler corner uses it.
Cancelling a drag, a preview or an IME composition restores the
document, its selection and now its revision. Revisions come from one
counter, so the numbers a cancelled preview used are never handed out
again and caches keyed by (uid, revision) never show a cancelled
preview.
The Type tool shows an input method's marked text in the story as a
preview of text.insert, underlined (the converting clause twice), with
the candidate window at the caret. The commit is one text.insert and one
undo step; a cancelled composition leaves the document as it was. Keys,
shortcuts, the clipboard and Undo wait while the IME composes; a click,
a tool or document switch, or any journaled command keeps the marked
text as typed. On macOS the app tells the input context to drop marked
text the tool kept.
With a split window, only the pane last clicked takes keyboard events
(both panes saw them, so typing went in twice).
The web build drops only real key names from text events, and nothing
while its text input has the keyboard, so autocompleted words survive.
The control channel's ui.ime, the headless MCP backend's ui.ime and the
MCP ime tool send IME events.
The placed PDF's asset stores its Crop to choice (crop, art, trim, bleed,
media, or the content bounds with visible or all layers) and where that
box sits on the page. The graphic spans the box: the screen, PDF export,
rasterised exports and clipping-path tracing draw only that part of the
page, so a larger frame doesn't reveal the bleed.
IDML export writes the choice as PDFCrop, with GraphicBounds spanning the
box. Import reads PDFCrop back; the engine finds the box on the PDF page
after import (and after relink or update) and maps it onto GraphicBounds,
or gives a graphic without bounds the box's size. Documents saved without
a choice load with the crop box. The Place PDF dialog offers the content
bounds too, and links.list reports the choice.
IDML has no drop cap style attribute. Import reads the nested style list's leading "through 1 Dropcap" entry as the drop cap style; export writes the drop cap style as that entry. The drop cap style counts as that entry when composing, so nested styles after it start after the drop cap.
Preferences > Units & Increments > Origin sets DocSettings.rulerOrigin
(document.preferences {rulerOrigin: spread|page|spine}, IDML
RulerOrigin). Rulers and the X/Y fields (Control, Properties, Info,
transform.set) measure from that origin plus the zero point; with a page
origin the horizontal ruler restarts on each page and an object measures
from the page it is on.
Cmd-drag (Ctrl) from the ruler corner adds a horizontal and a vertical
spread guide through the drop point. The live preview while dragging the
zero point is kept on the pasteboard like the committed value.
Translations for Origin, Spine and Lock/Unlock Zero Point.
The layout-parity files (ROADMAP, compose lib/tests, engine text, fonts fontdb, idml import/tests, canvas) resolve as in the merge of main into feat/layout-parity.
Conflict: ROADMAP.md: as feat/layout-parity's merge
Conflict: crates/compose/src/lib.rs: as feat/layout-parity's merge; this branch's trimmed trailing spaces follow main's warichu::place and come before the drop cap splice
Conflict: crates/compose/src/tests.rs: both sides' tests
Conflict: crates/engine/src/cmd/text.rs: as feat/layout-parity's merge; this branch's TypingFormat/typing_format and main's warichu_cmd
Conflict: crates/fonts/src/fontdb.rs: this branch's styles/traits_of/linked_style over style_traits; style_traits falls back to the family without main's format suffix (exact_style_traits)
Conflict: crates/idml/src/import.rs, crates/idml/src/tests.rs, crates/ui-egui/src/canvas.rs: as feat/layout-parity's merge
Conflict: crates/ui-egui/src/control.rs: main's page_index and automation_contract_tests, then this branch's tests module
Conflict: crates/ui-egui/src/lib.rs: this branch's ClipboardFn and main's Inbox of ImportedFile
Conflict: crates/ui-egui/src/menus.rs: main's Quick Apply tests, then this branch's copy and paste keys test
Conflict: ROADMAP.md: this branch's Text engine, IDML interchange and Right-to-left lines; main's FID2, PDF export and Interface language lines
Conflict: crates/compose/src/lib.rs: list labels as main's number_label/bullet_label/empty-paragraph arms, kept in this branch's list_label form that marks label glyphs; main's layout_line call (ends_para, forced_mid) and warichu::place, then the drop cap splice; rule above uses main's first-line column/end_x span with this branch's rule_color; caret(): drop-cap branch, then main's stacked-row metrics
Conflict: crates/compose/src/tests.rs: both sides' tests
Conflict: crates/engine/src/cmd/text.rs: type.para doc lists the drop cap fields and main's rule fields
Conflict: crates/fonts/src/fontdb.rs: both (plausible/measured_top/typo_ascent and without_format_suffix)
Conflict: crates/idml/src/import.rs: main's table style regions, borders and alternating fill/stroke attrs (this branch's alt_fills helper dropped, unused); underline/strikethrough colour from main with this branch's tint(); frame_options takes the object-style chain's TextFramePreference elements, the frame's column rule colour resolved after it
Conflict: crates/idml/src/tests.rs: main's tests, plus this branch's added tests and helpers
Conflict: crates/ui-egui/src/canvas.rs: main's compose::highlight_quads, then this branch's drop-cap highlight
The zero point is document state (DocSettings.zeroPoint, zeroPointLocked):
an offset from the top-left corner of each spread's pages, so every
spread measures from the same relative place and split views share it.
view.zeroPoint {at, reset} and view.lockZeroPoint {on} set it; moving it
is not an undo step and undo/redo keep it. Values are kept on the
pasteboard, from commands, files and IDML.
Rulers and the X/Y fields (Control, Properties, Info, transform.set)
measure from it. IDML reads and writes Document ZeroPoint.
Dragging from the ruler corner places it where released, with crosshair
lines while dragging; a click that stays in the corner does nothing; a
double-click resets it; the corner's context menu locks it.
style.paragraph.create and style.paragraph.edit store an explicit
startAt: null as Continue from Previous Number, so it overrides a Start At
the style would otherwise inherit.