mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 06:01:18 +00:00
Type: type edges are drawn offscreen on at most 32,768 pixels a side
`Renderer::draw_type_edges` let its offscreen drawing grow to `u16::MAX` pixels a side, the size at which vello_cpu panics. In a frame drawn coarser than the output, a thin strip of type could take more than 32,768 output pixels a side while staying within the pixel budget. The offscreen drawing now uses the frame's own pixels when the output's would be more than `MAX_RASTER_SIDE` a side, and type whose offscreen drawing would still be larger than that is drawn as Sharp, as `fx.rs` limits its offscreen rasters to `MAX_RASTER_SIDE`.
This commit is contained in:
@@ -1914,8 +1914,8 @@ impl Renderer {
|
||||
/// strokes in opaque black, which gives the share `c` of each pixel they cover; the pixel's
|
||||
/// color and opacity are then scaled by [`edge_coverage`] of `c` divided by `c`, so the opacity
|
||||
/// of the paints is kept. Where the output's pixels would number more than the frame's there
|
||||
/// and more than [`fx::PIXEL_BUDGET`] (a frame drawn coarser than the output), the frame's own
|
||||
/// pixels are used.
|
||||
/// and more than [`fx::PIXEL_BUDGET`], or be more than [`MAX_RASTER_SIDE`] a side (a frame
|
||||
/// drawn coarser than the output), the frame's own pixels are used.
|
||||
///
|
||||
/// The pixels are kept (`type_edges`). In a later frame they are placed without drawing the
|
||||
/// type offscreen while the object, the output's zoom and rotation, the method and edge
|
||||
@@ -1928,7 +1928,8 @@ impl Renderer {
|
||||
/// inline graphics, type whose own fills or strokes include a brush stroke or a blend mode
|
||||
/// other than Normal, type that overprints while 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'.
|
||||
/// 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.
|
||||
fn draw_type_edges(&mut self, ctx: &mut RenderContext, f: &Frame, n: &Node, t: &TextObject, g: &TextGeom) -> bool {
|
||||
if proof::overprints(f.opts) && t.runs.iter().any(|r| r.style.overprint_fill || r.style.overprint_stroke) {
|
||||
return false;
|
||||
@@ -1972,6 +1973,10 @@ 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 {
|
||||
return false;
|
||||
}
|
||||
let view = Affine::translate((-x0, -y0)) * output;
|
||||
let visible = view.inverse().transform_rect_bbox(Rect::new(0.0, 0.0, f64::from(w), f64::from(h)));
|
||||
let px = 1.0 / view.determinant().abs().sqrt().max(1e-12);
|
||||
@@ -2355,10 +2360,11 @@ fn type_reach(n: &Node, t: &TextObject, g: &TextGeom) -> Rect {
|
||||
/// The map from a frame's pixels to the pixels [`Renderer::draw_type_edges`] draws type on, for
|
||||
/// the region `on` of the frame's pixels: `grid`, which maps them to the output's, unless the
|
||||
/// output's pixels there would number more than the frame's and more than [`fx::PIXEL_BUDGET`],
|
||||
/// and then the frame's own pixels (the identity).
|
||||
/// or be more than [`MAX_RASTER_SIDE`] a side, and then the frame's own pixels (the identity).
|
||||
fn edge_grid(on: Rect, grid: Affine) -> Affine {
|
||||
let area = |r: Rect| r.width() * r.height();
|
||||
if area(grid.transform_rect_bbox(on)) > area(on).max(fx::PIXEL_BUDGET) { Affine::IDENTITY } else { grid }
|
||||
let (out, side) = (grid.transform_rect_bbox(on), f64::from(MAX_RASTER_SIDE));
|
||||
if area(out) > area(on).max(fx::PIXEL_BUDGET) || out.width() > side || out.height() > side { Affine::IDENTITY } else { grid }
|
||||
}
|
||||
|
||||
/// Pixel `p` of type the anti-aliasing method `m` draws, where the type covers `c` (out of 255) of
|
||||
|
||||
@@ -253,7 +253,8 @@ fn type_with_an_alternate_glyph_highlight_is_drawn_as_sharp() {
|
||||
}
|
||||
|
||||
/// The type is drawn on the output's pixels unless, in a frame coarser than the output, they
|
||||
/// would number more than the frame's there and more than the effects' pixel budget.
|
||||
/// would number more than the frame's there and more than the effects' pixel budget, or be more
|
||||
/// than `MAX_RASTER_SIDE` a side.
|
||||
#[test]
|
||||
fn type_edges_are_drawn_on_at_most_the_budgets_pixels() {
|
||||
let finer = Affine::scale(0.25);
|
||||
@@ -261,6 +262,20 @@ fn type_edges_are_drawn_on_at_most_the_budgets_pixels() {
|
||||
let coarser = Affine::scale(4.0);
|
||||
assert_eq!(edge_grid(Rect::new(0.0, 0.0, 100.0, 100.0), coarser), coarser, "160,000 pixels");
|
||||
assert_eq!(edge_grid(Rect::new(0.0, 0.0, 1000.0, 1000.0), coarser), Affine::IDENTITY, "16 million 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 be more than `MAX_RASTER_SIDE` pixels a side is drawn as
|
||||
/// Sharp type is.
|
||||
#[test]
|
||||
fn type_wider_than_the_raster_limit_is_drawn_as_sharp() {
|
||||
// "Hamburg" at 25,000%, about 37,000 pixels wide, on four rows through its letters.
|
||||
let view = Affine::translate((-2_000.0, -12_500.0)) * Affine::scale(250.0);
|
||||
let draw = |m| Renderer::new().render(&page(m, None), 40_000, 4, view, &RenderOptions::default()).pixels;
|
||||
let sharp = draw(TypeAntiAlias::Sharp);
|
||||
let a: Vec<u8> = sharp.chunks(4).map(|p| p[3]).collect();
|
||||
assert!(partial(&a) > 0, "the rows cross the edges of the letters");
|
||||
assert!(draw(TypeAntiAlias::None) == sharp, "None type is drawn as Sharp");
|
||||
}
|
||||
|
||||
/// The offscreen drawing takes in the farthest a stroke reaches: a mitered character stroke's
|
||||
|
||||
Reference in New Issue
Block a user