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.
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.
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.
Preserve the reviewed shared UI tree and the frozen app dependency commit while
bringing in current main. Port the new keymap UI APIs and use verified central
fonts in its strict UI tests and snapshots.
Dragging a native window's only tab, or its only group, moves the
window and docks it on release. It took a frame's edges and its tab
strip but not its body's center, a rule meant for the bar, so the
center rectangle was neither a target nor filled under the pointer.
Such a move now joins the center as the tab or group drag would; the
bar still does not.
The ×'s glyph inset, size and hit area are set in one place (MACOS_CLOSE,
OTHER_CLOSE in render/native.rs). On macOS the glyph sits where macOS puts its
close button, and the hit area reaches 10 pt toward the leading edge and down
to the bar's bottom, past AppKit's corner resize area. Elsewhere the layout is
the same as before. CRAFT_DOCK_DEBUG_CLOSE=1 outlines the hit area and AppKit's
resize areas.
egui-winit starts RawInput::focused false and only a winit Focused event
sets it. A window that egui never heard was focused cancelled every tab,
group and window drag and every resize on its first frame. Gestures now
end on a focused-to-unfocused transition (or Escape); a window that
never reported focus still drags while the pointer is pressed in it.
A side split that leaves a half at its minimum is taken when the
dividers along that half can still travel, the groups beyond giving
way as they do for a dragged divider. An 80 pt group, whose halves
need 84, splits on all four sides and takes the rest from its
neighbour; only when the groups beyond are at their minimums too does
the drop join the group's tabs.
On macOS the native window is resizable by AppKit again, with its own areas
and cursors. The bar's buttons sit 19 pt in from the trailing edge, clear of
AppKit's corner area (about 15 pt into the window, a 19 pt square measured on
macOS 26), and the window sets no cursor of its own over AppKit's areas.
Elsewhere the bands are 6 pt deep with 16 pt corner Ls, and hand the resize
to the window system; the manual resize path is gone.
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.
* 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.
Floating::new, single and stack draw a fresh id on each call, so a layout
built anew each frame opened a new OS window each frame. with_id gives such
a layout the same windows every frame. Debug builds log a warning once when
three frames running replace every native window with new ones holding the
same panels.
Each side zone reaches zone_depth into the body, or a quarter of the
body's smaller side when that is less. A tall narrow group's top and
bottom zones are no deeper than its left and right ones.
A divider dragged past the minimum of the group it shrinks moves on to
the next group along the axis, and so on until every group on that side
is at its minimum. The line follows same-axis splits up the tree and
ends at a split across the axis or beside a dock. Groups touching the
divider on the other side grow, up to their maximums, as before.
Stacked panels and the groups of a dock column cascade the same way.
The bands along a native window's edges leave out the bar's buttons, which
sit 4 pt in from the window's edge. Each corner is an L, 4 pt deep and 12 pt
along both edges. macOS windows are not resizable by AppKit, whose resize
areas reach over the ×; the bands resize them by InnerSize and OuterPosition,
since winit has no BeginResize there.
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.
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).