* refactor(ui): split shortcut set import into sort, apply and conflict steps
Resolves SonarCloud rust:S3776 on import (ui-egui/src/shortcut_import.rs).
* refactor(ui): split drop caps and nested styles dialog into row helpers
Resolves SonarCloud rust:S3776 on drop_caps_and_nested_styles (ui-egui/src/dialogs.rs).
* refactor(ui): split draw_guides into bleed, grid, overlay and guide helpers
Resolves SonarCloud rust:S3776 on draw_guides (ui-egui/src/canvas.rs).
* refactor(ui): split control_paragraph into alignment, indent, drop cap and shading helpers
Resolves SonarCloud rust:S3776 on control_paragraph (ui-egui/src/chrome.rs).
* refactor(idml): move graphic layer option tree out of image_el
Resolves SonarCloud rust:S3776 on image_el (idml/src/export.rs).
PDF/X and CMYK groups keep this branch's approach: krilla's serialize
settings (pdfx::print_settings) write the CMYK page and transparency
groups, the GTS_PDFX output intent and the PDF/X Info and XMP entries.
make_pdfx4 adds only the XMP dates, so main's title argument and its
output-intent, Info and pdfxid XMP edits are dropped, and both
cmyk_group_spaces calls after writer.finish() (Export PDF, Print
Booklet) stay removed. Main's new parts are kept: file_info_metadata
(also for Print Booklet, on top of the print settings), optional content
registration and layer errors, add_form_fields, and pdfx's fonts module.
Main's metadata panic test calls the two-argument make_pdfx4.
craft-libs and the krilla patch are pinned to storytold/craft-libs
e3b9e239; Cargo.lock is main's, relocked without updates.
* EPUB: Split Document in a paragraph style's Export Tagging
* EPUB: Split Document as a document setting (off, one style, or export tags)
The document stores EPUB Export Options › Split Document (DocSettings.epub_split):
off (one content file, the default), a single paragraph style, or the
paragraph styles' Export Tagging › Split Document flags. document.epubSplit sets
it as one undo step; file.exportEpub takes a split that overrides it for one
export. A Style setting follows a renamed style and a deleted style's
replacement. IDML reads and writes EPubExportPreference BreakDocument and
ParagraphStyleName. A split before a list item or preformatted line closes the
open list or block first, so each content file is balanced.
* EPUB Export Options dialog with Split Document before Export EPUB
File › Export EPUB… opens EPUB Export Options, seeded from the document's
Split Document setting: a Split Document checkbox with Single Paragraph Style
(and its style) or Based on Paragraph Style Export Tags. OK stores a changed
setting through document.epubSplit, then continues to the save dialog; Cancel
does nothing. app.exportEpub with a path skips the dialog. Docs and the
progress log describe the setting.
* EPUB: the navigation test exports one content file with Split Document off
* EPUB export from the menu passes its options (cover, split) to the engine
* EPUB: Split Document on a style's EPUB tag map counts when the style says false; a caller's cover: false stays
* Type: story Optical Margin Alignment with a size, and Ignore Optical Margin (engine, IDML)
A story's Optical Margin Alignment applies to every paragraph except those
with Ignore Optical Margin; hang amounts scale with the story's size.
story.options sets it, type.para and paragraph styles take
ignoreOpticalMargin. IDML imports and exports StoryPreference
OpticalMarginAlignment/OpticalMarginSize and IgnoreEdgeAlignment. The
per-paragraph opticalMargin switch keeps hanging at the text's own size.
Part of #947.
* Type: the Story panel, and Ignore Optical Margin in the Paragraph panel menu and Paragraph Style Options
Window > Type & Tables > Story sets Optical Margin Alignment and its size
for the stories of the text selection or the selected text frames through
story.options, and is disabled without either. type.selectionAttrs
reports the stories' values as storyOptions, null where they differ.
The Paragraph panel menu toggles ignoreOpticalMargin, and Paragraph Style
Options > Indents and Spacing has an Ignore Optical Margin checkbox.
Part of #947.
* ROADMAP: the story Optical Margin Alignment entry names its default and scope
File › File Info… opens a dialog with Document Title, Author,
Description, Keywords, Copyright Notice and Copyright Info URL, and the
document saves them. The new file.info command reads them with {} and
sets the fields it is given; "" or null clears a field, and keywords
are a list or one line split at semicolons and commas. file.info.get
returns the fields without editing the document, so opening the dialog
does not end a Data Merge preview.
Export PDF, PDF/X-4 and Print Booklet write the title, author,
description and keywords into the PDF's document information and XMP.
EPUB export takes the title and author from File Info, and HTML export
takes the title. A title or author given to the export replaces File
Info's, and an empty Document Title leaves the document's name as the
title. Export PDF's dialog no longer sends the document's name as the
PDF title, so the PDF takes its title from File Info; the file name
still comes from the document's name.
* Anchored objects: Relative to Spine mirrors custom positions on right-hand pages
* Anchored objects: page side from the frame's spread position; footnote cache keyed by page side
The setting was imported and editable but never read: the composer, the
canvas grid and baseline snapping measured the grid from the page top.
BaselineGrid::origin gives the first line on a page (start, plus the
page's top margin for Top Margin), and all three use it. The composition
cache tracks the setting and the pages' top margins.
Also adds a left-to-right facing-pages guard test for mirrored margins
and the right parent page's guides and running head.
A cell's text rotation (Cell Options › Text › Rotation) was already read from
IDML and written back, but only 0 is composed, so an imported form's narrow
header columns of vertical labels came in horizontal and wrapped mid-word
("Eingela / ngt am") — and nothing anywhere said why. The reporter's file has
30 such cells.
Composing rotated cell text is a larger change than this. What this does is
stop it being silent, and let the value be set from the API:
- the IDML import reports it once per file: "2 table cell(s) have rotated text
(Cell Options › Text › Rotation): the angle is kept and written back, but the
text is composed horizontally";
- `table.setCell` takes `rotation` (0, 90, 180 or 270, any other angle refused,
negatives and multiples normalised), which nothing could set before;
- `table.get` reports each cell's rotation, so a round trip can be checked.
Tests: the angle through an export and back with the warning counted once for
the file (and no warning when no cell is rotated), and the command's accepted
and refused angles. Each fails without its own part.
* View: Lock Guides and Lock Column Guides are commands (#1096)
view.lockGuides {on?} (Cmd+Alt+;) sets the Lock Guides UI state the Properties panel and ruler-guide drags use. view.lockColumnGuides {on?} is a document setting, on by default, saved with the document, not an undo step, and read from and written to IDML ColumnGuideLocked. Both are in View > Grids & Guides with checkmarks.
* View: Lock Column Guides is translated wherever Lock Guides is (#1096)
* View: Lock Column Guides is undoable (#1096)
* ROADMAP: the progress line lands in one commit after the guide PRs
* IDML: keep column guides that were dragged off centre (#1096)
InDesign records dragged column guides in `MarginPreference ColumnsPositions`,
as pairs of offsets from the margin box's left edge. The importer discarded them
and divided the columns evenly, so a page whose gutter the designer had moved
came back with it in the middle: on a 450 pt margin box, `0 150 170 450` was
read as columns at 215 and 235.
`Columns::positions` already existed, documented as "Custom column positions
(after dragging column guides)", but nothing set it and nothing read it. Now
`Page::column_rects` returns the custom rects when they are set — that one
method is what the canvas guides, snapping, threading and the first frame of a
placed story all go through, so they follow the dragged gutter — the importer
fills it, and the exporter writes the page's real positions instead of
recomputing an even split, so the round trip keeps them.
`layout.marginsAndColumns` clears them when a count or gutter is set, which is
what InDesign's Margins and Columns does. Without that the stale positions would
outrank the new value and the dialog would look broken.
Verified against InDesign-authored IDML rather than assumed, which settled two
things. The attribute is written whether or not anything was dragged — a real
page's values are exactly its even split — so an even set is dropped rather than
marking every imported page custom and freezing its columns; the tolerance for
that comparison only absorbs float noise, about 1e-14 pt on that page. And
`<Guide>` is a `<Page>` child, not a `<Spread>` one, which is where this
importer already looks: the reporter's missing ruler guide was 099fbd2, landed
the day the ticket was filed, not a second bug.
That commit left `lib.rs` still listing guides as ignored on import; corrected.
* IDML: custom column positions are validated and round-trip (#1096)
Columns::positions are used only when they are 2 x count finite edges,
ascending from 0 to the margin box width (within 0.01 pt); anything else
is the even split, in Page::column_rects, on IDML import (bounded parse,
checked against the page's margin box) and on IDML export.
Columns::with_gutter_moved moves one gutter's pair of guides between its
neighbours for the coming column-guide command.
ROADMAP: drop four progress-log lines the #1121 merge duplicated and move
its line to the top.
* IDML: a page without its own margins checks the default's column positions against its width (#1096)
* ROADMAP: the progress line lands in one commit after the guide PRs
---------
Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
A stop can name a colour swatch (spot, process, tint, [Paper]) next to its
display colour. swatch.create {gradient}, object.gradient, the Gradient panel
and IDML StopColor keep the reference; renames follow it, swatch edits refresh
the stop's colour and a deleted swatch leaves a plain colour. The field is
optional and omitted for plain stops, so saved documents load and save as
before.