Files
wordcraft/crates/layout/Cargo.toml
T
VoiceLessQ d7429d217a Pictures: one decoder checks the header against the budget, progressive JPEG coefficients included (#3644)
Document pictures now decode through wordcraft_geom::picture (behind a
new `image` feature of the geom crate). It reads the header, refuses the
picture before anything is allocated when the decode's peak would pass
the budget, then decodes with the header's size and the budget as
limits.

The peak is the larger of three moments: the decoder's output beside
what it holds while decoding, the output beside its RGBA8 conversion,
and that beside a premultiplied copy. A progressive JPEG's decoder
(zune-jpeg) holds an i16 for every coefficient of every component, in
whole MCUs, for the whole picture; the SOF header gives that size. A
7900 x 7900 progressive JPEG without subsampling needs 9 bytes a pixel
(561 MB), past the 512 MB budget, although two RGBA buffers (499 MB)
fit. With the fix reverted, the test's header-only file of that size
was decoded and the test process peaked at 542 MiB resident.

- Render and PDF export ask the probe in their wrappers (decode_pixmap,
  load_image), so a picture past the budget gets the grey box or is
  left out, as before.
- The crop dialog and every picture edit decoded with load_from_memory
  and looked at the size afterwards. They decode through the probe now,
  and so do wrap outlines and the RTF re-encode.
- A picture edit has the drawing budget instead of an 80 M pixel cap
  checked after decoding. A picture past that budget (about 67 M RGBA
  pixels) can't be drawn either, so no edit that could be seen is lost.
2026-10-24 18:01:45 -01:00

29 lines
947 B
TOML

[package]
name = "wordcraft-layout"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "WordCraft layout: shaping, line breaking, tabs, lists, tables, pagination, headers/footers, hit testing"
[lints]
workspace = true
[dependencies]
wordcraft-geom = { workspace = true, features = ["image"] }
wordcraft-doc = { workspace = true }
wordcraft-fonts = { workspace = true }
wordcraft-proof = { workspace = true }
wordcraft-metafile = { workspace = true }
kurbo = { workspace = true }
unicode-bidi = { workspace = true }
unicode-linebreak = { workspace = true }
unicode-segmentation = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
image = { workspace = true }
log = { workspace = true }
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
# The browser clock (`SystemTime::now()`/`Instant::now()` panic on wasm32-unknown-unknown).
js-sys = "0.3"