Compare commits

..
Author SHA1 Message Date
Dylan M. Taylor 875029b502 Repair: bound the notes page size like a slide 2026-11-04 03:24:13 +00:00
4 changed files with 13 additions and 24 deletions
+1 -17
View File
@@ -777,14 +777,6 @@ fn decode_frame(job: &FrameJob, pool: &Pool, stats: &mut DecodeStats) -> Result<
Ok((rf, pic))
}
/// Bytes all parallel tile states may hold of whole-frame CDEF and restoration metadata; past it
/// the tiles decode one after another on the frame's own metadata.
const TILE_METADATA_BUDGET: usize = 256 << 20;
fn tile_metadata_fits(tiles: usize, per_tile: usize) -> bool {
tiles.checked_mul(per_tile).is_some_and(|n| n <= TILE_METADATA_BUDGET)
}
/// Decode the tiles of a frame (tile number, data), in parallel when several; returns the final
/// CDFs of tile context_update_tile_id.
fn decode_tiles(pool: &Pool, fs: &mut FrameState, cdfs: &Cdfs, tiles: &[(usize, Vec<u8>)]) -> Result<Option<Box<Cdfs>>> {
@@ -798,7 +790,7 @@ fn decode_tiles(pool: &Pool, fs: &mut FrameState, cdfs: &Cdfs, tiles: &[(usize,
};
// Intra block copy reads the current frame through the tile's own buffer: keep whole-frame
// buffers (tiles one after another) for it.
if tiles.len() > 1 && pool.is_parallel() && !fs.fh.allow_intrabc && tile_metadata_fits(tiles.len(), fs.tile_metadata_bytes()) {
if tiles.len() > 1 && pool.is_parallel() && !fs.fh.allow_intrabc {
let mut states: Vec<TileState> = tiles
.iter()
.map(|(num, _)| {
@@ -1083,14 +1075,6 @@ mod guard_tests {
#[cfg(test)]
mod budget_tests {
use super::*;
#[test]
fn tile_metadata_copies_are_budgeted() {
assert!(tile_metadata_fits(64, 1 << 20));
assert!(!tile_metadata_fits(4096, 1 << 20));
assert!(!tile_metadata_fits(usize::MAX, 2));
}
use deckcraft_bitstream::budget::DECODE_MEMORY_BUDGET;
fn color(mono: bool) -> crate::header::ColorConfig {
-7
View File
@@ -253,13 +253,6 @@ impl FrameState {
self.lr = t.lr;
}
/// Bytes of CDEF and loop-restoration metadata each parallel tile state copies whole.
pub fn tile_metadata_bytes(&self) -> usize {
let lr = &self.lr;
// 1 (type) + 6 (Wiener) + 1 (SGR set) + 2 (SGR weights) bytes per unit.
self.cdef.len() + lr.lr_type.iter().map(|v| v.len() * 10).sum::<usize>()
}
/// Private buffers for the tile covering mode info rows [r0, r1) x columns [c0, c1); tiles
/// on the right / bottom frame edge also cover the allocation margins.
pub fn tile_state(&self, r0: usize, r1: usize, c0: usize, c1: usize) -> TileState {
+5
View File
@@ -247,6 +247,11 @@ pub fn repair(p: &mut Presentation) {
if !(p.notes_size.width.is_finite() && p.notes_size.width > 0.0 && p.notes_size.height.is_finite() && p.notes_size.height > 0.0) {
p.notes_size = Presentation::default().notes_size;
}
// A notes page is bounded like a slide: canvas and handout drawing scale with it.
p.notes_size = deckcraft_model::Size::new(
p.notes_size.width.clamp(*SLIDE_SIDE.start(), *SLIDE_SIDE.end()),
p.notes_size.height.clamp(*SLIDE_SIDE.start(), *SLIDE_SIDE.end()),
);
sane_numbers(p);
}
+7
View File
@@ -451,6 +451,13 @@ fn degenerate_slide_sizes_are_repaired() {
}
}
#[test]
fn repair_bounds_the_notes_page_size() {
let mut p = Presentation { notes_size: deckcraft_model::Size::new(1e12, 0.01), ..Default::default() };
repair(&mut p);
assert_eq!((p.notes_size.width, p.notes_size.height), (4032.0, 72.0));
}
/// A file whose slide size is null, a string or missing a side (written by hand or by
/// another tool; NaN is also saved as null) opens with the default size rather than failing
/// as damaged.