When stroking a rounded rectangle path with tiny-skia and rendering it at a small pixel size, a visible streak/artifact appears in the corners. The exact same path renders cleanly at a larger output size.
The bug is in tiny-skia alone — it does not require resvg/usvg. The path is built directly with tiny_skia::PathBuilder and rendered with Pixmap::stroke_path.
[dependencies]
tiny-skia = "0.12.0"
// The path corresponds to this SVG, which is what we started from:
//
// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
// <svg xmlns="http://www.w3.org/2000/svg"
// xmlns:xlink="http://www.w3.org/1999/xlink"
// height="3.5in" preserveAspectRatio="none"
// viewBox="-120 -168 240 336" width="2.5in">
// <rect width="239" height="335" x="-119.5" y="-167.5"
// rx="12" ry="12" fill="white" stroke="black"></rect>
// </svg>
use tiny_skia::{Color, FillRule, Paint, PathBuilder, Pixmap, Stroke, Transform};
fn render(to_width: u32, to_height: u32) -> Vec<u8> {
let svg_w = 240.0_f32;
let svg_h = 336.0_f32;
let mut target_height = to_height;
let mut scale = target_height as f32 / svg_h;
let mut target_width = (svg_w * scale).round() as u32;
if target_width > to_width {
scale = to_width as f32 / svg_w;
target_width = to_width;
target_height = (svg_h * scale).round() as u32;
}
let mut pixmap = Pixmap::new(target_width, target_height).unwrap();
pixmap.fill(Color::WHITE);
let transform = Transform::from_scale(scale, scale)
.post_translate(120.0 * scale, 168.0 * scale);
let x = -119.5_f32;
let y = -167.5_f32;
let w = 239.0_f32;
let h = 335.0_f32;
let r = 12.0_f32;
let mut pb = PathBuilder::new();
pb.move_to(x + r, y);
pb.line_to(x + w - r, y);
pb.quad_to(x + w, y, x + w, y + r);
pb.line_to(x + w, y + h - r);
pb.quad_to(x + w, y + h, x + w - r, y + h);
pb.line_to(x + r, y + h);
pb.quad_to(x, y + h, x, y + h - r);
pb.line_to(x, y + r);
pb.quad_to(x, y, x + r, y);
pb.close();
let path = pb.finish().unwrap();
let mut fill_paint = Paint::default();
fill_paint.set_color_rgba8(255, 255, 255, 255);
fill_paint.anti_alias = true;
pixmap.fill_path(&path, &fill_paint, FillRule::Winding, transform, None);
let mut stroke_paint = Paint::default();
stroke_paint.set_color_rgba8(0, 0, 0, 255);
stroke_paint.anti_alias = true;
let stroke = Stroke { width: 1.0, ..Stroke::default() };
pixmap.stroke_path(&path, &stroke_paint, &stroke, transform, None);
pixmap.encode_png().unwrap()
}
fn main() {
std::fs::write("ok.png", render(286, 400)).unwrap();
std::fs::write("glitches.png", render(143, 200)).unwrap();
}
Both outputs should show a clean rounded-rectangle stroke. Lower resolution should only reduce anti-aliasing detail, not introduce structural artifacts.
• The bug was originally encountered through resvg + usvg rendering an SVG card. I narrowed it down by reconstructing the same path with PathBuilder and reproducing the artifact without any SVG pipeline involved — so the root cause is in tiny-skia's path rendering (likely stroke tessellation / AA edge accumulation), not in the SVG layer.
Description
When stroking a rounded rectangle path with tiny-skia and rendering it at a small pixel size, a visible streak/artifact appears in the corners. The exact same path renders cleanly at a larger output size.
The bug is in tiny-skia alone — it does not require resvg/usvg. The path is built directly with tiny_skia::PathBuilder and rendered with Pixmap::stroke_path.
Reproduction
Cargo.toml:
src/main.rs:
Expected Behavior
Both outputs should show a clean rounded-rectangle stroke. Lower resolution should only reduce anti-aliasing detail, not introduce structural artifacts.
Actual Behavior
• ok.png (286×400) — renders correctly:

• glitches.png (143×200) — a visible streak appears in the corners:

Notes
• The bug was originally encountered through resvg + usvg rendering an SVG card. I narrowed it down by reconstructing the same path with PathBuilder and reproducing the artifact without any SVG pipeline involved — so the root cause is in tiny-skia's path rendering (likely stroke tessellation / AA edge accumulation), not in the SVG layer.