Vendor things

This commit is contained in:
John Doty 2024-03-08 11:03:01 -08:00
parent 5deceec006
commit 977e3c17e5
19434 changed files with 10682014 additions and 0 deletions

View file

@ -0,0 +1,199 @@
use tiny_skia::*;
#[test]
fn rect() {
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, false);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pixmap = Pixmap::new(100, 100).unwrap();
let rect = Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/rect.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn rect_aa() {
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.5, 10.0, 80.0, 80.5).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, true);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pixmap = Pixmap::new(100, 100).unwrap();
let rect = Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/rect-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn rect_ts() {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
let clip_path = clip_path.transform(Transform::from_row(1.0, -0.3, 0.0, 1.0, 0.0, 15.0)).unwrap();
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, false);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/rect-ts.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn circle_bottom_right_aa() {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let clip_path = PathBuilder::from_circle(100.0, 100.0, 50.0).unwrap();
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, true);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/circle-bottom-right-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn stroke() {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, false);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut stroke = Stroke::default();
stroke.width = 10.0;
let path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/stroke.png").unwrap();
assert_eq!(pixmap, expected);
}
// Make sure we're clipping only source and not source and destination
#[test]
fn skip_dest() {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
pixmap.fill_path(
&PathBuilder::from_rect(Rect::from_xywh(5.0, 5.0, 60.0, 60.0).unwrap()),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
let mut pixmap2 = Pixmap::new(200, 200).unwrap();
pixmap2.as_mut().fill_path(
&PathBuilder::from_rect(Rect::from_xywh(35.0, 35.0, 60.0, 60.0).unwrap()),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
let clip_path = PathBuilder::from_rect(Rect::from_xywh(40.0, 40.0, 40.0, 40.0).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, true);
pixmap.draw_pixmap(0, 0, pixmap2.as_ref(), &PixmapPaint::default(),
Transform::identity(), Some(&clip_mask));
let expected = Pixmap::load_png("tests/images/clip/skip-dest.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn intersect_aa() {
let circle1 = PathBuilder::from_circle(75.0, 75.0, 50.0).unwrap();
let circle2 = PathBuilder::from_circle(125.0, 125.0, 50.0).unwrap();
let mut clip_mask = ClipMask::new();
clip_mask.set_path(200, 200, &circle1, FillRule::Winding, true);
clip_mask.intersect_path(&circle2, FillRule::Winding, true);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_rect(
Rect::from_xywh(0.0, 0.0, 200.0, 200.0).unwrap(),
&paint,
Transform::identity(),
Some(&clip_mask),
);
let expected = Pixmap::load_png("tests/images/clip/intersect-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn ignore_memset() {
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, false);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 255);
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(
Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap(),
&paint,
Transform::identity(),
Some(&clip_mask),
);
let expected = Pixmap::load_png("tests/images/clip/ignore-memset.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn ignore_source() {
let clip_path = PathBuilder::from_rect(Rect::from_xywh(10.0, 10.0, 80.0, 80.0).unwrap());
let mut clip_mask = ClipMask::new();
clip_mask.set_path(100, 100, &clip_path, FillRule::Winding, false);
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 255); // Must be opaque.
paint.blend_mode = BlendMode::SourceOver;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill(Color::WHITE);
pixmap.fill_rect(
Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap(),
&paint,
Transform::identity(),
Some(&clip_mask),
);
let expected = Pixmap::load_png("tests/images/clip/ignore-source.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,167 @@
use tiny_skia::*;
#[test]
fn line() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(90.0, 80.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![5.0, 10.0], 0.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/line.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn quad() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.quad_to(35.0, 75.0, 90.0, 80.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![5.0, 10.0], 0.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/quad.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn cubic() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.cubic_to(95.0, 35.0, 0.0, 75.0, 75.0, 90.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![5.0, 10.0], 0.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/cubic.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn hairline() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.cubic_to(95.0, 35.0, 0.0, 75.0, 75.0, 90.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![5.0, 10.0], 0.0);
stroke.width = 0.5;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/hairline.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn complex() {
let mut pb = PathBuilder::new();
pb.move_to(28.7, 23.9);
pb.line_to(177.4, 35.2);
pb.line_to(177.4, 68.0);
pb.line_to(129.7, 68.0);
pb.cubic_to(81.6, 59.3, 41.8, 63.3, 33.4, 115.2);
pb.cubic_to(56.8, 128.7, 77.3, 143.8, 53.3, 183.8);
pb.cubic_to(113.8, 185.7, 91.0, 109.7, 167.3, 111.8);
pb.cubic_to(-56.2, 90.3, 177.3, 68.0, 110.2, 95.5);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![10.0, 5.0], 2.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/complex.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn multi_subpaths() {
let mut pb = PathBuilder::new();
pb.move_to(49.0, 76.0);
pb.cubic_to(22.0, 150.0, 11.0, 213.0, 186.0, 151.0);
pb.cubic_to(194.0, 106.0, 195.0, 64.0, 169.0, 26.0);
pb.move_to(124.0, 41.0);
pb.line_to(162.0, 105.0);
pb.cubic_to(135.0, 175.0, 97.0, 166.0, 53.0, 128.0);
pb.line_to(93.0, 71.0);
pb.move_to(24.0, 52.0);
pb.line_to(108.0, 20.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![10.0, 5.0], 2.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/multi_subpaths.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn closed() {
let mut pb = PathBuilder::new();
pb.move_to(22.0, 22.0);
pb.cubic_to(63.0, 16.0, 82.0, 24.0, 84.0, 46.0);
pb.cubic_to(86.0, 73.0, 15.0, 58.0, 16.0, 89.0);
pb.close();
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![10.0, 5.0], 2.0);
stroke.width = 2.0;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/dash/closed.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,615 @@
use tiny_skia::*;
#[test]
fn horizontal_line() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(90.0, 10.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/empty.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn vertical_line() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(10.0, 90.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/empty.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn single_line() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(90.0, 90.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/empty.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn int_rect() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(10.0, 15.0, 80.0, 70.0).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/int-rect.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn float_rect() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(10.3, 15.4, 80.5, 70.6).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn int_rect_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(10.0, 15.0, 80.0, 70.0).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/int-rect-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn float_rect_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(10.3, 15.4, 80.5, 70.6).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn float_rect_aa_highp() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
paint.force_hq_pipeline = true;
let rect = Rect::from_xywh(10.3, 15.4, 80.5, 70.6).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect-aa-highp.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn tiny_float_rect() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(1.3, 1.4, 0.5, 0.6).unwrap();
let mut pixmap = Pixmap::new(3, 3).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
assert_eq!(
pixmap.pixels(),
&[
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(50, 127, 150, 200).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
]
);
}
#[test]
fn tiny_float_rect_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(1.3, 1.4, 0.5, 0.6).unwrap();
let mut pixmap = Pixmap::new(3, 3).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
assert_eq!(
pixmap.pixels(),
&[
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(51, 128, 153, 60).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
ColorU8::from_rgba(0, 0, 0, 0).premultiply(),
]
);
}
#[test]
fn float_rect_clip_top_left_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(-10.3, -20.4, 100.5, 70.2).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect-clip-top-left-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn float_rect_clip_top_right_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(60.3, -20.4, 100.5, 70.2).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect-clip-top-right-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn float_rect_clip_bottom_right_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let rect = Rect::from_xywh(60.3, 40.4, 100.5, 70.2).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/float-rect-clip-bottom-right-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn int_rect_with_ts_clip_right() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(0.0, 0.0, 100.0, 100.0).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::from_row(1.0, 0.0, 0.0, 1.0, 0.5, 0.5), None);
let expected = Pixmap::load_png("tests/images/fill/int-rect-with-ts-clip-right.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn open_polygon() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(75.160671, 88.756136);
pb.line_to(24.797274, 88.734053);
pb.line_to( 9.255130, 40.828792);
pb.line_to(50.012955, 11.243795);
pb.line_to(90.744819, 40.864522);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/polygon.png").unwrap();
assert_eq!(pixmap, expected);
}
// Must be the same a open.
#[test]
fn closed_polygon() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(75.160671, 88.756136);
pb.line_to(24.797274, 88.734053);
pb.line_to( 9.255130, 40.828792);
pb.line_to(50.012955, 11.243795);
pb.line_to(90.744819, 40.864522);
pb.close(); // the only difference
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/polygon.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn winding_star() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(50.0, 7.5);
pb.line_to(75.0, 87.5);
pb.line_to(10.0, 37.5);
pb.line_to(90.0, 37.5);
pb.line_to(25.0, 87.5);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/winding-star.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn even_odd_star() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(50.0, 7.5);
pb.line_to(75.0, 87.5);
pb.line_to(10.0, 37.5);
pb.line_to(90.0, 37.5);
pb.line_to(25.0, 87.5);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::EvenOdd, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/even-odd-star.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn quad_curve() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 15.0);
pb.quad_to(95.0, 35.0, 75.0, 90.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::EvenOdd, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/quad.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn cubic_curve() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 15.0);
pb.cubic_to(95.0, 35.0, 0.0, 75.0, 75.0, 90.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::EvenOdd, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/cubic.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn memset2d() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 255); // Must be opaque to trigger memset2d.
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 90.0, 90.0).unwrap());
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/memset2d.png").unwrap();
assert_eq!(pixmap, expected);
}
// Make sure we do not write past pixmap memory.
#[test]
fn memset2d_out_of_bounds() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 255); // Must be opaque to trigger memset2d.
let path = PathBuilder::from_rect(Rect::from_ltrb(50.0, 50.0, 120.0, 120.0).unwrap());
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/memset2d-2.png").unwrap();
assert_eq!(pixmap, expected);
}
// Not sure how to properly test anti-aliasing,
// so for now simply check that it actually applied.
#[test]
fn fill_aa() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(50.0, 7.5);
pb.line_to(75.0, 87.5);
pb.line_to(10.0, 37.5);
pb.line_to(90.0, 37.5);
pb.line_to(25.0, 87.5);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::EvenOdd, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/star-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn overflow_in_walk_edges_1() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.cubic_to(39.0, 163.0, 117.0, 61.0, 130.0, 70.0);
let path = pb.finish().unwrap();
// Must not panic.
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
}
#[test]
fn clip_line_1() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(50.0, -15.0);
pb.line_to(-15.0, 50.0);
pb.line_to(50.0, 115.0);
pb.line_to(115.0, 50.0);
pb.close();
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/clip-line-1.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn clip_line_2() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
// This strange path forces `line_clipper::clip` to return an empty array.
// And we're checking that this case is handled correctly.
let mut pb = PathBuilder::new();
pb.move_to(0.0, -1.0);
pb.line_to(50.0, 0.0);
pb.line_to(0.0, 50.0);
pb.close();
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/clip-line-2.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn clip_quad() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let mut pb = PathBuilder::new();
pb.move_to(10.0, 85.0);
pb.quad_to(150.0, 150.0, 85.0, 15.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/clip-quad.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn clip_cubic_1() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
// `line_clipper::clip` produces 2 points for this path.
let mut pb = PathBuilder::new();
pb.move_to(10.0, 50.0);
pb.cubic_to(0.0, 175.0, 195.0, 70.0, 75.0, 20.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/clip-cubic-1.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn clip_cubic_2() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
// `line_clipper::clip` produces 3 points for this path.
let mut pb = PathBuilder::new();
pb.move_to(10.0, 50.0);
pb.cubic_to(10.0, 40.0, 90.0, 120.0, 125.0, 20.0);
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/fill/clip-cubic-2.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn aa_endless_loop() {
let mut paint = Paint::default();
paint.anti_alias = true;
// This path was causing an endless loop before.
let mut pb = PathBuilder::new();
pb.move_to(2.1537175, 11.560721);
pb.quad_to(1.9999998, 10.787931, 2.0, 10.0);
let path = pb.finish().unwrap();
// Must not loop.
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
}
#[test]
fn clear_aa() {
// Make sure that Clear with AA doesn't fallback to memset.
let mut paint = Paint::default();
paint.anti_alias = true;
paint.blend_mode = BlendMode::Clear;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill(Color::from_rgba8(50, 127, 150, 200));
pixmap.fill_path(
&PathBuilder::from_circle(50.0, 50.0, 40.0).unwrap(),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
let expected = Pixmap::load_png("tests/images/fill/clear-aa.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn line_curve() {
let mut paint = Paint::default();
paint.anti_alias = true;
let path = {
let mut pb = PathBuilder::new();
pb.move_to(100.0, 20.0);
pb.cubic_to(100.0, 40.0, 100.0, 160.0, 100.0, 180.0); // Just a line.
pb.finish().unwrap()
};
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
// Must not panic.
}
#[test]
fn vertical_lines_merging_bug() {
// This path must not trigger edge_builder::combine_vertical,
// otherwise AlphaRuns::add will crash later.
let mut pb = PathBuilder::new();
pb.move_to(765.56, 158.56);
pb.line_to(754.4, 168.28);
pb.cubic_to(754.4, 168.28, 754.4, 168.24, 754.4, 168.17);
pb.cubic_to(754.4, 168.09, 754.4, 168.02, 754.4, 167.95);
pb.line_to(754.4, 168.06);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
// Must not panic.
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::from_row(5.4, 0.0, 0.0, 5.4, -4050.0, -840.0), None);
let expected = Pixmap::load_png("tests/images/fill/vertical-lines-merging-bug.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn fill_rect() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(
Rect::from_xywh(20.3, 10.4, 50.5, 30.2).unwrap(),
&paint,
Transform::from_row(1.2, 0.3, -0.7, 0.8, 12.0, 15.3),
None,
);
let expected = Pixmap::load_png("tests/images/canvas/fill-rect.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,418 @@
use tiny_skia::*;
#[test]
fn two_stops_linear_pad_lq() {
let mut paint = Paint::default();
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-pad-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_linear_repeat_lq() {
let mut paint = Paint::default();
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(100.0, 100.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Repeat,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-repeat-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_linear_reflect_lq() {
let mut paint = Paint::default();
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(100.0, 100.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Reflect,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-reflect-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn three_stops_evenly_spaced_lq() {
let mut paint = Paint::default();
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.50, Color::from_rgba8(220, 140, 75, 180)),
GradientStop::new(0.75, Color::from_rgba8(40, 180, 55, 160)),
],
// No need to check other modes. "Two stops" tests will cover them.
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/three-stops-evenly-spaced-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_unevenly_spaced_lq() {
let mut paint = Paint::default();
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.75, Color::from_rgba8(220, 140, 75, 180)),
],
// No need to check other modes. "Two stops" tests will cover them.
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-unevenly-spaced-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_linear_pad_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-pad-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_linear_repeat_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(100.0, 100.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Repeat,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-repeat-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_linear_reflect_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(100.0, 100.0),
vec![
GradientStop::new(0.0, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.0, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Reflect,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-linear-reflect-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn three_stops_evenly_spaced_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.50, Color::from_rgba8(220, 140, 75, 180)),
GradientStop::new(0.75, Color::from_rgba8(40, 180, 55, 160)),
],
// No need to check other modes. "Two stops" tests will cover them.
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/three-stops-evenly-spaced-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn two_stops_unevenly_spaced_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = LinearGradient::new(
Point::from_xy(10.0, 10.0),
Point::from_xy(190.0, 190.0),
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.75, Color::from_rgba8(220, 140, 75, 180)),
],
// No need to check other modes. "Two stops" tests will cover them.
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/two-stops-unevenly-spaced-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
// The radial gradient is only supported by the high quality pipeline.
// Therefore we do not have a lq/hq split.
#[test]
fn well_behaved_radial() {
let mut paint = Paint::default();
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(120.0, 80.0),
100.0,
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.75, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/well-behaved-radial.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn focal_on_circle_radial() {
let mut paint = Paint::default();
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(120.0, 80.0),
28.29, // This radius forces the required pipeline stage.
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.75, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/focal-on-circle-radial.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn conical_greater_radial() {
let mut paint = Paint::default();
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(120.0, 80.0),
10.0, // This radius forces the required pipeline stage.
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(0.75, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/conical-greater-radial.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn simple_radial_lq() {
let mut paint = Paint::default();
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(100.0, 100.0),
100.0,
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.00, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/simple-radial-lq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn simple_radial_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(100.0, 100.0),
100.0,
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.00, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/simple-radial-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn simple_radial_with_ts_hq() {
let mut paint = Paint::default();
paint.force_hq_pipeline = true;
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(100.0, 100.0),
100.0,
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 200)),
GradientStop::new(1.00, Color::from_rgba8(220, 140, 75, 180)),
],
SpreadMode::Pad,
Transform::from_row(2.0, 0.3, -0.7, 1.2, 10.5, -12.3),
).unwrap();
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/simple-radial-with-ts-hq.png").unwrap();
assert_eq!(pixmap, expected);
}
// Gradient doesn't add the Premultiply stage when all stops are opaque.
// But it checks colors only on creation, so we have to recheck them after calling `apply_opacity`.
#[test]
fn global_opacity() {
let mut paint = Paint::default();
paint.shader = RadialGradient::new(
Point::from_xy(100.0, 100.0),
Point::from_xy(100.0, 100.0),
100.0,
vec![
GradientStop::new(0.25, Color::from_rgba8(50, 127, 150, 255)), // no opacity here
GradientStop::new(1.00, Color::from_rgba8(220, 140, 75, 255)), // no opacity here
],
SpreadMode::Pad,
Transform::identity(),
).unwrap();
paint.shader.apply_opacity(0.5);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/gradients/global-opacity.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,257 @@
use tiny_skia::*;
fn draw_line(x0: f32, y0: f32, x1: f32, y1: f32, anti_alias: bool, width: f32, line_cap: LineCap) -> Pixmap {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let mut pb = PathBuilder::new();
pb.move_to(x0, y0);
pb.line_to(x1, y1);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = anti_alias;
let mut stroke = Stroke::default();
stroke.width = width;
stroke.line_cap = line_cap;
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
pixmap
}
#[test]
fn hline_05() {
let expected = Pixmap::load_png("tests/images/hairline/hline-05.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 90.0, 10.0, false, 0.5, LineCap::Butt), expected);
}
#[test]
fn hline_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/hline-05-aa.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 90.0, 10.0, true, 0.5, LineCap::Butt), expected);
}
#[test]
fn hline_05_aa_round() {
let expected = Pixmap::load_png("tests/images/hairline/hline-05-aa-round.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 90.0, 10.0, true, 0.5, LineCap::Round), expected);
}
#[test]
fn vline_05() {
let expected = Pixmap::load_png("tests/images/hairline/vline-05.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 10.0, 90.0, false, 0.5, LineCap::Butt), expected);
}
#[test]
fn vline_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/vline-05-aa.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 10.0, 90.0, true, 0.5, LineCap::Butt), expected);
}
#[test]
fn vline_05_aa_round() {
let expected = Pixmap::load_png("tests/images/hairline/vline-05-aa-round.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 10.0, 90.0, true, 0.5, LineCap::Round), expected);
}
#[test]
fn horish_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/horish-05-aa.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 90.0, 70.0, true, 0.5, LineCap::Butt), expected);
}
#[test]
fn vertish_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/vertish-05-aa.png").unwrap();
assert_eq!(draw_line(10.0, 10.0, 70.0, 90.0, true, 0.5, LineCap::Butt), expected);
}
#[test]
fn clip_line_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-line-05-aa.png").unwrap();
assert_eq!(draw_line(-10.0, 10.0, 110.0, 70.0, true, 0.5, LineCap::Butt), expected);
}
#[test]
fn clip_line_00() {
let expected = Pixmap::load_png("tests/images/hairline/clip-line-00.png").unwrap();
assert_eq!(draw_line(-10.0, 10.0, 110.0, 70.0, false, 0.0, LineCap::Butt), expected);
}
#[test]
fn clip_line_00_v2() {
let mut pixmap = Pixmap::new(512, 512).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = false;
let mut stroke = Stroke::default();
stroke.width = 0.0;
let mut builder = PathBuilder::default();
builder.move_to(369.26462, 577.8069);
builder.line_to(488.0846, 471.04388);
let path = builder.finish().unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/hairline/clip-line-00-v2.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn clip_hline_top_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-hline-top-aa.png").unwrap();
assert_eq!(draw_line(-1.0, 0.0, 101.0, 0.0, true, 1.0, LineCap::Butt), expected);
}
#[test]
fn clip_hline_bottom_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-hline-bottom-aa.png").unwrap();
assert_eq!(draw_line(-1.0, 100.0, 101.0, 100.0, true, 1.0, LineCap::Butt), expected);
}
#[test]
fn clip_vline_left_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-vline-left-aa.png").unwrap();
assert_eq!(draw_line(0.0, -1.0, 0.0, 101.0, true, 1.0, LineCap::Butt), expected);
}
#[test]
fn clip_vline_right_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-vline-right-aa.png").unwrap();
assert_eq!(draw_line(100.0, -1.0, 100.0, 101.0, true, 1.0, LineCap::Butt), expected);
}
fn draw_quad(anti_alias: bool, width: f32, line_cap: LineCap) -> Pixmap {
let mut pixmap = Pixmap::new(200, 100).unwrap();
let mut pb = PathBuilder::new();
pb.move_to(25.0, 80.0);
pb.quad_to(155.0, 75.0, 175.0, 20.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = anti_alias;
let mut stroke = Stroke::default();
stroke.width = width;
stroke.line_cap = line_cap;
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
pixmap
}
#[test]
fn quad_width_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/quad-width-05-aa.png").unwrap();
assert_eq!(draw_quad(true, 0.5, LineCap::Butt), expected);
}
#[test]
fn quad_width_05_aa_round() {
let expected = Pixmap::load_png("tests/images/hairline/quad-width-05-aa-round.png").unwrap();
assert_eq!(draw_quad(true, 0.5, LineCap::Round), expected);
}
#[test]
fn quad_width_00() {
let expected = Pixmap::load_png("tests/images/hairline/quad-width-00.png").unwrap();
assert_eq!(draw_quad(false, 0.0, LineCap::Butt), expected);
}
fn draw_cubic(points: &[f32; 8], anti_alias: bool, width: f32, line_cap: LineCap) -> Pixmap {
let mut pixmap = Pixmap::new(200, 100).unwrap();
let mut pb = PathBuilder::new();
pb.move_to(points[0], points[1]);
pb.cubic_to(points[2], points[3], points[4], points[5], points[6], points[7]);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = anti_alias;
let mut stroke = Stroke::default();
stroke.width = width;
stroke.line_cap = line_cap;
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
pixmap
}
#[test]
fn cubic_width_10_aa() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-10-aa.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], true, 1.0, LineCap::Butt), expected);
}
#[test]
fn cubic_width_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-05-aa.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], true, 0.5, LineCap::Butt), expected);
}
#[test]
fn cubic_width_00_aa() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-00-aa.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], true, 0.0, LineCap::Butt), expected);
}
#[test]
fn cubic_width_00() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-00.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], false, 0.0, LineCap::Butt), expected);
}
#[test]
fn cubic_width_05_aa_round() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-05-aa-round.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], true, 0.5, LineCap::Round), expected);
}
#[test]
fn cubic_width_00_round() {
let expected = Pixmap::load_png("tests/images/hairline/cubic-width-00-round.png").unwrap();
assert_eq!(draw_cubic(&[25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], false, 0.0, LineCap::Round), expected);
}
#[test]
fn chop_cubic_01() {
let expected = Pixmap::load_png("tests/images/hairline/chop-cubic-01.png").unwrap();
// This curve will invoke `path_geometry::chop_cubic_at_max_curvature` branch of `hair_cubic`.
assert_eq!(draw_cubic(&[57.0, 13.0, 17.0, 15.0, 55.0, 97.0, 89.0, 62.0], true, 0.5, LineCap::Butt), expected);
}
#[test]
fn clip_cubic_05_aa() {
let expected = Pixmap::load_png("tests/images/hairline/clip-cubic-05-aa.png").unwrap();
assert_eq!(draw_cubic(&[-25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], true, 0.5, LineCap::Butt), expected);
}
#[test]
fn clip_cubic_00() {
let expected = Pixmap::load_png("tests/images/hairline/clip-cubic-00.png").unwrap();
assert_eq!(draw_cubic(&[-25.0, 80.0, 55.0, 25.0, 155.0, 75.0, 175.0, 20.0], false, 0.0, LineCap::Butt), expected);
}
#[test]
fn clipped_circle_aa() {
let mut pixmap = Pixmap::new(100, 100).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.width = 0.5;
let path = PathBuilder::from_circle(50.0, 50.0, 55.0).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/hairline/clipped-circle-aa.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,11 @@
#[rustfmt::skip] mod clip;
#[rustfmt::skip] mod dash;
#[rustfmt::skip] mod fill;
#[rustfmt::skip] mod gradients;
#[rustfmt::skip] mod hairline;
#[rustfmt::skip] mod path;
#[rustfmt::skip] mod pattern;
#[rustfmt::skip] mod pixmap;
#[rustfmt::skip] mod png;
#[rustfmt::skip] mod skia_dash;
#[rustfmt::skip] mod stroke;

View file

@ -0,0 +1,266 @@
use tiny_skia::*;
#[test]
fn empty() {
let pb = PathBuilder::new();
assert!(pb.finish().is_none());
}
#[test]
fn line() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 20.0, 30.0, 40.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 20.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
]);
assert_eq!(format!("{:?}", path),
"Path { segments: \"M 10 20 L 30 40\", \
bounds: Rect { left: 10.0, top: 20.0, right: 30.0, bottom: 40.0 } }");
}
#[test]
fn no_move_before_line() {
let mut pb = PathBuilder::new();
pb.line_to(30.0, 40.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(0.0, 0.0, 30.0, 40.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(0.0, 0.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
]);
}
#[test]
fn no_move_before_quad() {
let mut pb = PathBuilder::new();
pb.quad_to(40.0, 30.0, 60.0, 75.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(0.0, 0.0, 60.0, 75.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(0.0, 0.0)),
PathSegment::QuadTo(Point::from_xy(40.0, 30.0), Point::from_xy(60.0, 75.0)),
]);
}
#[test]
fn no_move_before_cubic() {
let mut pb = PathBuilder::new();
pb.cubic_to(40.0, 30.0, 60.0, 75.0, 33.0, 66.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(0.0, 0.0, 60.0, 75.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(0.0, 0.0)),
PathSegment::CubicTo(Point::from_xy(40.0, 30.0), Point::from_xy(60.0, 75.0), Point::from_xy(33.0, 66.0)),
]);
}
#[test]
fn no_move_before_close() {
let mut pb = PathBuilder::new();
pb.close();
assert!(pb.finish().is_none());
}
#[test]
fn double_close() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(20.0, 10.0);
pb.line_to(20.0, 20.0);
pb.close();
pb.close();
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 10.0, 20.0, 20.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 10.0)),
PathSegment::LineTo(Point::from_xy(20.0, 10.0)),
PathSegment::LineTo(Point::from_xy(20.0, 20.0)),
PathSegment::Close,
]);
}
#[test]
fn double_move_to_1() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.move_to(30.0, 40.0);
assert!(pb.finish().is_none());
}
#[test]
fn double_move_to_2() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.move_to(20.0, 10.0);
pb.line_to(30.0, 40.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(20.0, 10.0, 30.0, 40.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(20.0, 10.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
]);
}
#[test]
fn two_contours() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
pb.move_to(100.0, 200.0);
pb.line_to(300.0, 400.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 20.0, 300.0, 400.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 20.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
PathSegment::MoveTo(Point::from_xy(100.0, 200.0)),
PathSegment::LineTo(Point::from_xy(300.0, 400.0)),
]);
}
#[test]
fn two_closed_contours() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
pb.close();
pb.move_to(100.0, 200.0);
pb.line_to(300.0, 400.0);
pb.close();
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 20.0, 300.0, 400.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 20.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
PathSegment::Close,
PathSegment::MoveTo(Point::from_xy(100.0, 200.0)),
PathSegment::LineTo(Point::from_xy(300.0, 400.0)),
PathSegment::Close,
]);
}
#[test]
fn line_after_close() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
pb.close();
pb.line_to(20.0, 20.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 20.0, 30.0, 40.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 20.0)),
PathSegment::LineTo(Point::from_xy(30.0, 40.0)),
PathSegment::Close,
PathSegment::MoveTo(Point::from_xy(10.0, 20.0)),
PathSegment::LineTo(Point::from_xy(20.0, 20.0)),
]);
}
#[test]
fn hor_line() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(20.0, 10.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 10.0, 20.0, 10.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 10.0)),
PathSegment::LineTo(Point::from_xy(20.0, 10.0)),
]);
}
#[test]
fn ver_line() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 10.0);
pb.line_to(10.0, 20.0);
let path = pb.finish().unwrap();
assert_eq!(path.bounds(), Rect::from_ltrb(10.0, 10.0, 10.0, 20.0).unwrap());
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(10.0, 10.0)),
PathSegment::LineTo(Point::from_xy(10.0, 20.0)),
]);
}
#[test]
fn translate() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
let mut path = pb.finish().unwrap();
path = path.transform(Transform::from_translate(10.0, 20.0)).unwrap();
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(20.0, 40.0)),
PathSegment::LineTo(Point::from_xy(40.0, 60.0)),
]);
}
#[test]
fn scale() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
let mut path = pb.finish().unwrap();
path = path.transform(Transform::from_scale(2.0, 0.5)).unwrap();
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(20.0, 10.0)),
PathSegment::LineTo(Point::from_xy(60.0, 20.0)),
]);
}
#[test]
fn transform() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
let mut path = pb.finish().unwrap();
path = path.transform(Transform::from_row(2.0, 0.7, -0.3, 0.5, 10.0, 20.0)).unwrap();
assert_eq!(path.segments().collect::<Vec<_>>(), &[
PathSegment::MoveTo(Point::from_xy(24.0, 37.0)),
PathSegment::LineTo(Point::from_xy(58.0, 61.0)),
]);
}
#[test]
fn invalid_transform() {
let mut pb = PathBuilder::new();
pb.move_to(10.0, 20.0);
pb.line_to(30.0, 40.0);
let path = pb.finish().unwrap();
// will produce infinity
assert_eq!(path.transform(Transform::from_scale(std::f32::MAX, std::f32::MAX)), None);
}
#[test]
fn circle() {
assert!(PathBuilder::from_circle(250.0, 250.0, 300.0).is_some()); // Must not panic.
}
#[test]
fn large_circle() {
assert!(PathBuilder::from_circle(250.0, 250.0, 2000.0).is_some()); // Must not panic.
}

View file

@ -0,0 +1,243 @@
use tiny_skia::*;
fn crate_triangle() -> Pixmap {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(0.0, 20.0);
pb.line_to(20.0, 20.0);
pb.line_to(10.0, 0.0);
pb.close();
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(20, 20).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
pixmap
}
#[test]
fn pad_nearest() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Pad,
FilterQuality::Nearest,
1.0,
Transform::identity(),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/pad-nearest.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn repeat_nearest() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Nearest,
1.0,
Transform::identity(),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/repeat-nearest.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn reflect_nearest() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Reflect,
FilterQuality::Nearest,
1.0,
Transform::identity(),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/reflect-nearest.png").unwrap();
assert_eq!(pixmap, expected);
}
// We have to test tile mode for bilinear/bicubic separately,
// because they're using a different algorithm from nearest.
#[test]
fn pad_bicubic() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Pad,
FilterQuality::Bicubic,
1.0,
// Transform must be set, otherwise we will fallback to Nearest.
Transform::from_row(1.1, 0.3, 0.0, 1.4, 0.0, 0.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/pad-bicubic.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn repeat_bicubic() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Bicubic,
1.0,
// Transform must be set, otherwise we will fallback to Nearest.
Transform::from_row(1.1, 0.3, 0.0, 1.4, 0.0, 0.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/repeat-bicubic.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn reflect_bicubic() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Reflect,
FilterQuality::Bicubic,
1.0,
// Transform must be set, otherwise we will fallback to Nearest.
Transform::from_row(1.1, 0.3, 0.0, 1.4, 0.0, 0.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/reflect-bicubic.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn filter_nearest_no_ts() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Nearest,
1.0,
Transform::identity(),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/filter-nearest-no-ts.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn filter_nearest() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Nearest,
1.0,
Transform::from_row(1.5, 0.0, -0.4, -0.8, 5.0, 1.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/filter-nearest.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn filter_bilinear() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Bilinear,
1.0,
Transform::from_row(1.5, 0.0, -0.4, -0.8, 5.0, 1.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/filter-bilinear.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn filter_bicubic() {
let triangle = crate_triangle();
let mut paint = Paint::default();
paint.shader = Pattern::new(
triangle.as_ref(),
SpreadMode::Repeat,
FilterQuality::Bicubic,
1.0,
Transform::from_row(1.5, 0.0, -0.4, -0.8, 5.0, 1.0),
);
let path = PathBuilder::from_rect(Rect::from_ltrb(10.0, 10.0, 190.0, 190.0).unwrap());
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/pattern/filter-bicubic.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,171 @@
use tiny_skia::*;
#[test]
fn clone_rect_1() {
let mut pixmap = Pixmap::new(200, 200).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200); paint.anti_alias = true;
pixmap.fill_path(
&PathBuilder::from_circle(100.0, 100.0, 80.0).unwrap(),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
let part = pixmap.as_ref().clone_rect(IntRect::from_xywh(10, 15, 80, 90).unwrap()).unwrap();
let expected = Pixmap::load_png("tests/images/pixmap/clone-rect-1.png").unwrap();
assert_eq!(part, expected);
}
#[test]
fn clone_rect_2() {
let mut pixmap = Pixmap::new(200, 200).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
pixmap.fill_path(
&PathBuilder::from_circle(100.0, 100.0, 80.0).unwrap(),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
let part = pixmap.as_ref().clone_rect(IntRect::from_xywh(130, 120, 80, 90).unwrap()).unwrap();
let expected = Pixmap::load_png("tests/images/pixmap/clone-rect-2.png").unwrap();
assert_eq!(part, expected);
}
#[test]
fn clone_rect_out_of_bound() {
let mut pixmap = Pixmap::new(200, 200).unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
pixmap.fill_path(
&PathBuilder::from_circle(100.0, 100.0, 80.0).unwrap(),
&paint,
FillRule::Winding,
Transform::identity(),
None,
);
assert!(pixmap.as_ref().clone_rect(IntRect::from_xywh(250, 15, 80, 90).unwrap()).is_none());
assert!(pixmap.as_ref().clone_rect(IntRect::from_xywh(10, 250, 80, 90).unwrap()).is_none());
assert!(pixmap.as_ref().clone_rect(IntRect::from_xywh(10, -250, 80, 90).unwrap()).is_none());
}
#[test]
fn fill() {
let c = Color::from_rgba8(50, 100, 150, 200);
let mut pixmap = Pixmap::new(10, 10).unwrap();
pixmap.fill(c);
assert_eq!(pixmap.pixel(1, 1).unwrap(), c.premultiply().to_color_u8());
}
#[test]
fn draw_pixmap() {
// Tests that painting algorithm will switch `Bicubic`/`Bilinear` to `Nearest`.
// Otherwise we will get a blurry image.
// A pixmap with the bottom half filled with solid color.
let sub_pixmap = {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
let rect = Rect::from_xywh(0.0, 50.0, 100.0, 50.0).unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_rect(rect, &paint, Transform::identity(), None);
pixmap
};
let mut paint = PixmapPaint::default();
paint.quality = FilterQuality::Bicubic;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.draw_pixmap(20, 20, sub_pixmap.as_ref(), &paint, Transform::identity(), None);
let expected = Pixmap::load_png("tests/images/canvas/draw-pixmap.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn draw_pixmap_ts() {
let triangle = {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(0.0, 100.0);
pb.line_to(100.0, 100.0);
pb.line_to(50.0, 0.0);
pb.close();
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
pixmap
};
let mut paint = PixmapPaint::default();
paint.quality = FilterQuality::Bicubic;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.draw_pixmap(
5, 10,
triangle.as_ref(),
&paint,
Transform::from_row(1.2, 0.5, 0.5, 1.2, 0.0, 0.0),
None,
);
let expected = Pixmap::load_png("tests/images/canvas/draw-pixmap-ts.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn draw_pixmap_opacity() {
let triangle = {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(0.0, 100.0);
pb.line_to(100.0, 100.0);
pb.line_to(50.0, 0.0);
pb.close();
let path = pb.finish().unwrap();
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.fill_path(&path, &paint, FillRule::Winding, Transform::identity(), None);
pixmap
};
let mut paint = PixmapPaint::default();
paint.quality = FilterQuality::Bicubic;
paint.opacity = 0.5;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.draw_pixmap(
5, 10,
triangle.as_ref(),
&paint,
Transform::from_row(1.2, 0.5, 0.5, 1.2, 0.0, 0.0),
None,
);
let expected = Pixmap::load_png("tests/images/canvas/draw-pixmap-opacity.png").unwrap();
assert_eq!(pixmap, expected);
}

View file

@ -0,0 +1,32 @@
use tiny_skia::*;
#[test]
fn decode_grayscale() {
let pixmap = Pixmap::load_png("tests/images/pngs/grayscale.png").unwrap();
assert_eq!(pixmap.pixel(10, 10).unwrap(), ColorU8::from_rgba(255, 255, 255, 255).premultiply());
assert_eq!(pixmap.pixel(50, 50).unwrap(), ColorU8::from_rgba(0, 0, 0, 255).premultiply());
}
#[test]
fn decode_grayscale_alpha() {
let pixmap = Pixmap::load_png("tests/images/pngs/grayscale-alpha.png").unwrap();
assert_eq!(pixmap.pixel(10, 10).unwrap(), ColorU8::from_rgba(0, 0, 0, 0).premultiply());
assert_eq!(pixmap.pixel(50, 50).unwrap(), ColorU8::from_rgba(0, 0, 0, 255).premultiply());
}
#[test]
fn decode_rgb() {
let pixmap = Pixmap::load_png("tests/images/pngs/rgb.png").unwrap();
assert_eq!(pixmap.pixel(10, 10).unwrap(), ColorU8::from_rgba(255, 255, 255, 255).premultiply());
assert_eq!(pixmap.pixel(50, 50).unwrap(), ColorU8::from_rgba(36, 191, 49, 255).premultiply());
}
#[test]
fn decode_rgba() {
let pixmap = Pixmap::load_png("tests/images/pngs/rgba.png").unwrap();
assert_eq!(pixmap.pixel(10, 10).unwrap(), ColorU8::from_rgba(0, 0, 0, 0).premultiply());
assert_eq!(pixmap.pixel(25, 25).unwrap(), ColorU8::from_rgba(161, 227, 165, 108).premultiply());
assert_eq!(pixmap.pixel(50, 50).unwrap(), ColorU8::from_rgba(33, 190, 47, 252).premultiply());
}
// TODO: test encoding, somehow

View file

@ -0,0 +1,45 @@
use tiny_skia::*;
#[test]
fn crbug_140642() {
// We used to see this construct, and due to rounding as we accumulated
// our length, the loop where we apply the phase would run off the end of
// the array, since it relied on just -= each interval value, which did not
// behave as "expected". Now the code explicitly checks for walking off the
// end of that array.
//
// A different (better) fix might be to rewrite dashing to do all of its
// length/phase/measure math using double, but this may need to be
// coordinated with SkPathMeasure, to be consistent between the two.
assert!(StrokeDash::new(vec![27734.0, 35660.0, 2157846850.0, 247.0], -248.135982067).is_some());
}
#[test]
fn crbug_124652() {
// http://code.google.com/p/chromium/issues/detail?id=124652
// This particular test/bug only applies to the float case, where
// large values can "swamp" small ones.
assert!(StrokeDash::new(vec![837099584.0, 33450.0], -10.0).is_some());
}
// Extremely large path_length/dash_length ratios may cause infinite looping
// due to single precision rounding.
#[test]
fn infinite_dash() {
let mut pb = PathBuilder::new();
pb.move_to(0.0, 5.0);
pb.line_to(5000000.0, 5.0);
let path = pb.finish().unwrap();
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut stroke = Stroke::default();
stroke.dash = StrokeDash::new(vec![0.2, 0.2], 0.0);
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None); // Doesn't draw anything.
assert!(true);
}

View file

@ -0,0 +1,134 @@
use tiny_skia::*;
#[test]
fn round_caps_and_large_scale() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let path = {
let mut pb = PathBuilder::new();
pb.move_to(60.0 / 16.0, 100.0 / 16.0);
pb.line_to(140.0 / 16.0, 100.0 / 16.0);
pb.finish().unwrap()
};
let mut stroke = Stroke::default();
stroke.width = 6.0;
stroke.line_cap = LineCap::Round;
let transform = Transform::from_scale(16.0, 16.0);
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, transform, None);
let expected = Pixmap::load_png("tests/images/stroke/round-caps-and-large-scale.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn circle() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let path = PathBuilder::from_circle(100.0, 100.0, 50.0).unwrap();
let mut stroke = Stroke::default();
stroke.width = 2.0;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::default(), None);
let expected = Pixmap::load_png("tests/images/stroke/circle.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn zero_len_subpath_butt_cap() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(50.0, 50.0);
pb.line_to(50.0, 50.0);
let path = pb.finish().unwrap();
let mut stroke = Stroke::default();
stroke.width = 20.0;
stroke.line_cap = LineCap::Butt;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::default(), None);
let expected = Pixmap::load_png("tests/images/stroke/zero-len-subpath-butt-cap.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn zero_len_subpath_round_cap() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(50.0, 50.0);
pb.line_to(50.0, 50.0);
let path = pb.finish().unwrap();
let mut stroke = Stroke::default();
stroke.width = 20.0;
stroke.line_cap = LineCap::Round;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::default(), None);
let expected = Pixmap::load_png("tests/images/stroke/zero-len-subpath-round-cap.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn zero_len_subpath_square_cap() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(50.0, 50.0);
pb.line_to(50.0, 50.0);
let path = pb.finish().unwrap();
let mut stroke = Stroke::default();
stroke.width = 20.0;
stroke.line_cap = LineCap::Square;
let mut pixmap = Pixmap::new(100, 100).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::default(), None);
let expected = Pixmap::load_png("tests/images/stroke/zero-len-subpath-square-cap.png").unwrap();
assert_eq!(pixmap, expected);
}
#[test]
fn round_cap_join() {
let mut paint = Paint::default();
paint.set_color_rgba8(50, 127, 150, 200);
paint.anti_alias = true;
let mut pb = PathBuilder::new();
pb.move_to(170.0, 30.0);
pb.line_to(30.553378, 99.048418);
pb.cubic_to(30.563658, 99.066835, 30.546308, 99.280724, 30.557592, 99.305282);
let path = pb.finish().unwrap();
let mut stroke = Stroke::default();
stroke.width = 30.0;
stroke.line_cap = LineCap::Round;
stroke.line_join = LineJoin::Round;
let mut pixmap = Pixmap::new(200, 200).unwrap();
pixmap.stroke_path(&path, &paint, &stroke, Transform::default(), None);
let expected = Pixmap::load_png("tests/images/stroke/round-cap-join.png").unwrap();
assert_eq!(pixmap, expected);
}