diff --git a/crates/render/src/renderer/text.rs b/crates/render/src/renderer/text.rs index 1642fd193..9db9ba8e3 100644 --- a/crates/render/src/renderer/text.rs +++ b/crates/render/src/renderer/text.rs @@ -233,7 +233,7 @@ impl Renderer { /// Overprint Preview is on, and type that shows a substitution highlight on screen. Drawn /// offscreen, those would blend with nothing or take the method on art that is not the /// characters'. It also returns false for type whose offscreen drawing would be more than - /// [`MAX_RASTER_SIDE`] pixels a side. + /// [`MAX_RASTER_SIDE`] pixels a side or more than [`fx::PIXEL_BUDGET`] pixels in all. fn draw_type_edges(&mut self, ctx: &mut RenderContext, f: &Frame, n: &Node, t: &TextObject, g: &Arc, geom_kept: bool) -> bool { if proof::overprints(f.opts) && t.runs.iter().any(|r| r.style.overprint_fill || r.style.overprint_stroke) { return false; @@ -280,8 +280,9 @@ impl Renderer { // Whole pixels of the output. let (x0, y0) = (on.x0.floor(), on.y0.floor()); let (Ok(w), Ok(h)) = (u16::try_from((on.x1 - x0).ceil() as u64), u16::try_from((on.y1 - y0).ceil() as u64)) else { return false }; - // (vello_cpu panics drawing near `u16::MAX` pixels a side.) - if u32::from(w) > MAX_RASTER_SIDE || u32::from(h) > MAX_RASTER_SIDE { + // (vello_cpu panics drawing near `u16::MAX` pixels a side.) Past the pixel budget the type + // is drawn as Sharp draws it. + if u32::from(w) > MAX_RASTER_SIDE || u32::from(h) > MAX_RASTER_SIDE || f64::from(w) * f64::from(h) > fx::PIXEL_BUDGET { return false; } let view = Affine::translate((-x0, -y0)) * output; diff --git a/crates/render/src/tests/typeedges.rs b/crates/render/src/tests/typeedges.rs index 3ea7e1735..b98dfe60f 100644 --- a/crates/render/src/tests/typeedges.rs +++ b/crates/render/src/tests/typeedges.rs @@ -546,6 +546,27 @@ fn type_edges_are_drawn_on_at_most_the_budgets_pixels() { assert_eq!(edge_grid(Rect::new(0.0, 0.0, 10_000.0, 1.0), coarser), Affine::IDENTITY, "40,000 pixels a side"); } +/// Type whose offscreen drawing would hold more pixels than the effects' pixel budget (in a large +/// raster export) is drawn as Sharp draws it, without the offscreen drawing; just within the +/// budget it is drawn offscreen with its method. +#[test] +fn type_past_the_pixel_budget_is_drawn_as_sharp() { + // "Hamburg" at 10,000%, its letters across every pixel of the render. + let draw = |m: TypeAntiAlias, side: u32| { + let half = f64::from(side) / 2.0; + let view = Affine::translate((half - 9_000.0, half - 4_500.0)) * Affine::scale(100.0); + let mut r = Renderer::new(); + let pixels = r.render(&page(m, None), side, side, view, &RenderOptions::default()).pixels; + (r.stats.type_edges, pixels) + }; + // 3,000 × 3,000 pixels, past the 8.4 million of the budget. + let (drawn, strong) = draw(TypeAntiAlias::Strong, 3_000); + assert_eq!(drawn, 0, "the type is not drawn offscreen"); + assert!(strong == draw(TypeAntiAlias::Sharp, 3_000).1, "the type is drawn as Sharp draws it"); + // 2,800 × 2,800 pixels, within it. + assert_eq!(draw(TypeAntiAlias::Strong, 2_800).0, 1, "the type is drawn offscreen"); +} + /// Type across a canvas of the largest side the renderer draws (`MAX_CONTEXT_SIDE` pixels) is /// drawn with its method on every pixel. #[test]