Commit Graph
5363 Commits
Author SHA1 Message Date
aiongg fc85dc9853 DES-10 T2: AssetData and SourceKey hold asset bytes in the document model
Asset.data becomes AssetData (embedded bytes or a linked length, each
under a process-unique SourceKey), with the link_relative, link_hash,
storage and proxy fields. AlphaOutline names its source by SourceKey.
Dedup in assets.rs compares embedded bytes as before.
2026-11-14 05:15:03 +00:00
aiongg e9f58f5fd0 Build: restore designcraft_format::write for recovery; render decodes without naming the image crate
(cherry picked from commit 078f5994c4)
2026-11-14 04:37:44 +00:00
aiongg 1a156fa564 Merge remote-tracking branch 'upstream/main' into image-perf
# Conflicts:
#	crates/images/src/jpeg.rs
#	crates/images/src/lib.rs
2026-11-14 04:29:08 +00:00
aiongg 7d9a3ad302 Canvas: an overlay of an image that fails to decode shows nothing 2026-11-14 04:00:52 +00:00
aiongg e5576e7ec2 Images: wake a turned-away decode once, keep colour and zoom state right
- A request turned away as recently decoded schedules its wake only for the
  first decode of that image, level and epoch: a view larger than the cache
  (or more failed images than are remembered) no longer decodes every 2 s.
- A worker that takes a job while a wake is scheduled hands the timed wait on.
- A full decode drawn at level 0 from the cache leaves the zoom-in list.
- Pixels decoded under colour settings changed since are not cached.
- Shadows and glows drawn while an image in them decodes are not kept.
2026-11-14 04:00:52 +00:00
aiongg 51b4a95cd9 Canvas, Pages: overlays and thumbnails don't wait for image decodes
The content-grabber ghost and the place-gun thumbnail take their proxy
with mip_now: a level not cached yet decodes in the background and they
draw another cached level, or the outline, meanwhile. A stand-in texture
is drawn again when the image generation advances.

Pages panel thumbnails render with defer_images, so they no longer run
warm on the UI thread or wait at the decode gate. A thumbnail that drew
images still decoding renders again once more have finished, at most
every 250 ms.
2026-11-14 03:49:26 +00:00
aiongg 0a97679647 Images: harden the background decodes
- A panic anywhere in a background job, sizing and the wait at the gate
  included, marks the image bad. A guard takes the job off the busy
  list however it ends, and a thread that ends is counted out so
  another starts.
- Background decodes reserve their bytes where mip chooses the decode:
  the reduced JPEG estimate before a reduced decode (a JPEG without one
  goes to the full decode), the full peak before a full decode, nothing
  when a cached level is halved.
- A request turned away as recently decoded schedules one generation
  advance for when its window has passed, so its stand-in doesn't stay
  until the view changes. Emptying the cache (new colour settings,
  clear) starts a new epoch, and decodes into the old cache no longer
  count as recent.
- At most two full decodes are kept for zooming in; a newer one evicts
  the oldest.
- warm's planning runs under catch_unwind; a panic skips warming.
- Renderer::images_pending says whether the last render drew an image
  still decoding.

Regression tests use a test-only fault hook that panics inside the job
and inside warm's planning.
2026-11-14 03:49:26 +00:00
Dylan M. Taylor 7107a64d6c Merge pull request #2766 from storytold/codex/designcraft-craftlibs-clean
Cut over document formats and codecs to craft-libs (#778)
2026-11-13 22:36:04 -05:00
Dylan M. Taylor 614feb8607 Merge remote-tracking branch 'origin/main' into codex/designcraft-craftlibs-clean 2026-11-14 03:36:00 +00:00
Dylan M. Taylor 382fc27a5b fix(idml,images,pptx,textimport): update adapters and tests for craft-libs cutover 2026-11-14 03:35:09 +00:00
aiongg eefdfbb688 Docs: image cache keeps the levels drawn; canvas decodes in the background 2026-11-14 03:32:18 +00:00
aiongg 28fdd9a50e Canvas: render again for finished image decodes in batches
The canvas renders with RenderOptions::defer_images and keeps the image
generation each texture was rendered at. Finished background decodes
are taken up at most every 250 ms and not while a render is in flight,
so a page of photos decoding one after another re-renders a few times
instead of once per photo, and a newer request doesn't drop the render
in flight before it is shown. The eyedropper still decodes the image it
samples.

Based on #2051 by texjer.
2026-11-14 03:32:08 +00:00
aiongg 9563e93bd2 Images: keep only the levels drawn and decode off the canvas thread
The image cache kept the full-resolution level 0 of every TIFF, PNG,
PSD and CMYK JPEG, and of any image shown at High Quality: about 48 MB
for a 12 MP photo, so after a dozen photos every edit evicted and
decoded them again on the render thread.

- mip keeps only the level drawn. It remembers each asset's full size
  (from its header, then from a decode), builds a coarser level from a
  finer cached one, and tries the reduced JPEG decode before a full one.
  When an image is zoomed into (a finer level asked for while a coarser
  one is cached) it keeps the full decode too, up to 96 MB, so the
  following steps halve it instead of decoding again.
- With RenderOptions::defer_images (the canvas) the image draw uses
  mip_now: a level that isn't cached is decoded on one of three
  background threads, newest request first, and a coarser cached level
  or a light box is drawn meanwhile. images::generation advances and
  the waker runs when a decode finishes. A decoder panic marks the
  image bad. Background decodes reserve their peak bytes at the same
  gate as warm, so they wait while decodes in flight hold half the
  budget.
- An image asked for again within 2 s of its decode (evicted at once:
  the view holds more than the cache) isn't decoded again until then,
  in place or in the background, so the canvas never decodes on its
  own thread.
- warm counts an asset as cached when the level each drawing takes, or
  a finer one, is cached, and sizes a job by the levels it keeps. It
  leaves a decode larger than the whole budget to the render, and the
  canvas skips it.
- A render that deferred an image isn't kept as the CMYK view snapshot.

Based on #2051 by texjer.
2026-11-14 03:32:00 +00:00
aiongg 445eb502ec Render: a PDF layer variant keeps its identity while anything holds it
The image cache keys decodes by the bytes' address, so a variant rebuilt
as a new Arc misses the decodes it already has. With decodes in the
background, more variants on screen than the variant cache kept would
decode and re-render without end. Variants are now looked up weakly,
with the 64 most recent held strongly.

Based on #2051 by texjer.
2026-11-14 03:29:47 +00:00
aiongg 34f0b702e5 Images: a decoder panic in a warm worker marks the image bad; checked level lookup 2026-11-14 03:15:24 +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
jayzed80 c509445ed0 IDML export: keep endnote reference numbers (#2753) (#2764)
The IDML story writer skipped the endnote reference character, so an
exported body story lost every endnote's place: "an endnote here. End."
with nothing between "here" and the full stop. The endnote frame's
story was written with its numbers as text, so nothing linked the
listed endnote back to where it was referenced.

Each reference is now written as its own superscript character range
holding the endnote's number, formatted by Endnote Options (start,
style, prefix and suffix) as the endnote frame lists it. IDML's
Endnote / EndnoteRange elements are not written yet.
2026-11-14 00:34:31 +00:00
Dylan M. Taylor b681b10733 Pin DesignCraft shared codecs to merged fixes 2026-11-13 23:53:29 +00:00
autocraft-bot[bot] 0f924b71ae Merge main into fix/parallel-sync-image-decode 2026-11-13 21:12:07 +00:00
Dylan M. Taylor fe9498cd5f Merge branch 'codex/designcraft-craft-libs' of https://github.com/storytold/designcraft into codex/designcraft-craft-libs
# Conflicts:
#	Cargo.lock
2026-11-13 21:10:04 +00:00
Zinadin Zidan 40cc78d8f8 Text Frame Options: insets and gutter in the ruler units (#2739) (#2754)
The Text Frame Options dialog filled its fields from the document's
ruler unit but never set the dialog's own unit, so it stayed at picas.
The spinner fields (Top, Bottom, Left, Right, a non-rectangular frame's
Inset, the column width and gutter, Paragraph Spacing Limit) showed
their values in picas whatever Preferences > Units & Increments said,
and a bare number typed in any measure field, Min under First Baseline
included, was read as picas.

The dialog now takes the document's horizontal ruler unit when it opens
and keeps it while open, as the Rectangle dialog does (#1964).
2026-11-13 21:08:26 +00:00
Dylan M. Taylor 1284edfa3b Pin shared CSV codec to merge commit 2026-11-13 21:08:18 +00:00
AlPaka1234 618c191166 Window: restore hidden panels when selecting panels, control bar or workspaces (#2742) (#2746)
Fixes #2742.

Make UiState::hidden_panels session-only (#[serde(skip)]) and clear hidden_panels when opening or revealing panels, toggling the Control bar while hidden, or loading/resetting workspaces. Treat hidden panels and flyouts as not visible in checked/toggle checks so Window commands unhide them instead of toggling them off invisibly.
2026-11-13 20:58:53 +01: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
.CooCoo cf4efa1833 Text Frame Options: every dropdown and field has an accessible name (#2733)
* Text Frame Options: every dropdown and field has an accessible name

The Columns and Align dropdowns on the General tab, and the dropdowns and
text fields on the Column Rules, Baseline Options and Auto-Size tabs, had
no accessible name, so a screen reader announced them without a caption
and kittest's accessibility check failed on the dialog. Each one now takes
the caption shown next to it. The non-rectangular frame test runs with the
check on and opens every tab.

* Text Frame Options: numeric fields take their captions as names

The Number, Width, Gutter, Maximum, inset and Paragraph Spacing Limit
fields on the General tab were named by their internal ids, so a screen
reader announced tfo_columnWidth and its spinner read as Increase
tfo_columnWidth. Each field and its spinner buttons now take the caption
shown beside it.

* Text Frame Options: test the numeric editors' accessible names

The test checked only the spinner buttons' names. It now also finds each
numeric editor of the General tab (Number, Width, Gutter, Maximum, Paragraph
Spacing Limit, the four sides and Inset) by the text-input role and its
caption.
2026-11-13 16:27:26 +00:00
Dylan M. Taylor 59db0b67a7 Use shared IDML transparency writer 2026-11-13 09:43:29 -05:00
Dylan M. Taylor b409bccb0f Use shared IDML effect setting writers 2026-11-13 09:40:28 -05:00
Dylan M. Taylor 703ffed779 Use shared IDML text path writer 2026-11-13 09:37:36 -05:00
Dylan M. Taylor dab41a4f60 Use shared IDML hyperlink destination writer 2026-11-13 09:35:55 -05:00
Dylan M. Taylor 4fbe39af99 Use shared IDML index parser 2026-11-13 09:33:26 -05:00
Dylan M. Taylor 6cea56ce01 Remove app-local IDML topic ID helper 2026-11-13 09:30:20 -05:00
Dylan M. Taylor 6bc26299fa Use shared IDML anchored setting writer 2026-11-13 09:30:04 -05:00
Dylan M. Taylor 1cb0c04143 Use shared IDML index writer 2026-11-13 09:27:22 -05:00
Dylan M. Taylor a9c4253e57 Use shared IDML page reference writer 2026-11-13 09:23:32 -05:00
Dylan M. Taylor c74cf007d0 Use shared cell and table style decorations 2026-11-13 09:13:02 -05:00
Dylan M. Taylor 61f6a83de5 Use shared IDML object style values 2026-11-13 09:10:17 -05:00
Dylan M. Taylor 90f6ddba6e Use shared IDML graphic MIME fallback 2026-11-13 09:07:49 -05:00
Dylan M. Taylor c94a29204d Use shared IDML graphic MIME fallback 2026-11-13 09:07:12 -05:00
Dylan M. Taylor 6a980c01c2 Pin IDML API after shared main rebase 2026-11-13 09:06:02 -05:00
Dylan M. Taylor 41bbd27a40 Use shared placed graphic metadata 2026-11-13 09:04:34 -05:00
Dylan M. Taylor 611fe571da Use shared IDML anchored object values 2026-11-13 09:00:48 -05:00
Dylan M. Taylor 7f2ac33275 Use shared IDML frame fitting values 2026-11-13 08:58:46 -05:00
Dylan M. Taylor a92db95301 Delegate IDML object style merging to craft-idml 2026-11-13 08:56:24 -05:00
Dylan M. Taylor 75eeeca16f Use shared IDML table style values 2026-11-13 08:50:49 -05:00
Dylan M. Taylor 862c052c2f Use shared IDML cell style values 2026-11-13 08:49:14 -05:00
Dylan M. Taylor 9ea7beb6f3 Format IDML cross-reference mapper 2026-11-13 08:47:15 -05:00
Dylan M. Taylor ed0543639a Write IDML cross-reference format through craft-idml 2026-11-13 08:47:03 -05:00
Dylan M. Taylor b782bdde6d Read IDML conditions and lists from shared models 2026-11-13 08:44:55 -05:00
Dylan M. Taylor b45c58f2e3 Use shared IDML cross-reference and EPUB models 2026-11-13 08:43:04 -05:00