Commit Graph
416 Commits
Author SHA1 Message Date
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 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
aiongg 02eb391d39 Merge #202: i18n: parse_number for typed and pasted numbers
# Conflicts:
#	crates/i18n/README.md
2026-10-24 02:26:12 +00:00
aiongg a8b8fbd5a8 i18n: the RTL unit test sets its number format, as the region now decides digits 2026-10-24 02:26:04 +00:00
aiongg 5f4c39ea94 i18n: a region-formatted count is a left-to-right isolate in RTL wordings; trn_plain has no marks 2026-10-24 02:26:04 +00:00
aiongg aaf9f29e4f Merge #210: i18n: numbers for a region on ICU4X, locale digits in counts and sizes
# Conflicts:
#	Cargo.lock
#	crates/i18n/Cargo.toml
#	crates/i18n/README.md
#	crates/i18n/src/lib.rs
2026-10-24 02:25:57 +00:00
aiongg fa78cb52a5 Merge #206: craft-i18n: search folding and locale sorting
# Conflicts:
#	crates/i18n/Cargo.toml
#	crates/i18n/src/lib.rs
2026-10-24 02:25:27 +00:00
aiongg 7cb4a73b3c i18n: file sizes and measures fill {n} as a left-to-right isolate 2026-10-24 02:20:40 +00:00
aiongg c465dd3f47 Merge #204: i18n: file sizes and measures with translatable unit names
# Conflicts:
#	crates/i18n/README.md
#	crates/i18n/src/lib.rs
2026-10-24 02:20:40 +00:00
aiongg 1faeabfead Merge #203: i18n: formatting region apart from the interface language
# Conflicts:
#	Cargo.lock
#	crates/i18n/README.md
#	crates/i18n/src/lib.rs
2026-10-24 02:20:33 +00:00
aiongg 85148fd99c Merge #201: i18n: isolate inserted values in fmt and trn 2026-10-24 02:18:41 +00:00
aiongg 9f75d3dc19 pdf: keep a CID font's /W2 table past an out-of-range first CID; vendor hayro-cmap from PdfCraft (#254)
* pdf: keep a CID font's /W2 table past an out-of-range first CID; vendor hayro-cmap from PdfCraft

- hayro-interpret: a /W2 run whose first CID is past 65535 is skipped, as in
  /W. A run starting at 4294967295 overflowed the CID counter and discarded
  the whole table. Unit test in font::cid.
- hayro-cmap 0.1.0 is vendored from PdfCraft a2ec27b47 with its malformed-CMap
  patch (PdfCraft #3177): bad bfchar/bfrange entries, an unresolvable usecmap
  and an unparseable tail are skipped instead of failing the whole CMap. The
  crate's tests come with it. Wired up like the other vendored Hayro crates
  (workspace exclude, patch entry, SOURCE.json, backend test script); NOTICE,
  ATTRIBUTION.md and vendor/README.craft-reader.md record the source.

* hayro-syntax: refuse an xref-stream subsection that runs past object number u32::MAX

The object number was start + i in unchecked u32: a subsection starting near
u32::MAX overflowed (a panic in debug builds, a wrong object number in
release). Covered in xref::tests::xref_stream_entries_need_backing_bytes.

* hayro-cmap: a binary usecmap counts against the nesting limit; /W2 checks the CID first

- hayro-cmap: a binary CMap's usecmap passed its own depth to the nested
  parse, so a self-referencing binary CMap recursed until the stack
  overflowed. It now counts like a text usecmap. Test:
  self_referencing_binary_usecmap_stops_at_the_nesting_limit.
- hayro-interpret: the /W2 first-CID check runs before the run's metrics
  are read, so an incomplete run past CID 65535 no longer discards the
  rest of the table.

* hayro-syntax: refuse xref-stream object numbers past i32::MAX

ObjectIdentifier stores an i32; a number between i32::MAX and u32::MAX
was cast to a negative object number.
2026-10-23 22:17:04 -04:00
aiongg 07f1250d6c Merge upstream main into print-color 2026-10-24 02:09:21 +00:00