Commit Graph
1546 Commits
Author SHA1 Message Date
Dylan M. Taylor 10e7f7763a Test typed StencilCraft document readers 2026-11-13 04:13:55 -05:00
Dylan M. Taylor 27d3b4acf5 Keep StencilCraft v1 fixtures with shared document crate 2026-11-13 04:08:30 -05:00
Dylan M. Taylor 166d0d2127 craft-stencilcraft-document: share the native document model 2026-11-13 03:46:47 -05:00
Dylan M. Taylor 370f6714ed craft-stencilcraft-format: support typed document fields 2026-11-13 03:34:41 -05:00
Dylan M. Taylor 01452740b6 Merge pull request #1169 from dylanmtaylor/codex/stencilcraft-format-api
Add bounded common raster codec facade
2026-11-13 03:25:55 -05:00
Dylan M. Taylor 47107f6601 craft-mesh: retain glTF texture and sampler inventory (#1151)
* craft-mesh: expose unreferenced glTF texture variants

* mesh: validate texture inventory image indices

* Fix PR 1151 validation and workspace checks

* Fix remaining Rust 1.95 workspace lint findings

* Fix proof workspace Clippy warning

* Fix remaining workspace Clippy findings

* Fix video all-features Clippy warning

* KRA: parse nested layers without recursion

* Preserve KRA layer limit traversal order

* Avoid expect in iterative KRA parser

* OpenRaster: parse nested stacks without recursion

* Plate tests honor optional font fixtures

* Keep bundled font index bytes unchanged

* Preserve font build license fixture bytes

* ci: allow longer workspace test matrix

* test: respect Windows Hunspell path behavior

* ci: provision keymap fonts for all-feature tests

* ci: provision PSD corpus for full workspace tests
2026-11-13 02:17:30 -05:00
Dylan M. Taylor 72d544b707 Merge pull request #1153 from storytold/fix/psd-head-view
psd: expose bounded borrowed header resources
2026-11-13 02:15:50 -05:00
Dylan M. Taylor e2cab3f651 Merge pull request #1158 from storytold/feat/stencilcraft-format
Add versioned flattened JSON format schema
2026-11-13 02:13:29 -05:00
Dylan M. Taylor eeee3d08b6 Add shared Base64 PNG helpers 2026-11-13 02:03:55 -05:00
Dylan M. Taylor c5d1e937ae feat(materialx): add bounded reader and OpenPBR writer (#1167)
* feat(materialx): add bounded document reader and OpenPBR writer

* proof, video, latex, cms: satisfy the clippy lints that ship with Rust 1.100

The newer clippy flags needless bool guards and range loops whose index
only indexes one slice; express both with the equivalent iterators so
the workspace lint stays green on every platform.

* cms: index the ink loops instead of a range loop, which newer clippy rejects

* feat(materialx): resolve shader graphs and write OpenPBR materials

* feat(materialx): resolve shader graphs and write OpenPBR materials
2026-11-13 02:03:31 -05:00
Dylan M. Taylor 63196e66f3 Merge pull request #1157 from dylanmtaylor/codex/craft-metafile-hatch-percent
metafile: render GDI+ percentage hatch brushes
2026-11-13 02:03:14 -05:00
Dylan M. Taylor 79923702ff Merge remote-tracking branch 'origin/main' into fix/psd-head-view 2026-11-13 06:06:44 +00:00
Dylan M. Taylor 21d7c1267e metafile: draw GDI+ percentage hatch styles 2026-11-13 06:05:42 +00:00
Dylan M. Taylor 07a4cd0fc7 #778: preserve consumer VP8 frame limits 2026-11-13 06:05:39 +00:00
Dylan M. Taylor 93d75f44d7 Merge remote-tracking branch 'origin/main' into feat/stencilcraft-format 2026-11-13 06:05:00 +00:00
Dylan M. Taylor 4b8dde4c12 test(stencilcraft-format): exercise reader scalar root variants 2026-11-13 05:52:28 +00:00
Dylan M. Taylor eb379cf3d2 test(stencilcraft-format): cover scalar JSON roots 2026-11-13 05:51:08 +00:00
Dylan M. Taylor 7c3a099ad8 Read native format JSON from streams 2026-11-13 05:21:58 +00:00
Dylan M. Taylor e95c99e7bc Support common raster output formats by path 2026-11-13 00:10:01 -05:00
Dylan M. Taylor dc705aa364 Re-export common RGBA pixel types 2026-11-13 00:09:00 -05:00
Dylan M. Taylor 1dbfad04fd Support extension-based raster encoding 2026-11-13 00:08:05 -05:00
Dylan M. Taylor 5407ea8220 Document required kerf field in native format example 2026-11-13 00:04:29 -05:00
Dylan M. Taylor 4ecdcd78da Export common raster codec facade 2026-11-13 00:03:41 -05:00
Dylan M. Taylor 8c41139369 Add shared raster codec facade and versioned JSON headers 2026-11-13 00:01:32 -05:00
Dylan M. Taylor 4c25109473 test(openpgp): align signature time with generated key 2026-11-13 03:47:36 +00:00
Dylan M. Taylor 7316e4e223 fix: clear workspace baseline gates on Rust 1.100 2026-11-13 03:13:53 +00:00
Nicolas Bohn 5056c13ef7 fix(dxf): split binary hex payloads into chunks of at most 127 bytes (#1147) (#1148) 2026-11-12 21:49:37 -05:00
Dylan M. Taylor 1b53814a38 Apply verified workspace format fixes 2026-11-13 02:37:09 +00:00
Dylan M. Taylor 7a639e04a7 Fix workspace clippy loop in LaTeX tests 2026-11-13 02:35:01 +00:00
Dylan M. Taylor d31b04810b Fix current workspace clippy diagnostics 2026-11-13 02:28:06 +00:00
Dylan M. Taylor c7fb7544c2 craft-stencilcraft-format: add native JSON schema 2026-11-13 02:23:04 +00:00
Dylan M. Taylor 61d9de7846 psd: bound resource iterator size hint 2026-11-13 00:21:00 +00:00
Dylan M. Taylor cc9c380543 Fix PSD resource iterator size hint 2026-11-13 00:05:37 +00:00
Dylan M. Taylor 341c84d1b1 Add borrowed PSD head resource views 2026-11-13 00:03:19 +00:00
Dylan M. TaylorandDylan Taylor f92a91afa4 plotter: add TB54 registration-mark offset command (#1139)
* plotter: add TB54 registration-mark offset command with py_silhouette citation

The full Silhouette registration sequence (TB99 through TB55, plus
TB123/TB124 for search and TB23 for manual positioning) is documented
in the community driver py_silhouette (zero_on_registration_mark()),
which reverse-engineered the protocol from public behaviour — not from
any proprietary binary.

TB54,0,0 sets the registration-mark offset to zero (mark at expected
position). Without it the machine may use a non-zero default offset.

* workspace: allow unused_workspace_dependencies lint

The root Cargo.toml declares many workspace dependencies that are not
referenced by any crate's Cargo.toml (e.g. craft-aep, craft-ai-core,
craft-cms, etc.). This is intentional — they are available for apps to
use. Suppress the clippy warning so CI passes.

* workspace: allow unused_workspace_dependencies (cargo lint)

This is a cargo-level lint (not clippy) that fires when workspace
dependencies declared in [workspace.dependencies] are not referenced
by any crate's Cargo.toml. Many entries are intentionally available
for apps to use.

* cms, prepress, proof: allow unused_workspace_dependencies lint

These crates are built individually by CI (cargo clippy -p <crate>)
which does not inherit workspace lints. Add per-crate suppression.

* cms, prepress, proof: inherit workspace lints

Add [lints] workspace = true so these crates pick up the
unused_workspace_dependencies suppression from the root Cargo.toml.

* revert: remove duplicate [lints] sections

The cms, prepress, and proof crates already had [lints] workspace = true.
My previous commits accidentally added duplicate sections.

* cargo: suppress unused_workspace_dependencies lint via config

This is a cargo-level lint (not clippy) that fires when workspace
dependencies declared in [workspace.dependencies] are not referenced
by any crate's Cargo.toml. Many entries are intentionally available
for apps to use.

---------

Co-authored-by: Dylan Taylor <dylanmtaylor@gmail.com>
2026-11-12 15:44:47 -05:00
.CooCoo d23f5f36bb craft-drawingml: outline digests print a near-zero coordinate without its sign (#1127)
outlines_match_the_string_dispatch failed on macOS for curvedRightArrow
while Linux and Windows passed. The digest prints each coordinate with
{:.3}, which writes a residue such as -1.4e-14 from the sine or cosine of
a right angle as "-0.000". The sign of that residue depends on the
platform's libm, so the digest did too.

digest_coord now maps every coordinate that prints as zero to 0.0 before
it is printed. The digests of pieWedge, curvedRightArrow and
curvedDownArrow, the only names whose outlines held such residues, are
taken again; no outline changes.
2026-11-12 13:45:57 -06:00
Dylan M. Taylor e98299546f crs: a repeated name keeps its first value, as craft-metadata reads it
craft-metadata #1042 keeps the first text-bearing value of a repeated
property so a blank repeat cannot hide a location, but craft-crs's doc
comment and test still claimed the last repeat wins. The workspace-wide
test job has been red since it landed because of that assertion.
2026-11-12 11:26:10 -05:00
nonplessesdsnrffffandBen Mathews 65cf3f9b0d craft-web-host: accept PDF page attachments from the host
* craft-web-host: accept PDF page attachments from the host

---------

Co-authored-by: Ben Mathews <ben@themathewsgroup.com>
2026-11-12 10:43:32 -05:00
Ken MantleandKenM76 f3b643d081 prepress: separate a page in bands, past the 4 MP plate cap
* prepress: separate a page in bands, past the 4 MP plate cap

`plates_in_bands` finds a page's inks once, then separates it in row
bands of at most MAX_PLATE_PIXELS each, rendering every band through
craft-pdf raster's size/offset viewport. A page can now be separated at
print resolution with bounded memory: only the renderer's 8192-pixel
side limit and a 256 MP per-plate total (MAX_BANDED_PIXELS) lower the
resolution. `plates` is unchanged in behaviour: it is the one-band case
of the same code.

Tests: bands of 7 rows join byte for byte into the whole-page render of
an anti-aliased disc under an overprinting spot (fails when the band
offset is dropped), and a 40 pt page at 3700 dpi separates at full
resolution in bands under the cap (fails when banding uses the plate
cap's scale).

Refs #838.

* prepress: bands pass the renderer's whole-page limits

The page's pixel size came from `raster::dimensions` on the whole page,
which enforces the renderer's 64 MP and 8192-pixel side limits, so a
Letter page past about 830 dpi failed with OutputLimit instead of
banding. The size is now computed as the renderer floors it, and only
each band's viewport reaches the renderer. Bands are also capped at
MAX_SIDE rows, and ink discovery renders within the renderer's limits.

A Letter page at 900 dpi now separates in 19 bands at full resolution;
across the page the side limit still lowers it, near 960 dpi.

Test: a 10 x 2000 pt strip at 600 dpi (16 666 rows) separates in three
bands with its black square on the right rows. It fails with either the
whole-page dimensions call or the uncapped band height restored.

* prepress: check the page before discovery; say what the banded cap bounds

The page-size check now runs before ink discovery renders anything.
MAX_BANDED_PIXELS bounds pixels, not the number of bands; the doc
comment and the README caps table say so.

* prepress: count a sub-pixel side as one pixel in the banded cap

A side scaled under one pixel still renders one, so a very thin, tall
page could pass MAX_BANDED_PIXELS by far. banded_scale now fits the
other side alone in that case, and separate() refuses any floored size
over the cap before it renders a band.

* prepress: keep the banded area scale under the cap after rounding

The area scale came from the exact cap, so f32 rounding could floor a
page one row past it (17 x 15 058 824 pt at 72 dpi), which then failed
with OutputLimit. The same 0.1% margin as the one-pixel branches now
applies to the area scale too, with a test on that page.

---------

Co-authored-by: KenM76 <KenM76>
2026-11-12 10:41:24 -05:00
aionggandaiongg 270db68c1e craft-cms: run the CMS suite in CI
* craft-cms: run the CMS suite in CI; say when system-profile checks are skipped

* craft-cms: satisfy clippy's chunks_exact_to_as_chunks lint in the total-ink test

---------

Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-11-12 10:38:37 -05:00
Zach Shallbetter b6cbd59671 craft-atomic: eliminate runtime panic on wasm32-unknown-unknown (closes #81)
* craft-atomic: eliminate runtime panic on wasm32-unknown-unknown (closes #81)

---------

Co-authored-by: Zach Shallbetter <zachshallbetter@icloud.com>
2026-11-12 10:38:30 -05:00
Hamza NaveedandHamza 75af6f589a PDF interpret: a glyph shown in a clipping mode clips even with no outline
* PDF interpret: a glyph shown in a clipping mode clips even with no outline

A glyph shown in a clipping render mode (`4 Tr` to `7 Tr`) adds its outline to
the clipping path, and that clip applies to everything painted after `ET` until
the enclosing `Q`. When the glyphs shown have no outline -- a space, say -- the
clip they contribute is empty, and an empty clip admits nothing.

`interpret_window` applied a clip only once a glyph had contributed an outline,
so such a text object applied *no* clip and what followed painted unmasked.

A text object that shows no glyph at all is a different case and is left alone:
the clipping path is unchanged there, as readers leave it, and a glyph whose
outline is unavailable (Type 3) leaves the real clip unknown, so both stay
unclipped. pdf.js draws the same line in `endText`: it builds the clip from the
glyphs shown, empty outlines and all, and applies none when none were shown.

Measured on a page filled red behind the text object, Preview (CoreGraphics)
and Firefox (pdf.js) agreeing on the case this changes:

    a space shown in 7 Tr    before: the fill paints   after: nothing paints
    no glyph shown in 7 Tr   unchanged: the fill paints

Companion to storytold/pdfcraft#3451.

The first push of this branch also carried 803 build-artifact files from
`crates/pdf/read-only-contract/target/`, which `.gitignore` did not cover: its
`/target` is anchored to the repository root, so a sub-crate's own build
directory is not ignored. Recommitted without them, and `target/` added so the
next one cannot slip in either (#185 review).

* pdf: test visible glyphs in a clipping mode, and what each clip leaves on the page

---------

Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
2026-11-12 10:38:02 -05:00
638ee75115 Paint dialog tabs that join their page
* Paint dialog tabs that join their page

* Discard texture updates explicitly in headless rendering tests

* Cover centered baselines below selected dialog tabs

* Tests: use Id::unique, as main's egui requires

---------

Co-authored-by: Fluorine <joseph.anglada92@gmail.com>
Co-authored-by: Joseph Anglada Muñiz <janglada@nd-soft.com>
2026-11-12 10:37:55 -05:00
b903f08e7b Share bounded frosted backdrop composition
* Share bounded frosted backdrop composition

* Scope upload assertions to the backdrop texture

* Discard texture updates explicitly in headless rendering tests

* Correct texture ID borrowing in upload-count regression

* Bound texture sides before queuing backdrop uploads

---------

Co-authored-by: Fluorine <joseph.anglada92@gmail.com>
Co-authored-by: Joseph Anglada Muñiz <janglada@nd-soft.com>
2026-11-12 10:37:46 -05:00
6026ad570f Share shape gallery choices and procedural previews
* Share shape gallery choices and procedural previews

* Clip shape previews to their supplied rectangles

* Discard texture updates explicitly in headless rendering tests

* Honor fill colors across complete star and heart contours

* Make heart contour collection type explicit

* Use fixed-size triangle chunks in fill regression

---------

Co-authored-by: Fluorine <joseph.anglada92@gmail.com>
Co-authored-by: Joseph Anglada Muñiz <janglada@nd-soft.com>
2026-11-12 10:37:36 -05:00
aionggandaiongg e56b2f1220 craft-window: frame policy v2: the app's bar is the title bar by default
* craft-window: frame policy v2: integrated title bar by default, desktop and backend detection

Add the policy module: Backend, Desktop::detect, TitleBarPref, Os, Frame
{Native, Inset, Integrated}, pure decide, decide_for and apply. Caption
layouts come from GNOME gsettings, kwinrc and GTK settings.ini parsers.
Choice::probe, the root Frame and decorate keep their behaviour.

* craft-window: review fixes for the frame policy

Desktop gains icon_theme, Decision gains desktop, Backend::from_env,
GNOME layout falls back to settings.ini, compositor socket variables mark
tiling, GTK_THEME wins over settings.ini, layout is read only for an
integrated frame, Layout::mirrored.

* craft-window: CRAFT_TITLEBAR applies when the app's own variable is unset

---------

Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-11-12 10:37:27 -05:00
aionggandaiongg bcf1e69cf4 craft-window: restore store: window.json beside config.toml and a pure place()
* craft-window: restore store: window.json beside config.toml and a pure place()

* craft-window: restore: review fixes (bar strip, mixed DPI, pending writes, work area)

---------

Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-11-12 10:37:20 -05:00
aionggandaiongg 1329b6bf04 platform: GNOME's light setting reads as light, and Watcher::wait_first for the first frame
* platform: GNOME's light setting reads as light, and Watcher::wait_first for the first frame

GNOME 42-46 writes color-scheme 'default' for Settings > Appearance > Light and the portal
reports 0. Both now decode as Light on GNOME (XDG_CURRENT_DESKTOP, read once at start);
0 stays no preference on other desktops.

Watcher::wait_first(timeout) blocks until the first answer, a known-absent portal with an
empty fallback, a no-preference answer, worker exit or drop, or the timeout.

* platform: GNOME's 'default' is light only on a GNOME desktop

---------

Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-11-12 10:37:13 -05:00
VoiceLessQandVoiceLessQ 5afeda8327 craft-proof it: a ‘ quote can open the next sentence, as “ and « do
In "Vado. ‘poi’ torno." the capital-letter check skipped poi, because ends_sentence didn't count ‘ among the characters that may open the next sentence. This is the last part of storytold/wordcraft#3675; the rest came with #484.

---------

Co-authored-by: VoiceLessQ <t12kaem@gmail.com>
2026-11-12 10:37:00 -05:00
Hamza NaveedandHamza 9b7b748fbb krilla: TrueType subsets keep the font's OS/2 table (embedding permissions)
* krilla: TrueType subsets keep the font's OS/2 table (embedding permissions)

The subsetter writes only the tables it subsets, so a FontFile2 program
had no OS/2 table and the font's embedding permissions (OS/2.fsType)
never reached the PDF: a Preview & Print or Restricted font looked
unrestricted to anything reading the file later (designcraft#1781).

Patch 18 adds the source font's OS/2 table, byte for byte, to a
TrueType subset that lacks one, rewriting the table directory with its
checksums and head.checkSumAdjustment. CFF programs are still embedded
bare. Ledger, patch file and SOURCE.json updated; craft-pdf's new
font_tables test checks the table, its fsType and the font's checksums.

* krilla: the OS/2 test checks the embedded program is a subset

Its sfnt and re-read checks also pass for the source font embedded whole. A subset has fewer glyphs than the fixture's 11, and a shorter glyf.

---------

Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
2026-11-12 10:36:53 -05:00