Commit Graph
1861 Commits
Author SHA1 Message Date
aiongg dadb2993e9 DES-10 T6: Links status by hash, update, embed and unembed for linked graphics
links.list gains storage; a linked graphic's status comes from the open
check while its bytes are unchanged, else from its files: OK by size and
time without reading, else by content hash; Modified or Missing. Update,
Relink and Relink to Folder read the file into a new linked version with
a new hash and proxy. Embed checks the file first and keeps the link
record; links.unembed links to the original when it holds the same
bytes, else writes them into dir. Not on the web.

(cherry picked from commit 8d617b872f7d7b01b9551d07a3e82be03e1c1362)
2026-11-14 06:46:11 +00:00
aiongg ade2d3cfd4 DES-10 T6: graphics placed from a file link to it by default
File > Place, the place cursor (place.load, grid, contact sheet), media,
media posters and table graphic cells record the file's absolute path,
its path relative to the document, size, time and content hash, and a
proxy image, and keep the bytes read for placing in the linked-bytes
store for the first draw. embed: true keeps the bytes in the document
with the link record. base64 bytes and the web always embed.

(cherry picked from commit 4f5bd99088b2f32bece3be08258ec66c15dd3b44)
2026-11-14 06:46:11 +00:00
aiongg 957e073664 DES-10 T9: IDML and INDD imports link the graphics they reference
(cherry picked from commit 995b248cd3b591cae6dd7dd0f9a1b10cac89f22d)
2026-11-14 06:45:09 +00:00
aiongg da524dec9b DES-10 T7: save, open, recovery and migration for linked assets
Save records each link's absolute path and its path relative to the
destination; linked assets write their record and proxy only, and Save a
Copy {embedLinks: true} copies every linked file in (failing on a missing
or changed one). On the web, links stay links with a warning.

Recovery snapshots record links as a save to the document's own file
would, never their originals; recovered documents resolve relative links
against the recorded document path.

Open (and Revert, Open Bytes, Recover) points each linked asset at its
file without reading it: a file with the recorded size and time is the
one; one with the recorded size and another time is hashed on a
cancellable background thread (native_links), absolute path first, and
the first hash match wins and keeps its new time. No match is Modified.
Status is kept on DocState::links for the Links panel; links.progress
applies results and gives the status-line notice once.

Documents saved before linked storage (embedded assets with a link and
no content hash), opened from a file, get a background byte comparison;
confirmed images get their hash and a proxy and save as links, and their
in-memory bytes become a link after that save. Changed or missing files
stay embedded.

Based on #1108 by ForestParks.

(cherry picked from commit 3a453b7f3752d255b6f74cfb55ea2459c5d9a074)
2026-11-14 06:25:01 +00:00
aiongg 3f1cbb4d23 Tests: Word fixtures carry the document relationships part
(cherry picked from commit 0ba9ad4fe5)
2026-11-14 06:23:07 +00:00
aiongg 7579d0d987 Place: test helper avoids unwrap; fmt 2026-11-14 06:22:51 +00:00
aiongg f024edb544 Place: arrow keys cycle the loaded images between drags (place.cycle) 2026-11-14 05:56:46 +00:00
aiongg 91f78b2db9 Place: Escape drops the current loaded image and loads the next (place.skip) 2026-11-14 05:54:59 +00:00
aiongg 7f0c2818f2 Place: closing a background document keeps the active document's place cursor 2026-11-14 05:50:35 +00:00
aiongg c8f105dd65 Merge pr-2308 (place contact sheet) into multi-place 2026-11-14 05:49:47 +00:00
aiongg 2ee301bd4b Merge pr-2302 (place cursor queue) into multi-place 2026-11-14 05:49:14 +00:00
aiongg b9a5bcbecc DES-10 T3: linked asset store and the engine's file loader
AssetData::linked carries a LinkedSource (absolute and relative path, document,
size, fingerprint, content hash). Linked bytes load through a process-wide
single-flight LRU store (512 MiB, 1 GiB per file) and the Loader the engine
installs in Session:🆕 absolute path first, then relative; a changed
fingerprint is checked against the hash, and other bytes are Modified.
Proxy.data is an AssetData so its decodes have a key of their own.
2026-11-14 05:37:36 +00:00
aiongg 55a0c7da3d DES-10 T2: port asset byte users to AssetData
Export, import, links, preflight, alpha wrap and the UI read bytes with
AssetData::load; every asset is still embedded.
2026-11-14 05:15:03 +00:00
Dylan M. Taylor 32274e843a Merge codex/designcraft-craft-libs into origin/main: cut over document formats and codecs to craft-libs 2026-11-14 02:13:28 +00:00
Dylan M. Taylor 77991abe6f fix(file): preserve legacy JSON on INDD paths 2026-11-14 00:40:59 +00:00
Dylan M. Taylor b681b10733 Pin DesignCraft shared codecs to merged fixes 2026-11-13 23:53:29 +00:00
AlPaka1234 dbdc5b697a Tools: snap Gap tool drags to active snapping settings (#2637) (#2749)
* Tools: snap Gap tool drags to active snapping settings (#2637)

* Tools: reject unreachable Gap tool snap targets beyond resize clamp

* Tools: preserve raw Gap tool delta when no reachable snap matches
2026-11-13 20:58:31 +01:00
Dylan M. Taylor bfbb831e54 Use shared neutral SVG scene for paste 2026-11-13 04:25:01 -05:00
Dylan M. Taylor 2769d0b88f Move DTD and raster encoding to craft-libs 2026-11-13 04:13:55 -05:00
Dylan M. Taylor 916749b2d0 Delegate XML parsing and PPTX writing to craft-libs 2026-11-13 02:13:35 -05:00
Dylan M. Taylor 3eaba67f58 Fix Clippy range loop in path orientation 2026-11-13 02:05:13 -05:00
Dylan M. Taylor 08a65d45a8 Route spreadsheet extensions through shared registry 2026-11-13 01:56:22 -05:00
Dylan M. Taylor a23b40e29a Use shared CSV and TSV format mappings 2026-11-13 01:52:51 -05:00
Dylan M. Taylor 29e0198952 Delegate delimited text parsing to craft-csv 2026-11-13 01:50:15 -05:00
Dylan M. Taylor bfef83bfd1 Use shared format probes for document opens 2026-11-13 01:46:50 -05:00
Dylan M. Taylor 3028b5328c Format shared registry dispatch 2026-11-13 01:45:29 -05:00
Dylan M. Taylor 44fd4aec60 Route CLI format dispatch through shared registry 2026-11-13 01:42:51 -05:00
Dylan M. Taylor d373506feb Route UI format dispatch through shared registry 2026-11-13 01:39:41 -05:00
Dylan M. Taylor aff7435b81 Route file dispatch through shared format APIs 2026-11-13 01:34:50 -05:00
.CooCoo 67a5cb273e Tables: table commands are disabled with the caret in footnote text (#2706)
Footnote text is addressed as a cell, so with the insertion point in a
footnote the table commands (Insert Row, Delete Column, Merge Cells,
Table Options, Select Table, table styles) were enabled and then failed
with "no table 18446744073709551615". They are now disabled with "place
the insertion point in a table", as the cell commands already were. The
caret's footnote offset is no longer looked up in the main story either,
where it could land on a table's paragraph. table.get and the other
commands that take any selection report the same message instead of the
footnote address. A call that names a table still runs.
2026-11-12 17:27:13 -05: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
.CooCoo 66b8c8ba3e Object styles: checks and fixes for corners, strokes and the style dialog (#2721)
- Corner options use path order for a path with more than one subpath, so
  a second rectangle no longer takes the first one's corner order.
- IDML export writes EnableStrokeAndCornerOptions="false" for a style
  without corners, so it does not take corners from its based-on style on
  import.
- style.object.create and style.object.edit refuse a stroke gap tint
  outside 0 to 1 and a stroke type field that its kind does not take, as
  object.stroke does. An edit that changes nothing returns restyled: 0.
- New Object Style and Object Style Options read a bare number in the
  document's ruler unit, keep a Text Frame General measurement that was
  not edited at its exact value, and New Object Style refuses a name
  another style has.
- Clear Overrides in the Object Styles panel is enabled when any selected
  object differs from its style.
2026-11-12 17:25:39 -05:00
Dylan M. Taylor e6ab0d263e Merge branch 'main' into feat/duplicate-layer 2026-11-12 16:43:33 -05:00
Dylan M. Taylor 9847f972da Update recovery test for explicit write conflict 2026-11-12 16:27:52 -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 07d264fd23 Copy: bound the anchored-object walk through cells and notes
Copying a story gives the objects anchored in its table cells and
notes fresh ids down to 64 levels, as the table copy does. A copy whose
stories below that level hold anchored objects, tables or notes is
refused with the nested-too-deeply error instead of recursing without
limit.
2026-11-12 12:57:17 -08:00
dotCooCoo b30d39fdec Layers: Duplicate Layer maps copies by the original's anchors and tables
object::renumber now gives a story copy's anchors and tables new ids.
Duplicate Layer keys each copied anchor by the original anchor's id,
so copied cross-references point at the copied paragraph, and pairs
copied tables with the originals in order, so objects anchored in
table cells keep their live captions. A copy that renumber reports
incomplete is refused with the nested-too-deeply error.
2026-11-12 12:48:41 -08:00
dotCooCoo ba4f45e522 Merge main into feat/text-frame-options-type-tool 2026-11-12 12:45:20 -08:00
Dylan M. Taylor 213f3b75a3 Report recovery writes owned by another session 2026-11-12 15:43:43 -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
Dylan M. Taylor 6790d009fe Merge pull request #2651 from dotCooCoo/fix/placed-image-resolution
Place: images come in at the resolution stored in the file
2026-11-12 15:25:55 -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 b5fad8e858 Use mutable subpath iteration for current Clippy 2026-11-12 19:45:08 +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