Commit Graph
427 Commits
Author SHA1 Message Date
aiongg fcbf08de14 Merge remote-tracking branch 'upstream/main' into pdf-reader-sync
# Conflicts:
#	vendor/hayro-syntax/SOURCE.json
2026-10-24 12:11:27 +00:00
Dylan M. TaylorandClaude Opus 5.5 13d766e074 security: bound vendored hayro CCITT rows of unknown height and JPEG 2000 codestream size (#255)
* security: bound vendored hayro CCITT rows of unknown height and JPEG 2000 codestream size

- CCITT: `/Rows 0` decoded to the end of the data; a bit of 2D code can repeat a whole row,
  so a small stream produced gigabytes. Rows are now capped by the output limit (in the
  stream's 1-bit rows) and 2^28 pixels.
- JPEG 2000: the decoder allocated its output from the codestream's own dimensions,
  infallibly. Over 2^28 pixels or the output limit (at least 64 MiB) is refused before
  decoding, and the buffer is reserved fallibly.
- SOURCE.json local hashes updated (ascii_85.rs's had not been after #253).

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

* fix(ccitt): pass the output limit in the columns test

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 04:29:32 -04:00
aiongg d0f4ab75a8 hayro-interpret, hayro-syntax: review fixes for the reader-sync batch
- Patch-mesh triangles are rebuilt after inflation, so the stored dot products match
  the vertices.
- A stencil image restores the fill alpha itself when the saved-state bound skipped
  its save.
- A resolved JP2 palette decodes to 8 bits whatever /BitsPerComponent says.
2026-10-24 08:07:16 +00:00
aiongg 4bd8b167da Merge part 5: ICC profile cache key 2026-10-24 07:46:44 +00:00
aiongg 89a5b2cf2e hayro-interpret: port PdfCraft's ICC profile cache key (#3020)
Cache the color space of an /ICCBased profile by its stream object, and on
a miss by its dictionary key and raw bytes, instead of the dictionary's
bytes alone, so two profiles with the same /N and /Length each draw through
their own profile. InterpreterCache::icc_profile_reads counts profile reads.
PdfCraft's two raster tests are adapted in tests/upstream_raster.rs.
2026-10-24 07:46:17 +00:00
aiongg 3648e60159 pdf: keep both sides' upstream_raster tests from the /Default color spaces merge 2026-10-24 07:43:00 +00:00
aiongg f8cbf0e1c2 pdf: keep both sides' upstream_raster tests from the /Default color spaces merge 2026-10-24 07:42:37 +00:00
aiongg d2b25a0dc1 Merge part 5: mesh shading extent
# Conflicts:
#	vendor/README.craft-reader.md
#	vendor/hayro/SOURCE.json
2026-10-24 07:40:58 +00:00
aiongg 197e5137fa Merge part 5: /Default color spaces
# Conflicts:
#	crates/pdf/tests/upstream_raster.rs
#	vendor/README.craft-reader.md
2026-10-24 07:40:52 +00:00
aiongg 4952238c66 hayro-interpret: port PdfCraft's /Default color spaces (#3018)
A resource dictionary's /DefaultGray, /DefaultRGB and /DefaultCMYK
replace the device spaces that color operators, cs/CS, images and
shadings select (ISO 32000-2 8.6.5.6). Decoded images and shadings are
cached per default.

Defaults follow this tree's resource scoping (a form with /Resources
sees only its own), and they do not apply on a plate, so device color
separates onto the same inks as before. PdfCraft's raster tests are
adapted in upstream_raster.rs, with a plate test in plates.rs.
2026-10-24 07:39:43 +00:00
aiongg a672020a96 Merge part 5: /VE expressions and page transparency group
# Conflicts:
#	vendor/README.craft-reader.md
2026-10-24 07:39:41 +00:00
aiongg 5ff42f2642 hayro-interpret, hayro: port PdfCraft's mesh shading extent (#3296)
EncodedShadingPattern::extent records the device pixels a mesh's triangles
touched when it was encoded. set_paint returns PaintSetup: the mesh texture
covers that extent with Extend::Pad instead of the whole path, and a mesh with
no triangle on the canvas paints nothing. Output is unchanged; the knockout
erase pass and plate drawing are untouched. Adds hayro's mesh_extent_tests.
2026-10-24 07:38:33 +00:00
aiongg 30ee2f832f hayro: port PdfCraft's page transparency group (#2972)
The page group composites over a transparent backdrop and is then put on the background, so a blend mode over an empty part of the page keeps its color. With a color replacement, and on a plate render, the background stays inside the group as its backdrop, so plate films are as before. Ledger hayro (18); the PdfCraft raster test is adapted in upstream_raster.rs.
2026-10-24 07:38:08 +00:00
aiongg 7c7ec9c8ca hayro-interpret: port PdfCraft's optional-content /VE expressions (#2987)
An optional content membership dictionary with a visibility expression (/And, /Or, /Not over listed groups) shows its content when the expression is true, ahead of /OCGs and /P. Malformed expressions, or ones nested deeper than 32 levels, fall back to /OCGs and /P. Ledger hayro-interpret (40); the PdfCraft raster test is adapted in upstream_raster.rs.
2026-10-24 07:36:15 +00:00
aiongg c45caf2cd1 Merge part 4 (syntax)
# Conflicts:
#	vendor/README.craft-reader.md
2026-10-24 07:33:56 +00:00
aiongg d118f471b8 hayro-syntax: port PdfCraft's unfiltered inline-image length (#3107)
From PdfCraft #3438 with its look-ahead bound (01af6cba3): an inline
image without a filter ends at the byte length its /W, /H, /CS, /BPC
and /IM give when white space and EI follow there, so an EI inside its
samples does not end it. Anything else keeps the EI look-ahead. A
computed end past the content window waits for more data only while it
fits within MAX_DECODED_STREAM.

Tests: PdfCraft's six content::tests unit tests.
2026-10-24 07:33:40 +00:00
aiongg d2ffefcddf hayro-syntax: port PdfCraft's JP2 palette without /ColorSpace (ledger P5)
A JPX image whose dictionary has no /ColorSpace, or one that does not resolve, takes its colors from the JP2 palette instead of drawing its raw indices as gray. Resolved palette colors are 8-bit samples whatever the index precision. From PdfCraft #3184, with its three jpx unit tests.
2026-10-24 07:32:06 +00:00
aiongg d9d02c42be hayro-syntax: port PdfCraft's trailer /Prev reference (ledger 24)
A trailer /Prev written as N G R is followed: it is the offset the referenced object holds when the section's own entries place it, and otherwise offset N. Each section's entries are read before its Prev is followed. From PdfCraft #2400, with its two xref unit tests; the local xref-stream bounds are kept.
2026-10-24 07:26:55 +00:00
aiongg 647156d354 Merge part 3 (fonts and text), #266
# Conflicts:
#	vendor/README.craft-reader.md
#	vendor/hayro/SOURCE.json
2026-10-24 07:12:51 +00:00
aiongg 860f437063 Merge part 2 (paint), #265 2026-10-24 07:12:35 +00:00
aiongg 2cbbf81b1d hayro-interpret: a transparent plate paint stays transparent when a stencil drops pattern opacity 2026-10-24 06:57:41 +00:00
aiongg 429258979d hayro-interpret, hayro: port PdfCraft's font and text fixes (ledger P7, 49, 50)
From PdfCraft 0b670caf4:

- P7 (PdfCraft #3109, #3116): text in mode 7 (clip only) installs its
  clip and reaches the device as GlyphDrawMode::Clip, which the hayro
  renderer does not paint, so extraction that leaves out invisible OCR
  text keeps a heading drawn through its clip. Test:
  clipping_only_text_reaches_the_device_apart_from_invisible_text in
  crates/pdf/tests/upstream_text.rs.
- (49) (PdfCraft #2949 and 09668ce88): a TrueType post table version
  1.0, 2.0 or 3.0 written with its 16-bit halves swapped is accepted,
  and a swapped 2.0 table's glyph names are read. Unit test on a
  synthetic sfnt in font::blob::tests.
- (50) (PdfCraft #3958): the CFF glyph-name map is built once on first
  use and shared between clones instead of scanning the charset per
  code. PdfCraft's unit test comes with it.
2026-10-24 06:55:26 +00:00
aiongg f4f0e88985 hayro-interpret, hayro: port PdfCraft's paint fixes (ledger 51, 46, P4, 36)
From PdfCraft 0b670caf4:

- (51): the saved-state accounting (state_bytes, the saved_bytes update,
  num_states) uses saturating sums, so a huge dash array or clip list
  stays over the 64 MiB input bound on 32-bit targets instead of
  wrapping.
- (46) and the hayro stencil paint (PdfCraft #2977): an image XObject's
  group applies the fill opacity, so a stencil mask's paint no longer
  carries it again (a mask at ca 0.5 was drawn at a quarter), a pattern
  paint drops the opacity it captured at scn (Pattern::without_opacity),
  and the mask is painted with the fill paint rather than the stroke
  paint.
- PdfCraft #3246 (unledgered): a shading pattern takes the alpha current
  at paint time (Pattern::set_alpha), so a gs after scn or SCN still
  applies; plate paints take it the same way.
- (36) (PdfCraft #3035): a mesh pixel whose corner no triangle holds
  strictly takes the triangle that covers its center, edges included
  (Triangle::covers), so shared edges leave no seam. Marked
  "PdfCraft patch (#3035)": the plate-mode code already uses (35) and
  (36) for #2770's numbers.

Tests: the PdfCraft raster tests for (46), #3246 and (36), adapted in
crates/pdf/tests/upstream_raster.rs.
2026-10-24 06:39:40 +00:00
aiongg 7895f5ed79 krilla: optional content groups (layers), patch 12 (#258)
Document::add_optional_content_group writes an OCG; Surface::start_optional_content and
end_optional_content mark content with /OC BDC/EMC, registering the group under the stream's
/Properties resources. Marks nest independently of tagging, and misuse returns or records a
KrillaError instead of panicking. The catalog gets /OCProperties (hidden groups in /OFF) and,
opt-in, /PageMode /UseOC. PDF/A-1 reports ValidationError::OptionalContent; below PDF 1.5 the
version requirement is registered too.
2026-10-24 02:13:19 -04:00
aiongg e95a9c8127 Merge pull request #190 from aiongg/print-color
pdf: CMYK print color in the vendored krilla, plate tests and craft-prepress
2026-10-24 01:58:00 -04:00
aiongg 4238a2dd57 Merge upstream main into print-color
Conflicts: NOTICE, vendor/README.craft-reader.md and the hayro-interpret and
hayro-syntax SOURCE.json keep the ec0a965 provenance and add hayro-cmap
(a2ec27b) and hayro-postscript (crates.io 0.1.0). type0.rs keeps PdfCraft's
flat sample array with its 64-bit largest sample and main's 32-bit test.
Local sha256 values recomputed for the merged files.
2026-10-24 05:46:57 +00:00
aiongg 2eca9b3a53 pdf: vendor hayro-postscript and skip << and >> runs without recursion (#263)
hayro-postscript 0.1.0 is the token scanner hayro-cmap uses for the
CMap streams PDFs embed. Its object reader skipped each `<<` or `>>`
by calling itself again, so a stream holding a long run of `<` or `>`
bytes recursed once per pair and aborted the process with a stack
overflow.

Vendor the crates.io package unchanged and patch `object::read` to
skip those runs in a loop, returning the same next object as before.
Wire it in like the other Hayro crates: workspace exclude,
[patch.crates-io] entry, SOURCE.json with registry and local hashes,
the backend test script, NOTICE, ATTRIBUTION.md and the reader README.

Tests cover a million `<` and a million `>` bytes, `<< /A 1 >>` and
nested `<<<< /X >>>>` runs.
2026-10-23 23:31:35 -04:00
aiongg d2d5a400da pdf: port PdfCraft's reader fixes, part 1 (syntax and text) (#261)
* hayro-syntax: port PdfCraft's syntax fixes (ledger 17, 19, 20, 23, 4-ext, #3565, base_dimensions floor)

From PdfCraft a2ec27b47:

- (17), (19): a CCITT image with /Rows 0, or with fewer /Rows than its
  /Height, decodes to the image height instead of zero or /Rows rows.
- (20): spaces or tabs between the stream keyword and its line break are
  skipped, so the stream data starts after the line break.
- (4) extension: an inline image's EI followed by a delimiter (EI%, EI[)
  ends the image; only a regular character makes it part of a longer token.
- (23): bytes above 0x7F between two EI candidates don't reject the first;
  the operator look-ahead decides.
- #3565: a doubled sign (--280, +-280) is read and skipped as one number.
- Page::base_dimensions keeps a one-point floor after /UserUnit instead of
  one raw unit.

Also a local bound: a CCITT /Columns past u32::MAX is refused instead of
wrapping to a small width that passed ccitt_size_ok.

Tests: content and number unit tests from PdfCraft, a stream unit test, a
synthetic page test for the floor, a CCITT /Columns unit test, and the two CCITT raster tests in
crates/pdf/tests/upstream_raster.rs.

* hayro-interpret: port PdfCraft's text fixes (ledger 30, 44, P2, P6, P8, 26-ext)

From PdfCraft a2ec27b47:

- (30): WinAnsi 0xA0 and 0xAD and MacRoman 0xCA read as an ordinary space
  and hyphen (Annex D.2 gives them those glyph names) unless /Differences
  names nbspace or sfthyphen.
- (44): a /ToUnicode /Identity-H or /Identity-V name reads two-byte codes
  as their Unicode values; controls and lone surrogates give no text.
- P6: glyph names outside the Adobe Glyph List (f_i, hyphen.case,
  uniXXXXXXXX) read by the glyph list specification's full mapping; names
  that only number a glyph (C39, c251) give no text.
- P8: a substitute font whose charmap lacks a spacing character (U+2002 and
  similar) draws its ordinary space instead of .notdef.
- P2: a Type 3 glyph's /FontBBox is transformed to device space before it
  bounds the glyph's clip and shadings, so shaded glyphs draw at every
  position.
- (26) extension: comma-below letters (s, t, k, l, n, r, G with comma) in
  the standard-font stand-ins are the base letter with the font's comma,
  scaled and placed under the baseline.

Tests: crates/pdf/tests/upstream_text.rs for (30), (44) and P6; the Type 3
shading and comma-below raster tests in crates/pdf/tests/upstream_raster.rs.
P8's PdfCraft test needs a Japanese substitute font and is not ported.

* hayro-syntax: refresh SOURCE.json local hashes for Cargo.lock, ascii_85.rs and filter/mod.rs

They changed in #241 and #253 without their local sha256 values.
2026-10-23 23:30:56 -04:00
aiongg ed368e819e ci: keep craft-cms changes in the PDF workflow's triggers
craft-cms has no workflow of its own, and craft-prepress and craft-plate-test
depend on it, so the PDF workflow is the only place its changes are tested.
2026-10-24 03:04:40 +00:00
aiongg 7069ebf368 Merge branch 'print-color-prepress-fixes' into print-color 2026-10-24 03:04:33 +00:00
aiongg 0073927bf4 Merge pull request #260 from aiongg/keymap-batch
keymap batch: craft-keymap, keyboard layouts, the Keyboard Shortcuts dialog
2026-10-23 22:59:20 -04:00
aiongg ef13696c29 krilla, craft-pdf tests: rustfmt the review fixes 2026-10-24 02:56:03 +00:00
aiongg 830985971f ci: plate-test job provisions the test font, and text scenes fail on CI without it 2026-10-24 02:54:41 +00:00
aiongg 4befe2f986 krilla: document that nonzero overprint mode applies to DeviceCMYK only 2026-10-24 02:53:25 +00:00
aiongg dc54ca0e71 krilla: Trapped::Unknown is written to XMP as well as the information dictionary 2026-10-24 02:53:06 +00:00
aiongg 66bc4f0b4c krilla: a PDF/X version fails PDF/A-1 to 3 validation, whose XMP needs an extension schema 2026-10-24 02:46:07 +00:00
aiongg f2b26db319 ci: PDF workflow skips craft-cms changes and pins the plate-test actions 2026-10-24 02:44:09 +00:00
aiongg 5d5e0892de krilla: Image::from_custom checks channel lengths in usize and returns an error 2026-10-24 02:43:24 +00:00
aiongg bdace448d9 prepress: non_exhaustive public enums, and checked plate sizes for hand-made Plates 2026-10-24 02:42:36 +00:00
aiongg 558f8ce2fc Merge upstream main into keymap-batch 2026-10-24 02:42:28 +00:00
aiongg 53837472d6 Merge pull request #259 from aiongg/i18n-batch
i18n batch: isolation, region, sizes, folding and sorting, ICU4X numbers, number parsing, craft-fonts-build
2026-10-23 22:42:02 -04:00
aiongg b4de602172 krilla: ImageColorspace stays Copy; DeviceN images take their space from CustomImage::device_n_space 2026-10-24 02:33:10 +00:00
aiongg 2c6b3b5392 hayro-interpret: compute the largest 32-bit Type 0 sample in 64 bits (#257)
PdfCraft ledger hayro-interpret (31), its overflow part: a Type 0 function
with /BitsPerSample 32 computed 2_u32.pow(32), which overflows (a panic with
overflow checks on). The maximum is now ((1u64 << bps) - 1) as f32. The flat
sample array that (31) also brings is a performance change and is not part of
this commit. Test: function::type0::tests::thirty_two_bit_samples_do_not_overflow.

PdfCraft's other reader limits are already covered here: ASCII85 output is
bounded by the decode limit (#253), object-stream indexes are parsed once with
checked offsets, and direct objects nest at most 64 levels (PdfCraft: 128).
2026-10-23 22:32:25 -04:00
aiongg fde8b638c3 prepress: to_pdf_color returns None for tints of no ink 2026-10-24 02:32:01 +00:00
aiongg fbda14c62b krilla: soft-mask groups blend in sGrey under ICC CMYK, so the backdrop stays black 2026-10-24 02:30:08 +00:00
aiongg 332a4456dd Merge #186: keymap: Keyboard Shortcuts dialog, named shortcut sets and the shortcut editor
# Conflicts:
#	crates/keymap/src/lib.rs
2026-10-24 02:29:57 +00:00
aiongg f0379def18 Merge #205: keymap: read presses by the keyboard layout 2026-10-24 02:29:52 +00:00
aiongg 4d646b3cbd Merge #164: Add craft-keymap: shared keyboard bindings and shortcut-set import 2026-10-24 02:29:52 +00:00
aiongg f7b71a80a1 prepress: decode spot names from the PDF once, so A#41 and AA get their own plates 2026-10-24 02:29:33 +00:00
aiongg ec65b95a65 Merge #213: Add craft-fonts-build: embed craft-fonts faces from an app's build.rs
# Conflicts:
#	Cargo.lock
2026-10-24 02:26:24 +00:00