Commit Graph
1289 Commits
Author SHA1 Message Date
dependabot[bot] 97c84a2fd8 ci(deps): bump the actions group across 1 directory with 2 updates
Bumps the actions group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [actions/cache](https://github.com/actions/cache).


Updates `actions/checkout` from 4 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v4...v7)

Updates `actions/cache` from 4.3.0 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/0057852bfaa89a56745cba8c7296529d2fc39830...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-08 10:34:32 +00:00
FredApps 0a9d1f48da Merge pull request #443 from alehel/craft-audio-split/05-aac-decode
craft-audio: AAC decoder (5/10)
2026-11-08 11:32:03 +01:00
alehelandClaude Opus 5.5 650d1996be craft-audio: say why the ADTS-in-MP4 seek limit is kept (#443)
The Limits entry from 79f5839 said what goes wrong but not why it is left.
It now says that such a file is outside the MP4 specification: an MP4 AAC
sample is one raw access unit with the configuration in the sample
description (ISO/IEC 14496-14, 14496-3), so ADTS headers do not belong in
it, and a sample's duration is the time it decodes to (ISO/IEC 14496-12).
It says why files within the specification are not affected, what still
works, and why seeks and edits in such files are not corrected: finding
where each sample's audio starts means counting the ADTS frames in every
sample before it, one read per sample, which would slow every ADTS-framed
MP4 at open to work around files outside the specification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:12:07 +01:00
alehelandClaude Opus 5.5 79f5839aa2 craft-audio: document the ADTS-in-MP4 seek and edit limits (#443)
AAC in MP4 stored as ADTS frames, with sample durations that count fewer
frames than the samples hold, decodes in full from the start, but seeks
place samples by those durations and land later than asked, and an edit
list measured in them can end the track early. The README's Limits section
now says so, and the seek example points to it.

Reported by FredApps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 09:10:16 +01:00
alehelandClaude Opus 5.5 a0e01d2552 craft-audio: review fixes, round 11 (#443)
Corrects round 10. A short ADTS-framed MP4 track, whose last sample is in
the read-ahead, lost that sample's trim when it cut more than one frame:
the trim counted as durations falling short, so the length was left to
decoding and its padding was presented. The track's last sample is now left
out of the read-ahead comparison.

Reported by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 06:16:58 +01:00
alehelandClaude Opus 5.5 2506ad3005 craft-audio: review fixes, round 10 (#443)
ADTS-framed AAC in MP4: durations short of the frames in the samples read
ahead no longer end the track. With HE-AAC samples of two ADTS frames each,
timed as two core frames, the durations matched one output frame per sample,
so the undercount check passed and the track stopped at half its length,
which probe reported as known. The frames each read-ahead sample holds are
now counted, and durations short of them leave the length unknown until
decoded, as durations short of one frame per sample already did. Correctly
timed AAC-LC samples of several frames keep their end trim.

Reported by FredApps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 05:42:48 +01:00
058b047760 print: winprint 64e7afd4, whose Direct2D factory is multi-threaded (#605)
Windows.Data.Pdf draws a page on several of its own worker threads, which
share the print control's device context. With winprint 5f80b9b's
single-threaded factory Direct2D takes no locks, so those threads race in
d2d1.dll and the app closes while printing, most often on pages with Type 3
fonts (storytold/pdfcraft#5006, storytold/pdfcraft#2684).
storytold/winprint.rs#11 made the factory multi-threaded; it was merged as
64e7afd4.

craft-winprint-gdi moves to the same revision, so one checkout of
winprint.rs serves both; crates/gdi is unchanged between 417ac3c and
64e7afd4.

Co-authored-by: mertan-wq <235487900+mertan-wq@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:42:38 -06:00
alehelandClaude Opus 5.5 8291279c8b craft-audio: review fixes, round 9 (#443)
From CodeRabbit's review of round 8:
- AudioSpecificConfig::parse consumes extensionFlag3 after the config when
  extensionFlag is set, so the 0x2b7 sync extension after it is found.
- AudioSpecificConfig::to_bytes refuses a sampling rate of 0, which would not
  parse back.
- ADTS-framed HE-AAC in MP4 whose sample durations count core frames is not cut
  to the durations' half length: durations short of one frame per sample no
  longer end an ADTS-framed track, and its length is unknown until decoded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 22:41:48 +01:00
alehelandClaude Opus 5.5 ac8c5aae5d craft-audio: review fixes, round 8 (#443)
From wanikhawar's review:
- AudioSpecificConfig::parse reads backward-compatible SBR and PS signalling
  (a 0x2b7 sync extension after the config), which craft-media's Matroska
  demuxer writes for legacy HE-AAC IDs. Without lookahead those streams decoded
  as their core.
- An MP4 media edit after one empty edit is applied: its priming skip and its
  end. The empty edit's delay is not added as silence.
- A packet lost whole is concealed as long as the last one decoded, so a stream
  of multi-frame ADTS packets keeps its timing.
- ADTS-framed MP4 samples keep their sample table's timing, instead of every
  sample being read at open to look for several frames in one.
- AdtsHeader::write refuses an object type, sampling frequency index or channel
  configuration its fields cannot hold; it masked them into other values.
- AudioSpecificConfig::lc no longer panics for a sampling frequency index with no
  rate, and the decoder refuses such a config.
- AudioSpecificConfig::to_bytes refuses channel configuration 0 without a program
  config element, which would not parse back.
- Upsample2x starts each channel's history afresh when the channel count
  changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 22:26:05 +01:00
FredApps 904f55bb21 Merge pull request #571 from dotCooCoo/feat/doc-read-cancellation
craft-doc: allow document reads to be canceled
2026-11-07 15:52:20 +01:00
FredApps 0d0638526a Merge pull request #548 from dotCooCoo/feat/doc-full-size-composite
craft-doc: read the optional full-size PhotoCraft composite
2026-11-07 15:50:02 +01:00
FredApps 946293444a Merge pull request #583 from dotCooCoo/fix/hayro-ccitt-images-feature
PDF: compile the CCITT row helper only with images
2026-11-07 15:48:27 +01:00
FredApps 57f3b0bb6c Pass read control through ICC archive lookup 2026-11-07 15:48:07 +01:00
FredApps 628c4e5ee4 Merge updated rendition test fixtures 2026-11-07 15:45:55 +01:00
FredApps c3456fbf78 Update budget test decoders to the buffered input type 2026-11-07 15:45:26 +01:00
FredApps aed25e8d34 Integrate image-only CCITT guards and combined rendition coverage 2026-11-07 15:44:44 +01:00
FredApps e26f3d1102 Integrate full-composite provenance with cancellable reads 2026-11-07 15:44:13 +01:00
FredApps f766bf10cd Merge main and preserve cancellable selective document reads 2026-11-07 15:43:45 +01:00
FredApps c8ea8be292 Merge main and preserve selected full-composite extraction 2026-11-07 15:40:03 +01:00
FredApps 2396054e77 Merge main and retain image-only CCITT guards 2026-11-07 15:39:40 +01:00
FredApps 481f66d287 Merge pull request #633 from dotCooCoo/chore/vendor-linesweeper
linesweeper: keep a copy of the crates.io 0.5.0 package in vendor/
2026-11-07 15:37:48 +01:00
FredApps d4c71662ad Merge pull request #585 from dotCooCoo/feat/doc-pcraft-icc-profile
craft-doc: read a bounded PhotoCraft ICC payload
2026-11-07 15:37:43 +01:00
FredApps 9fa0111656 Merge pull request #582 from dotCooCoo/fix/hayro-jpx-unused-import
PDF: remove an unused JPX macro import
2026-11-07 15:37:35 +01:00
FredApps 75647cb84a Merge pull request #581 from dotCooCoo/feat/doc-pcraft-document-head
craft-doc: read a caller-defined PhotoCraft document head
2026-11-07 15:37:30 +01:00
FredApps 2eac880de8 Merge pull request #580 from dotCooCoo/fix/hayro-interpret-source-digest
hayro-interpret: refresh the local image-reader digest
2026-11-07 15:37:25 +01:00
FredApps c0e0b2bb75 Merge pull request #577 from dotCooCoo/fix/language-pack-removal-record
font-store: preserve Language packs when removal cannot commit
2026-11-07 15:37:20 +01:00
FredApps dad42b6f3e Merge pull request #573 from dotCooCoo/feat/pdf-parser-cancellation
PDF: allow opening to be canceled during parsing
2026-11-07 15:37:14 +01:00
FredApps a1d91da34d Merge pull request #562 from dotCooCoo/feat/vectorcraft-pdf-preference-read
vectorcraft-format: read PDF preference with document contents
2026-11-07 15:37:07 +01:00
FredApps 57b88511b9 Merge pull request #549 from dotCooCoo/fix/doc-rendition-copy-budget
craft-doc: check rendition copy costs before decompressing
2026-11-07 15:37:02 +01:00
FredApps af6c186f1e Merge pull request #546 from dotCooCoo/feat/doc-selected-rendition
craft-doc: read a selected rendition without extracting other payloads
2026-11-07 15:36:55 +01:00
dotCooCoo c813b55bf7 craft-doc: say what the total budget counts
The max_total and Budget docs now say the budget counts bytes consumed
from gzip, and that unused lookahead from the initial gzip read (chunks
of up to 64 KiB) is not counted.
2026-11-07 06:29:48 -08:00
dotCooCoo 43224b0492 font-store: create Language pack recovery stages through the retained folder
The recovery stage is now created, opened and, when opening fails, removed through
the retained recovery directory handle. A failed open no longer leaves an empty
stage under .removing, and the removal is not recursive. A rollback failure now
names the recovery stage ID next to the pack's last known path.
2026-11-07 01:58:39 -08:00
dotCooCoo f211604aad linesweeper: the copy's README says which workflow a change here does not start
sonarcloud.yml runs on every pull request, so a change only under vendor/linesweeper starts a workflow; it does not start pdf.yml.
2026-11-06 20:51:55 -08:00
dotCooCoo f14cc7f21e linesweeper: keep a copy of the crates.io 0.5.0 package in vendor/
Add the linesweeper 0.5.0 package to vendor/ with no file changed, so
that a fix to it can reach the Craft apps through this repository
without waiting for a linesweeper release. The GitHub repository its
manifest names is archived, and its README says development moved off
GitHub.

Leave out the test font (fonts live in craft-fonts), the logo artwork,
the snapshot images and the package's repository tooling. SOURCE.json
lists each with its hash.

Add a workspace exclude, a [patch.crates-io] entry, SOURCE.json with
the archive hash and per-file hashes, NOTICE and ATTRIBUTION.md rows,
and the package's tests in the backend test script. craft-prepress's
flatten feature now builds against the copy, so Cargo.lock drops the
package's registry source and checksum.
2026-11-06 19:05:18 -08:00
Helen Kwok fd5e2feff6 web-api: drop a timed-out call, and give screenshot() one data field (#620)
A call that timed out left the app's request future running, so an app that releases a request when its future is dropped (the desktop ControlRequest abandons a request nobody waits for) ran the call late, after the page had been told it failed. call() now drives the request future itself and drops it when the timer wins.

The desktop control protocols name the base64 PNG of ui.screenshot differently (pngBase64, png_base64, png, base64), so screenshot() gave the page a different shape in each app. It now also puts the PNG in data and leaves the app's own field where it is.

The timer handle is kept as the environment returned it: Node returns an object, not a number, so a numeric id never cleared the timer and it fired after its closure was dropped.
2026-11-06 16:54:07 +01:00
FredApps 4859d8621d Merge pull request #625 from storytold/house-rules
Copy the shared house rules into AGENTS.md
2026-11-06 11:58:27 +01:00
FredApps 33da2e96ca Copy the shared house rules into AGENTS.md.
The deny-list paragraph and the chrono calendar exception now live in the Rust rules. CLAUDE.md imports AGENTS.md, and the workspace-lints requirement stays with the new-crate notes.
2026-11-06 11:42:42 +01:00
ashandClaude Opus 5.5 a3e0b5a944 craft-print: a job can be cancelled until it starts reaching the spooler (#622)
* craft-print: a job can be cancelled until it starts reaching the spooler

On Windows a job asks the printer's driver for its capabilities before
anything is sent. A networked printer in power save can hold that query
for a long time, and an app had no way to give up on the job without
risking it printing later (storytold/wordcraft#5710; CodeRabbit on
storytold/wordcraft#5732).

A Cancel token, passed to the new submit_cancellable, moves a job from
pending to cancelled or to sending. The job checks it at the last point
before anything reaches the spooler: on Windows after the driver has
answered, before the job file is written; on macOS and Linux before lp
starts. A cancelled job returns an error and is never sent; a job already
being sent completes. submit and submit_with_progress are unchanged, and
Error keeps its one variant so callers that match on it still compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: a job turns to sending with the provider held; the job file waits for it

Review: marked as sending before it took the PrintTicket provider, a job
could then wait behind another job's driver call that a sleeping printer
held, and an app that waits only for jobs being sent would wait on it.
The job now turns to sending only once it holds the provider, right
before printing, and writes its file only after that, so a cancelled job
leaves no copy of the document behind.

A test-only hold in the driver call lets the Windows spooler test cancel
a job while its driver doesn't answer: the cancel wins and, once the
driver answers, the job stops instead of reaching the paused queue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: the DEVMODE conversion comes before a job turns to sending

CodeRabbit on #622: winprint converts the ticket to a DEVMODE, a driver
call a sleeping printer can stall, before it creates the native job, so
a job stalled there had already turned to sending and couldn't be
cancelled. The conversion now runs first, with the provider held, while
the job can still be cancelled; the provider stays held until the first
copy's own conversion, so no other job comes between them.

Tests: the Windows spooler test also cancels a job held in that
conversion; the CUPS test gives a spooler that can't start, so any
attempt to start it would change the error. README: cancellation in the
progress section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: clarify cancellation during winprint conversion repeat

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:32:35 -05:00
ashandClaude Opus 5.5 b0b6a9d712 craft-font-catalog: run the Unix font-folder tests only on Unix (#621)
* craft-font-catalog: run the Unix font-folder tests only on Unix

Five tests build an Os::Unix FontEnv from Unix paths (/home/me, <dir>/sys/fonts</dir>).
Windows doesn't treat those paths as absolute, so the tests failed there. Production code
is unaffected: on Windows FontEnv::from_process picks Os::Windows, whose folders never go
through the Unix path logic. FontEnv's docs now say its paths follow the host's path rules.

The font-store workflow, which already triggers on crates/font-catalog, now also runs
craft-font-catalog's clippy and tests on Linux and Windows.

Refs #619

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-font-catalog: keep the store override and no-store tests on Windows

These assertions don't depend on Unix path rules, so they now sit in their own
ungated test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-font-catalog: verify store override precedence

Exercise the override with platform defaults present on every OS variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:30:54 -05:00
FredApps e653048a18 Merge pull request #618 from arnav-hiwarkar/fix/print-queues-without-driver-queries
craft-print: printer_queues lists the queues without asking any driver
2026-11-06 01:35:22 +01:00
arnav-hiwarkarandClaude Opus 5.5 81c2488a09 craft-print: document spooler_list
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 05:07:25 +05:30
arnav-hiwarkarandClaude Opus 5.5 a20c900ce0 craft-print: the Windows test counts driver queries during printer_queues
The live spooler test only checked that printer_queues() reports
two_sided as unknown, which would still pass if it called printers() and
cleared the field (CodeRabbit on #618). A test-only per-thread counter in
two_sided(), the one PrintCapabilities query printer discovery makes,
now shows printers() querying the test queue's driver (the control) and
printer_queues() querying none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 05:04:48 +05:30
arnav-hiwarkarandClaude Opus 5.5 62b0fe5edb craft-print: printer_queues lists the queues without asking any driver
On Windows, printers() reads each driver's PrintCapabilities to report
two-sided support before it returns. A networked printer in power save
can hold that query for a long time, so a Print dialog showed no printer
at all, not even the ones that were awake (storytold/wordcraft#5710,
storytold/wordcraft#5645, storytold/wordcraft#5413).

printer_queues() returns the same queues and default from EnumPrinters
and GetDefaultPrinter with two_sided unknown, and makes no driver call.
Submission still checks the job's options with the driver. On other
platforms it is printers(). printers() is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 04:54:11 +05:30
FredApps a8b996d207 Merge pull request #606 from ZIDAN44/fix/410-docking-handle-names
docking: each move handle has one name, after what it moves (#410)
2026-11-05 15:06:16 +01:00
FredApps 62e0f09500 Merge branch 'main' into fix/410-docking-handle-names 2026-11-05 14:52:31 +01:00
FredApps a231e517c3 craft-update: zip without zlib-rs so apps keep flate2's miniz backend (#608)
zip's `deflate` feature pulls in deflate-flate2-zlib-rs (and zopfli). Cargo
unifies flate2's features across the whole app, so on Windows every flate2
user in an app depending on craft-update switched to zlib-rs, whose level 1
is a static-Huffman quick mode that can produce output larger than its input
(Lightcraft's 16-bit ZIP TIFFs on Windows came out bigger than uncompressed).

Use `deflate-flate2` with flate2's default miniz_oxide backend instead; the
updater only reads Deflate zips, which that covers.
2026-11-05 13:20:56 +01:00
Zinadin ZidanandClaude Opus 5.5 9f68b84897 docs(docking): a label left with a digit keeps its text, not only one with a letter (#410)
A blank name falls back to the default label only when no letter or
digit is left ("{name} 2" gives "2"); the docs and the rustdoc of
labels::named said a letter. A test pins both cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:59:40 +06:00
Zinadin ZidanandClaude Opus 5.5 0f2ad92204 docs(docking): a group drawn without a drag bar is moved by its border band (#410)
The accessibility section said a group's top border band is never
announced. Where no drag bar is drawn the band is the group's one move
handle and has the node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:35:37 +06:00
FredApps 2e2312ddaf Merge pull request #420 from helenkwok/web-host
craft-web-host: the host messages as one contract and one bridge
2026-11-05 10:35:36 +01:00
FredAppsandCursor f1ae1ecacb Merge main into web-host
Keep both craft-web-api and craft-web-host in the workspace list, the
README and the lockfile. Point the host README at the command API that
landed in #413, and the command API README at these host messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-05 10:29:52 +01:00