Commit Graph
1003 Commits
Author SHA1 Message Date
aiongg eefdfbb688 Docs: image cache keeps the levels drawn; canvas decodes in the background 2026-11-14 03:32:18 +00:00
.CooCooandDylan M. Taylor 5fb75aaefc Properties: Text Frame section shows inset spacing and vertical justification (#2661)
* Properties: Text Frame section shows inset spacing and vertical justification

Properties › Text Frame now shows the frame's inset spacing under the
columns: Top and Bottom, a link that makes all four the same, then Left
and Right. A non-rectangular frame shows one Inset, the distance its text
keeps from the outline. Four buttons set Vertical Justification to Top,
Center, Bottom or Justify. Type on a path shows neither.

The section also shows with the Type tool in a frame. There it changes
the frame that shows the insertion point, or every frame that holds part
of the selected text, as Object › Text Frame Options does.

* Properties: one Inset for a non-rectangular frame keeps the other sides

The single Inset sets only the top inset, the one kept from the
outline. A rectangular frame that holds part of the same selected text
keeps its own sides.

* Properties: the one Inset field and the composer share the frame outline test

FrameOutline::of_item builds an item's outline with its corner options
applied. The composer uses it to keep the top inset from the outline,
and the Properties panel uses it to decide whether a frame shows one
Inset, so the two give the same answer for every frame.

* Text Frame Options: frames taken while typing stay with their document

OK is refused when another document became active after the dialog opened, so the saved frame ids do not change frames in that document.

* Properties: the inset link starts linked again after Revert

The link's state is kept per document state instead of per document, so
a frame with equal insets in the reverted document starts linked.

* Text Frame Options: frames taken while typing are refused after Revert

Revert keeps the document's id but replaces its state, so a new frame
can reuse a saved frame id. The dialog now ties the frames to the
document state, and OK is refused after Revert as it is in another
document.

* Properties: the one Inset of a non-rectangular frame sets all four sides

The composer bounds a shaped frame's text by its rectangle less all four
insets as well as by the outline, so a single Inset that changed only the
top left hidden sides in place: lowering a uniform 96 pt inset to 0 kept
text overset. When every frame the field changes is shaped, it now sets
all four sides. With a rectangular frame among them, only the top inset
changes and each frame keeps its other sides.

* Fix text frame dialog merge resolution

* Keep text frame preview targets fixed

* Fix target field key inference

* Tests: Text Frame Options show four sides for text through an oval and a rectangle

With the Type tool and text selected through an oval and a threaded
rectangle, with the oval as the caret's stored frame, the dialog shows
the four inset sides, a changed Top leaves the rectangle's other sides
as they were, and the link stays off while the rectangle's sides are
uneven.

* Properties: the inset link starts off when another frame has uneven sides

With selected text that runs through several frames, the link of Text
Frame > Inset Spacing started linked when the frame the section shows had
four equal insets, and a changed Top then set all four sides of every
frame. The link now starts linked only when every frame the field changes
has four equal insets. Its state is kept for that set of frames, so a link
turned on for one frame does not carry over to selected text that also
runs through a frame with uneven sides.

---------

Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
2026-11-12 17:27:08 -05:00
Dylan M. Taylor e6ab0d263e Merge branch 'main' into feat/duplicate-layer 2026-11-12 16:43:33 -05:00
Dylan M. Taylor 076e653ac3 Merge remote-tracking branch 'upstream/main' into codex/integrate-2658b 2026-11-12 16:27:39 -05:00
Dylan M. Taylor 520aeeefe1 Merge pull request #2652 from dotCooCoo/feat/text-frame-options-type-tool
Text: Text Frame Options open from the Type tool and change the frame holding the caret
2026-11-12 16:09:26 -05:00
Dylan M. Taylor 9fe0dd5197 Merge pull request #2666 from dotCooCoo/fix/recovery-off-interface-thread
Recovery: the timer writes recovery data on a background thread
2026-11-12 16:01:55 -05:00
dotCooCoo ba4f45e522 Merge main into feat/text-frame-options-type-tool 2026-11-12 12:45:20 -08:00
Dylan M. Taylor 1f2900fb50 Merge main into baseline grid justification PR 2026-11-12 15:29:33 -05:00
Dylan M. Taylor 3ebeb2ac96 Merge pull request #2669 from dotCooCoo/feat/object-style-text-frame-options
Object styles: a style sets its frames' paragraph styles and Text Frame General Options
2026-11-12 15:25:59 -05:00
dotCooCoo 963dc57d3b Merge main into feat/text-frame-options-type-tool 2026-11-12 12:23:08 -08:00
dotCooCoo b1ca9dd97d Merge main into feat/duplicate-layer 2026-11-12 12:23:07 -08:00
dotCooCoo 07728ede66 Merge main into fix/recovery-off-interface-thread 2026-11-12 11:26:06 -08:00
Codex 2a2d73ead9 Merge main preserving incremental composition and alpha-wrap caching 2026-11-12 19:41:39 +01:00
FredApps 17b74601fb Merge pull request #2663 from dotCooCoo/feat/alpha-channel-text-wrap
Text Wrap: Alpha Channel contours follow a transparent image's visible pixels
2026-11-12 19:38:50 +01:00
dotCooCoo 5662fefdaf Merge main into feat/duplicate-layer 2026-11-12 10:27:44 -08:00
dotCooCoo 6446622464 Merge main into feat/object-style-text-frame-options 2026-11-12 10:14:11 -08:00
dotCooCoo d9afe26fc8 Merge main into feat/type-shortcuts-carry 2026-11-12 10:10:51 -08:00
autocraft-bot[bot] 99da9632b3 Merge main into feat/text-frame-options-type-tool 2026-11-12 18:05:59 +00:00
FredApps fa671a104c Preserve latest incremental-composition documentation 2026-11-12 18:15:44 +01:00
FredApps 2348380198 Merge main and preserve PR #2663 behavior 2026-11-12 18:14:28 +01:00
FredApps 268f432385 Merge main and preserve PR #2699 behavior 2026-11-12 18:14:28 +01:00
Codex 7f8b352196 Merge main and retain shortcut and preflight documentation 2026-11-12 18:13:30 +01:00
Codex e81b2ea99e Merge main and preserve table query options and ID guidance 2026-11-12 18:13:30 +01:00
dotCooCoo 970e98fcc5 Compose: say where reuse resumes after an edit that moves lines
An edit that moves lines into other frames composes on until a paragraph
starts in the same frame and place as before, or to the story's end, as
an_edit_that_moves_lines_composes_up_to_the_next_frame_the_text_starts_in
shows. The ROADMAP line no longer cites an issue about selection lag.
2026-11-12 09:12:05 -08:00
dotCooCoo 78c06c9701 Merge main into feat/duplicate-layer 2026-11-12 09:08:34 -08:00
FredApps a5be0905dd Merge pull request #2649 from dotCooCoo/fix/merge-image-fields
Data merge: an image field in text places the image, not its path
2026-11-12 18:05:02 +01:00
FredApps 31d4c7f7f4 Merge pull request #2665 from dotCooCoo/feat/paste-clipboard-image
Paste: images on the system clipboard paste as embedded images
2026-11-12 18:03:55 +01:00
FredApps e8276337a3 Merge pull request #2354 from dotCooCoo/fix/table-story-target
Reject ambiguous table IDs across stories
2026-11-12 18:02:30 +01:00
FredApps b70472bc52 Merge pull request #2647 from dotCooCoo/feat/non-rectangular-frame-inset
Text Frame Options: a non-rectangular frame shows one Inset field
2026-11-12 18:00:15 +01:00
FredApps b7321d31b8 Merge pull request #2659 from dotCooCoo/feat/justification-auto-leading-single-word
Justification: the dialog sets Auto Leading and Single Word Justification
2026-11-12 17:58:12 +01:00
FredApps 6e50ee3974 Merge pull request #2650 from dotCooCoo/feat/paragraph-value-checks
Text: paragraph spacing and justification values are checked
2026-11-12 17:57:35 +01:00
autocraft-bot[bot] af298fadce Merge main into fix/recovery-off-interface-thread 2026-11-12 16:00:29 +00:00
dotCooCoo 329806477e Data merge: an explicit QR role in text is refused, and the caret follows each field
data.placeholder.add with role qr and the insertion point in text bound
the QR code to the first selected frame, which the caret was not in. It
now returns "qr placeholders bind to a frame", as a QR field there does.

A field inserted at the insertion point left the caret before its
marker, so a second field went in front of the first. The caret now
moves past the marker, as after typing.

Docs: docs/agents.md.
2026-11-12 07:45:10 -08:00
Adithya Shankaran 92043b4c48 Automation roots: refuse COM¹ to LPT³ and a device name before a colon (#2383)
* Automation roots: refuse COM¹ to LPT³ and a device name before a colon

is_device_name missed COM¹, COM², COM³ and LPT¹, LPT², LPT³, which Windows reserves as it does COM1.
It also cut the name only at a period, so COM1: and NUL:x were not seen as device names.

* Credit my name in the About window

* Automation roots: document the device-name tests

CodeRabbit's docstring check counts the touched tests. same_component stays without a doc comment, because #2205 deletes that function and a doc line above it conflicts.

* Automation roots: record the device-name refusal

The MCP roots description and the roadmap now name COM¹ to LPT³ and a device name before a colon.
2026-11-12 15:09:39 +00:00
dotCooCoo e22a6362cc Compose: list every case that composes a story whole in gap 20
docs/gaps.md now lists the same cases as docs/architecture.md and
reuse::plain. A doc comment on rejoin says that a run style an edit uses
for the first time stops the reuse until the old composition reaches the
same style at the same index.
2026-11-12 06:53:12 -08:00
dotCooCoo ba81cb05e9 Compose: an edit composes only the paragraphs it can change
Every edit of a story composed it from its first paragraph, so a typed
character in a long threaded story cost as much as laying out the whole
story: 456 ms in a story threaded over 300 pages.

A composition that lays every paragraph once keeps its state before each
paragraph. After an edit, composing starts one paragraph above the first
changed one, in the kept state and with the lines above copied. It stops
at the first unchanged paragraph it reaches in the state kept for that
paragraph, and copies the lines from there on with their story offsets
moved by the length of the edit.

- The cache does this when only the story differs from its entry.
- Composed whole as before: stories with footnotes, endnotes, tables,
  anchored objects, named lists, tracked deletions, balanced columns,
  vertical justification other than Top, column rules, type on a path,
  spanning or split paragraphs, paragraph borders or shading, and a
  layout that goes back over a paragraph (keep options).
- An edit that moves lines into other frames is composed to the end of
  the story.

In a 240-paragraph story a typed character composes 3 paragraphs
(240 before).

Docs: docs/architecture.md, docs/gaps.md (gap 20), ROADMAP.

Refs #2298
2026-11-12 06:21:26 -08:00
dotCooCoo fad00dd646 Data merge: an image field in a table cell or a note is refused by name
With the insertion point in a table cell or a note, data.placeholder.add
with an image field returned "a hyperlink field can't go in a table cell
or a note". It now returns a message about image fields that names the
two ways on: bind the field to a frame, or pass role text to merge its
path. Nothing is inserted on the error, and role text still puts the
marker in the cell.

Docs: docs/agents.md and the command's params text.
2026-11-12 05:58:02 -08:00
dotCooCoo 95fdb96680 Text wrap: a clipped contour visits only the edges in each line band
A clipped contour now looks only at the edges of the outline and its clips
that reach a line band, and charges its work budget for those alone. An
outline with thousands of points elsewhere no longer exhausts the budget
and falls back to the projections' common part. The Text wrap row of
docs/typography-parity.md notes that an image over 40 megapixels, or one
that can't be decoded, follows the frame's path.
2026-11-12 05:19:22 -08:00
autocraft-bot[bot] 6b9c47fdb2 Apply review fixes
- crates/ui-egui/src/app/clipboard.rs
- docs/egui-037-migration-plan.md
2026-11-12 05:37:36 +00:00
dotCooCoo 544ebaf571 Text wrap: a relinked image's new outline recomposes the text around it
- each traced Alpha Channel outline has a serial number, and the composition signatures include the outlines in use, so a relink or link update that changes only the image data no longer leaves text laid out around the old image
- a wrap with the default alpha threshold is saved without it, as before thresholds were stored
- docs/typography-parity.md says Alpha Channel contours follow the image's visible pixels
2026-11-11 21:33:53 -08:00
dotCooCoo 630b5dfc43 Paste: images on the system clipboard paste as embedded images (#2204)
Paste ignored a bitmap on the system clipboard: a screenshot or an image
copied in a browser had to be saved and placed. Paste now places it.

- edit.pasteImage {base64, name?, spread?, at?} embeds the image in the
  selected empty frame, or in a new frame centered on `at` at its stored
  resolution (72 ppi when none) and at most 60% of the page width, as
  File > Place sizes it. Save and reopen and IDML export keep the pixels.
  Images over 64 million pixels and names without an image extension are
  refused.
- Ctrl/Cmd+V pastes the image egui delivers with no text, and Edit >
  Paste reads the clipboard's bitmap, or the first image file of a copied
  file list, when there is no text or the text is only an address.
- The menu read waits at most 1.5 s on its own thread, with one read in
  flight at a time.
- With a native menu, objects copied here still paste as objects until
  the pasteboard's change count shows a newer copy.
- ui.paste takes {image} for the control channel.
2026-11-11 20:50:24 -08:00
dotCooCoo 630c2e2bba Merge #1520 (object-style-paragraph-styles) onto main 2026-11-11 20:24:48 -08:00
dotCooCoo fc09aa9124 Merge main into feat/type-shortcuts 2026-11-11 20:23:58 -08:00
dotCooCoo 5d9fbb4d4e Docs: vertical justification moves grid-aligned lines by whole grid steps 2026-11-11 20:02:54 -08:00
dotCooCoo 3473b8d96e Text: Text Frame Options refuse an ids that is not a list of object ids
A call with an `ids` or `id` that is not an object id used to fall back
to the selected frame or the caret's frame. It now fails and leaves the
document unchanged.

The Properties panel's Text Frame section shows the frame Text Frame
Options change: with the Type tool, the frame the caret is drawn in.
2026-11-11 19:46:20 -08:00
dotCooCoo 27963d6d05 Justification: the dialog sets Auto Leading and Single Word Justification
Type > Justification and Paragraph Style Options > Justification now show
Auto Leading (0% to 500% of the type size) and Single Word Justification
(Align Left, Align Center, Align Right, Full Justify). Both fields show the
selected paragraphs' values, or blank where they differ, and OK writes
autoLeading and singleWordJustify only when they were edited. An Auto
Leading outside 0% to 500% keeps the dialog open with the reason.
2026-11-11 19:45:30 -08:00
dotCooCoo fd15245f4e Merge #2275 into fix/recovery-off-interface-thread 2026-11-11 19:08:22 -08:00
dotCooCoo 18be5b76f5 Text: Text Frame Options in a footnote or table cell change the frame that shows it
With the insertion point in footnote text or a table cell and no stored
frame on the caret, Text Frame Options changed the last frame of the
thread. They now change the frame the caret is drawn in: the frame that
holds the placed footnote, or the cell's own occurrence (not a repeated
header or footer), else the frame that shows the footnote reference or
the table's anchor.
2026-11-11 19:06:29 -08:00
dotCooCoo 7809f5e9da Text: frame columns, gutter, switches and indents are checked too
object.textFrameOptions refuses a gutter outside 0 to 15552 pt, a column
count outside 1 to 40 (it was clamped) and an on/off option that is not
true or false (it was skipped). The Control bar's Columns field stops at
40, as the other column fields do. The params text gives the ranges and
lists flexibleWidth.

type.para and paragraph style create and edit refuse left and right
indents outside 0 to 15552 pt and first and last line indents outside
-15552 to 15552 pt. A style made from the selection is checked with the
values it takes from the selection.

style.paragraph.apply and style.paragraph.redefine check that Minimum,
Desired and Maximum stay in order in each justification row they change,
over the overrides paragraphs keep, and refuse the change otherwise.
2026-11-11 18:42:32 -08:00
dotCooCoo 510269744a Text: Text Frame Options open from the Type tool and change the frame holding the caret
Object > Text Frame Options and Cmd+B are enabled with a text caret or a
text selection. Without ids or selected objects, object.textFrameOptions
changes the frame that shows the insertion point, or every frame that
holds part of the selected text, instead of every frame of the story.
The dialog shows that frame's options and keeps the frames it opened
with while the preview reflows the text.

An empty ids list and an id that is not in the document are refused.
Options a frame already has leave the document unchanged and add no
undo step.

Fixes #2396
2026-11-11 18:40:25 -08:00