From 9bb38208c1dfae03ebf8a4ff911071fdb2ce9e14 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 31 Oct 2026 19:17:08 -0700 Subject: [PATCH] Character: type whose method would draw past the pixel budget is drawn as Sharp None, Crisp and Strong type is drawn offscreen on the output's pixels. The offscreen drawing was limited to 32,768 pixels a side, but not in area, so type across a large raster export held several more images of the export's size. Type whose offscreen drawing would hold more than the renderer's pixel budget (8.4 million pixels) is now drawn as Sharp draws it. --- crates/render/src/renderer/text.rs | 7 ++++--- crates/render/src/tests/typeedges.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) 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]