mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
Merge pull request #271 from armansito/pr-conflation-examples
Introduce test scenes that demonstrate conflation artifacts
This commit is contained in:
commit
2690c3602d
|
@ -30,6 +30,8 @@ pub fn test_scenes() -> SceneSet {
|
||||||
scene!(animated_text: animated),
|
scene!(animated_text: animated),
|
||||||
scene!(brush_transform: animated),
|
scene!(brush_transform: animated),
|
||||||
scene!(blend_grid),
|
scene!(blend_grid),
|
||||||
|
scene!(conflation_artifacts),
|
||||||
|
scene!(labyrinth),
|
||||||
];
|
];
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
scenes.push(ExampleScene {
|
scenes.push(ExampleScene {
|
||||||
|
@ -403,6 +405,172 @@ fn blend_square(blend: BlendMode) -> SceneFragment {
|
||||||
fragment
|
fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn conflation_artifacts(sb: &mut SceneBuilder, _: &mut SceneParams) {
|
||||||
|
use PathEl::*;
|
||||||
|
const N: f64 = 50.0;
|
||||||
|
const S: f64 = 4.0;
|
||||||
|
|
||||||
|
let scale = Affine::scale(S);
|
||||||
|
let x = N + 0.5; // Fractional pixel offset reveals the problem on axis-aligned edges.
|
||||||
|
let mut y = N;
|
||||||
|
|
||||||
|
let bg_color = Color::rgb8(255, 194, 19);
|
||||||
|
let fg_color = Color::rgb8(12, 165, 255);
|
||||||
|
|
||||||
|
// Two adjacent triangles touching at diagonal edge with opposing winding numbers
|
||||||
|
sb.fill(
|
||||||
|
Fill::NonZero,
|
||||||
|
Affine::translate((x, y)) * scale,
|
||||||
|
fg_color,
|
||||||
|
None,
|
||||||
|
&[
|
||||||
|
// triangle 1
|
||||||
|
MoveTo((0.0, 0.0).into()),
|
||||||
|
LineTo((N, N).into()),
|
||||||
|
LineTo((0.0, N).into()),
|
||||||
|
LineTo((0.0, 0.0).into()),
|
||||||
|
// triangle 2
|
||||||
|
MoveTo((0.0, 0.0).into()),
|
||||||
|
LineTo((N, N).into()),
|
||||||
|
LineTo((N, 0.0).into()),
|
||||||
|
LineTo((0.0, 0.0).into()),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Adjacent rects, opposite winding
|
||||||
|
y += S * N + 10.0;
|
||||||
|
sb.fill(
|
||||||
|
Fill::EvenOdd,
|
||||||
|
Affine::translate((x, y)) * scale,
|
||||||
|
bg_color,
|
||||||
|
None,
|
||||||
|
&Rect::new(0.0, 0.0, N, N),
|
||||||
|
);
|
||||||
|
sb.fill(
|
||||||
|
Fill::EvenOdd,
|
||||||
|
Affine::translate((x, y)) * scale,
|
||||||
|
fg_color,
|
||||||
|
None,
|
||||||
|
&[
|
||||||
|
// left rect
|
||||||
|
MoveTo((0.0, 0.0).into()),
|
||||||
|
LineTo((0.0, N).into()),
|
||||||
|
LineTo((N * 0.5, N).into()),
|
||||||
|
LineTo((N * 0.5, 0.0).into()),
|
||||||
|
// right rect
|
||||||
|
MoveTo((N * 0.5, 0.0).into()),
|
||||||
|
LineTo((N, 0.0).into()),
|
||||||
|
LineTo((N, N).into()),
|
||||||
|
LineTo((N * 0.5, N).into()),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Adjacent rects, same winding
|
||||||
|
y += S * N + 10.0;
|
||||||
|
sb.fill(
|
||||||
|
Fill::EvenOdd,
|
||||||
|
Affine::translate((x, y)) * scale,
|
||||||
|
bg_color,
|
||||||
|
None,
|
||||||
|
&Rect::new(0.0, 0.0, N, N),
|
||||||
|
);
|
||||||
|
sb.fill(
|
||||||
|
Fill::EvenOdd,
|
||||||
|
Affine::translate((x, y)) * scale,
|
||||||
|
fg_color,
|
||||||
|
None,
|
||||||
|
&[
|
||||||
|
// left rect
|
||||||
|
MoveTo((0.0, 0.0).into()),
|
||||||
|
LineTo((0.0, N).into()),
|
||||||
|
LineTo((N * 0.5, N).into()),
|
||||||
|
LineTo((N * 0.5, 0.0).into()),
|
||||||
|
// right rect
|
||||||
|
MoveTo((N * 0.5, 0.0).into()),
|
||||||
|
LineTo((N * 0.5, N).into()),
|
||||||
|
LineTo((N, N).into()),
|
||||||
|
LineTo((N, 0.0).into()),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn labyrinth(sb: &mut SceneBuilder, _: &mut SceneParams) {
|
||||||
|
use PathEl::*;
|
||||||
|
|
||||||
|
let rows: &[[u8; 12]] = &[
|
||||||
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1],
|
||||||
|
[0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1],
|
||||||
|
[1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||||
|
[0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||||
|
[1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0],
|
||||||
|
[0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0],
|
||||||
|
[1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
|
||||||
|
[0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
|
||||||
|
[0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
|
||||||
|
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
];
|
||||||
|
let cols: &[[u8; 10]] = &[
|
||||||
|
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
|
||||||
|
[0, 0, 1, 0, 0, 0, 1, 1, 1, 0],
|
||||||
|
[0, 1, 1, 0, 1, 1, 1, 0, 0, 1],
|
||||||
|
[1, 1, 0, 0, 0, 0, 1, 0, 1, 0],
|
||||||
|
[0, 0, 1, 0, 1, 0, 0, 0, 0, 1],
|
||||||
|
[0, 0, 1, 1, 1, 0, 0, 0, 1, 0],
|
||||||
|
[0, 1, 0, 1, 1, 1, 0, 0, 0, 0],
|
||||||
|
[1, 1, 1, 0, 1, 1, 1, 0, 1, 0],
|
||||||
|
[1, 1, 0, 1, 1, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
|
||||||
|
[0, 0, 1, 1, 0, 0, 0, 0, 1, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
|
||||||
|
[1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
|
||||||
|
];
|
||||||
|
let mut path = BezPath::new();
|
||||||
|
for (y, row) in rows.iter().enumerate() {
|
||||||
|
for (x, flag) in row.iter().enumerate() {
|
||||||
|
let x = x as f64;
|
||||||
|
let y = y as f64;
|
||||||
|
if *flag == 1 {
|
||||||
|
path.push(MoveTo((x - 0.1, y + 0.1).into()));
|
||||||
|
path.push(LineTo((x + 1.1, y + 0.1).into()));
|
||||||
|
path.push(LineTo((x + 1.1, y - 0.1).into()));
|
||||||
|
path.push(LineTo((x - 0.1, y - 0.1).into()));
|
||||||
|
|
||||||
|
// The above is equivalent to the following stroke with width 0.2 and square
|
||||||
|
// caps.
|
||||||
|
//path.push(MoveTo((x, y).into()));
|
||||||
|
//path.push(LineTo((x + 1.0, y).into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (x, col) in cols.iter().enumerate() {
|
||||||
|
for (y, flag) in col.iter().enumerate() {
|
||||||
|
let x = x as f64;
|
||||||
|
let y = y as f64;
|
||||||
|
if *flag == 1 {
|
||||||
|
path.push(MoveTo((x - 0.1, y - 0.1).into()));
|
||||||
|
path.push(LineTo((x - 0.1, y + 1.1).into()));
|
||||||
|
path.push(LineTo((x + 0.1, y + 1.1).into()));
|
||||||
|
path.push(LineTo((x + 0.1, y - 0.1).into()));
|
||||||
|
// The above is equivalent to the following stroke with width 0.2 and square
|
||||||
|
// caps.
|
||||||
|
//path.push(MoveTo((x, y).into()));
|
||||||
|
//path.push(LineTo((x, y + 1.0).into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note the artifacts are clearly visible at a fractional pixel offset/translation. They
|
||||||
|
// disappear if the translation amount below is a whole number.
|
||||||
|
sb.fill(
|
||||||
|
Fill::NonZero,
|
||||||
|
Affine::translate((20.5, 20.5)) * Affine::scale(80.0),
|
||||||
|
Color::rgba8(0x70, 0x80, 0x80, 0xff),
|
||||||
|
None,
|
||||||
|
&path,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn around_center(xform: Affine, center: Point) -> Affine {
|
fn around_center(xform: Affine, center: Point) -> Affine {
|
||||||
Affine::translate(center.to_vec2()) * xform * Affine::translate(-center.to_vec2())
|
Affine::translate(center.to_vec2()) * xform * Affine::translate(-center.to_vec2())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue