Commit Graph
4115 Commits
Author SHA1 Message Date
aiongg 4014dac6c2 Compose: under the Japanese composers a line sits the upper line's leading below it
Under the Aki Below leading model a line's leading is the space below it, so the
next line's reference point sits the upper line's leading below the upper line's
(InDesign's Japanese-composer output measures this in four corpus documents).
The first line in a frame or column places itself with its own leading; space
before and after adds on top, and the baseline grid snaps the result. The other
leading models advance by the lower line's leading as before.
2026-10-10 16:22:17 +00:00
aiongg 2667484d64 Merge feat/style-sections: Paragraph Style Options gains the remaining sections
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)
2026-10-10 16:22:08 +00:00
aiongg f7e17acfd3 Tabs: the commands return the tab list as stored
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.
2026-10-10 16:21:34 +00:00
aiongg 03697c53f2 Merge #343 update: tab lists checked through paragraph attributes and styles
Conflict: crates/doc/src/attrs.rs: next's TEXT_COLOR and the PR's tab-stop limits and TabStop checks
2026-10-10 16:20:39 +00:00
aiongg c3c24a0be8 Merge fix/idml-interchange: $ID/ font names, placed PDF page and crop, packaged IDML links (#338, #339, #340)
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
2026-10-10 16:20:17 +00:00
aiongg 4e5e040a79 Integration: Numbering & Section Options keeps Enter and Escape for an open popup
#342's Numbering & Section Options draws its OK and Cancel beside the options and reads Enter and Escape there, before the footer that #325's update guards. The same popup_open guard applies to those checks, so Enter and Escape in an open menu or name field go to the popup.
2026-10-10 16:19:06 +00:00
aiongg 4a6fef0ba1 Merge #325 update: popup Enter/Escape guard, presets as engine commands
Conflict: ROADMAP.md: the PR's New Document line (file.savePreset, file.deletePreset), next's Numbering & Section Options and chapter numbering lines
2026-10-10 16:19:02 +00:00
aiongg d241a22f80 Merge #83 update: drop cap fixes
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
2026-10-10 16:18:49 +00:00
aiongg 48de197a2f UI: ruby, kenten, shatai and grid settings in the style dialogs and the Ruby dialog 2026-10-10 16:17:43 +00:00
aiongg 64cc973df8 Tabs: style tab lists go through the same check as paragraph tab lists
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.
2026-10-10 16:15:02 +00:00
aiongg a2ff7d03f8 Drop caps: nested-style lists in table cells and notes clear an inherited drop cap style too
The IDML import pass walks each story's table cells, footnotes and
endnotes (nested, depth-bounded) as well as its own paragraphs.
2026-10-10 16:11:43 +00:00
aiongg 55fa985e38 Bullets and numbering: the tab position survives IDML
IDML has no attribute for the list Tab Position. Export writes it as the
left stop the composer adds for it, in the TabList of each style or
paragraph that sets the list type, the tab position or the tabs; a level
that ends an inherited list writes its tabs without the stop. Import
reads it back as an ordinary tab stop, so the composed text is the same.
2026-10-10 16:10:26 +00:00
aiongg fac18790bb Merge feat/cjk-typography into feat/cjk-typography-ui 2026-10-10 16:09:30 +00:00
aiongg 9c935ce50c CJK: leading model space below measures from the em box top, space above from the bottom 2026-10-10 16:09:30 +00:00
aiongg e20183033f Rulers: the two guides from the corner are one undo step
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.
2026-10-10 16:05:50 +00:00
aiongg 6dda095396 Engine: a cancelled gesture puts back the revision it began at
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.
2026-10-10 16:05:46 +00:00
aiongg 1276181cde Text: IME composition in place, commit as one step (#322)
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.
2026-10-10 16:05:36 +00:00
aiongg c846b92388 Merge feat/cjk-typography into feat/cjk-typography-ui 2026-10-10 16:03:53 +00:00
aiongg 29a75b3607 UI: every paragraph border, shading, span and list setting in the dialogs
Paragraph Style Options › Paragraph Border and Paragraph Shading,
Span Columns and Bullets and Numbering show every attribute of the
model. The same sections open for the selected paragraphs from the
Paragraph panel menu and the Type menu: Paragraph Borders and
Shading…, Span Columns… and Bullets and Numbering…. The bullet
character can be picked from the font's glyphs in the Glyphs panel's
grid. New strings are translated.
2026-10-10 16:03:11 +00:00
aiongg 8f93548572 Paragraph borders, shading, span space and list levels: model, layout and IDML
Borders gain a stroke type (built-in or a document stroke style), cap,
join, gap colour and tint, a shape and size per corner, column or text
width, top and bottom edges, closed boxes in each part of a split
paragraph, and one box for consecutive paragraphs with the same
settings. Shading gains the same corners, edges and width, Clip to
Frame, and Do not Print or Export. Boxes are drawn once the lines are in
place, as filled paths where they aren't plain rectangles.

Span and split paragraphs keep at least their space before and after
from the column text. Lists have levels that number on their own and
restart after a higher level, ^1 to ^9 in the number text, a character
style for the label, a bullet font, left, centre or right alignment at
the line start, and a tab position for the text after the label.

All attributes load from older files with their defaults and
round-trip through IDML, apart from the tab position.
2026-10-10 16:03:11 +00:00
aiongg 4c4dedaa93 Ruby: clears kenten on the same side, stays with the kana it overhangs, overprints in Overprint Preview 2026-10-10 16:02:52 +00:00
aiongg b720ff6147 CJK: ICF top and bottom from the font's BASE table for grid and character alignment 2026-10-10 16:02:52 +00:00
aiongg 5365d0f7ca Drop caps: tabs in right-to-left drop caps advance to the tab stops
Measured from the column's right edge, past the right indent.
2026-10-10 15:57:10 +00:00
aiongg f9fb640229 Drop caps: a cleared drop cap style round-trips through IDML
A drop cap style set at a level ([None] included) restyles the leading Dropcap entry of the nested style list, in export and when composing. A paragraph or style without nested styles of its own that clears an inherited drop cap style is written with the inherited list, whose Dropcap entry it sets to [None], or with an empty list.
2026-10-10 15:57:10 +00:00
aiongg 276b6f3170 Drop caps: an IDML nested style list of its own clears an inherited drop cap style
A style or paragraph whose nested style list has no leading Dropcap entry gets no drop cap style, since its list replaces the inherited one, Dropcap entry included.
2026-10-10 15:57:07 +00:00
aiongg d9bc53d7f8 Ruby: placement, spacing, font, size, overhang, scaling and colour settings with JLReq layout and IDML 2026-10-10 15:56:16 +00:00
aiongg 289c4a6aa4 IDML: a placed PDF keeps its crop choice
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.
2026-10-10 15:52:40 +00:00
aiongg 31a58a8501 CJK: kenten settings, shatai, auto tate-chu-yoko, rotate roman, roman word break and grid references 2026-10-10 15:50:32 +00:00
aiongg 70e41a297d Drop caps: nested styles start after the drop cap style
Test that the drop cap style counts as a leading "through 1 Dropcap" nested style, and describe the IDML form in ROADMAP. The previous drop cap commit also makes the cap reach down the text's leading rather than to where line N is set.
2026-10-10 15:50:14 +00:00
aiongg bcdbb68eee Drop caps: one-line caps keep a smaller size and set their tabs
A one-line drop cap keeps its characters' own point size when it is smaller than the text (verse numbers), and tabs inside a left-to-right drop cap advance to the paragraph's tab stops.
2026-10-10 15:50:05 +00:00
aiongg 21863563f3 Drop caps: a space after the cap doesn't widen the indent
Spaces right after the drop cap are set at its size on its baseline and leave the lines beside it starting where its characters end.
2026-10-10 15:49:48 +00:00
aiongg 7636af73e4 Drop caps: the cap style goes through IDML as a Dropcap nested style
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.
2026-10-10 15:48:58 +00:00
aiongg ade9eb6e69 Rulers: Spread, Page or Spine origin; Cmd-drag the corner for guides
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.
2026-10-10 15:41:54 +00:00
Michael TownshendandGitHub Copilot f05e8f5d98 #201: route macOS text clipboard commands through egui
Forward native Copy/Cut/Paste for active canvas text through egui so the desktop integration can use the system clipboard. Add regression coverage for the native clipboard event path.

Co-authored-by: GitHub Copilot <198982749+Copilot@users.noreply.github.com>
2026-10-10 17:41:14 +02:00
aiongg 5551cf9a25 Merge upstream main into feat/text-editing-and-frames
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
2026-10-10 15:36:43 +00:00
aiongg cd23a5fbbf Tabs: tab stops set through paragraph attributes are checked like the Tabs commands 2026-10-10 15:35:05 +00:00
aiongg 7f23a5e05b Merge upstream main into feat/layout-parity
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
2026-10-10 15:34:23 +00:00
aiongg 209f758727 Rulers: a document zero point you can drag, reset and lock
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.
2026-10-10 15:34:12 +00:00
aiongg 3ca0a4374e UI: CJK sections in Paragraph and Character Style Options 2026-10-10 15:32:32 +00:00
aiongg 7ed9f37d43 UI: Paragraph Style Options gains the remaining sections
Advanced Character Formats, OpenType Features, Underline Options and
Strikethrough Options reuse the Character Style Options sections. New
sections: Paragraph Border, Paragraph Shading, Keep Options, Span Columns
and Bullets and Numbering. The swatch menu is shared with Paragraph Rules.
The Span Columns layout option has its own Japanese caption.
2026-10-10 15:32:23 +00:00
aiongg 4f1be4b454 Styles: startAt null in a paragraph style continues numbering
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.
2026-10-10 15:32:23 +00:00
aiongg a80d21161f IDML: a spread missing from the package is reported, and part names match leniently 2026-10-10 15:32:20 +00:00
aiongg d03dd226c5 Text: the paragraph mark's size counts in its line's auto leading
The paragraph mark is a character of its paragraph's last line, so its leading (auto: its size times the auto leading percentage) takes part in the line's largest-leading rule. It doesn't change the line's ascent or descent. Earlier lines of the paragraph are unaffected.
2026-10-10 15:30:32 +00:00
aiongg 53710aca6e Merge #336 (feat/cjk-mode) for the CJK features preference 2026-10-10 15:20:01 +00:00
aiongg 7d5af8961c Package: the packaged IDML links its images instead of embedding them
The images are already copied to the package's Links folder, and the
IDML links point there; it no longer also embeds a copy of each one.
2026-10-10 15:18:18 +00:00
aiongg 0f11a4599f IDML: placed PDFs keep their page and crop
Export writes a PDFAttribute with the page number and PDFCrop="CropPDF":
the graphic bounds already span the page's crop box, so the frame clips
to the chosen trim, bleed or media box as before. Import reads the page
number back instead of always showing page 1.

A placed PDF page that the PDF does not have (a hostile PageNumber, or
any document holding one) is left out of PDF export with a warning
instead of failing the whole export.
2026-10-10 15:18:18 +00:00
aiongg 580db95c71 IDML: font names with the $ID/ prefix resolve
AppliedFont values like "$ID/Arial" import as the plain family, in
paragraph and character styles, text ranges and composite font entries.
The font database also looks a family up without the prefix, so
documents that already hold one draw in the named font.
2026-10-10 15:18:18 +00:00
aiongg c205b53b10 Integration: German and Japanese entries for the Numbering & Section Options strings
#342 adds twelve Layout › Numbering & Section Options strings to the shared table; next's de.rs
(#311) and ja.rs (#272) keep a row for every shared key. The rows carry over the shared table's
German and Japanese columns, so lookups are unchanged.
2026-10-10 14:56:33 +00:00
aiongg ba8e5e90ef Merge #344: fix(ui): Highlight swatch list rows and keep panels clear of scroll bars 2026-10-10 14:56:15 +00:00
aiongg 816ce1b756 Merge #342: feat(ui): Lay out Numbering & Section Options like InDesign's
Conflict: ROADMAP.md: kept both entries (New Document, then Numbering & Section Options).
Conflict: crates/ui-egui/src/dialogs.rs: width match keeps "newDocument" => 960.0 and adds "numberingSection" => 560.0, dropping the PR's "newDocument" if is_rtl => 380.0; tests keep next's helper block and add only the PR's numbering_and_section_options_keep_their_actions_in_view.
Conflict: crates/ui-egui/src/i18n.rs: kept both TABLE tail blocks (File › New › Document, then Layout › Numbering & Section Options).
Conflict: crates/ui-egui/src/i18n/it.rs: kept both tail blocks.
2026-10-10 14:56:15 +00:00