From b3551e3ce62f8f4e080c694632349e80decca93c Mon Sep 17 00:00:00 2001 From: aiongg Date: Tue, 13 Oct 2026 19:37:52 +0000 Subject: [PATCH] Integration: #588 CMYK ink passes cull items to the area they cover --- crates/render/src/blendspace.rs | 24 +++++++++++++++++++++++- crates/render/src/lib.rs | 5 +++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/render/src/blendspace.rs b/crates/render/src/blendspace.rs index e2f6600c5..5393d9cc2 100644 --- a/crates/render/src/blendspace.rs +++ b/crates/render/src/blendspace.rs @@ -370,13 +370,21 @@ impl Renderer { // Inside it: the two ink passes, with the render threads, over just the area. let (aw, ah) = (area.width() as u16, area.height() as u16); let shifted = Affine::translate((-area.x0, -area.y0)) * f.view; + // The passes draw only what reaches the area: items elsewhere are culled. + let visible = f.view.inverse().transform_rect_bbox(area); let stats = self.stats; let threads = self.threads; let mut pass = |plate| { let opts = RenderOptions { plate: Some(plate), ..rgb.clone() }; crate::PLATE.with(|p| p.set(opts.plate)); let mut off = RenderContext::new_with(aw, ah, vello_cpu::RenderSettings { num_threads: threads, ..Default::default() }); - self.draw_spread(&mut off, &Frame { opts: &opts, view: shifted, mt: threads > 0, ..*f }, sr); + #[cfg(test)] + let items = self.stats.items; + self.draw_spread(&mut off, &Frame { opts: &opts, view: shifted, visible, mt: threads > 0, ..*f }, sr); + #[cfg(test)] + { + self.cmyk_pass_items = self.stats.items - items; + } off.flush(); let mut pm = vello_cpu::Pixmap::new(aw, ah); off.render(&mut pm, &mut self.resources); @@ -593,6 +601,20 @@ mod tests { assert!(renderer.cmyk_pass_pixels >= 75 * 45, "{} px", renderer.cmyk_pass_pixels); } + #[test] + fn ink_passes_draw_only_the_items_that_reach_their_area() { + // A small Multiply object in a corner and a solid one far from it: the ink passes cover the + // corner and draw just the Multiply object. + let mut doc = document(); + rectangle(&mut doc, SpreadRef::Doc(0), Rect::new(100.0, 70.0, 150.0, 110.0), "C=100 M=0 Y=0 K=0", DcBlend::Normal); + rectangle(&mut doc, SpreadRef::Doc(0), Rect::new(5.0, 5.0, 25.0, 25.0), "C=0 M=100 Y=0 K=0", DcBlend::Multiply); + let mut renderer = Renderer::new(); + renderer.threads = 0; + draw(&doc, &mut renderer); + assert_eq!(renderer.cmyk_passes, 2); + assert_eq!(renderer.cmyk_pass_items, 1); + } + #[test] fn the_view_is_kept_only_when_the_ink_passes_ran() { let mut doc = document(); diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index 8406795ab..c73353ad1 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -235,6 +235,9 @@ pub struct Renderer { /// Pixels the last ink pass covered (tests). #[cfg(test)] cmyk_pass_pixels: usize, + /// Items the last ink pass drew (tests). + #[cfg(test)] + cmyk_pass_items: usize, pub threads: u16, pub stats: FrameStats, } @@ -287,6 +290,8 @@ impl Renderer { cmyk_passes: 0, #[cfg(test)] cmyk_pass_pixels: 0, + #[cfg(test)] + cmyk_pass_items: 0, threads: default_threads(), stats: FrameStats::default(), }