-
Notifications
You must be signed in to change notification settings - Fork 204
Description
Mix::Clip (or if we get #1192, add_clip_layer) is defined as:
Clipis the same asNormal, but the latter always creates an isolated blend group and the former can optimize that out.
To validate this, I created the following test scene:
Code for example (long)
pub(super) fn clipped_blend(scene: &mut Scene, params: &mut SceneParams<'_>) {
params.resolution = Some(Vec2::new(1000., 1200.));
let transform = Affine::translate((10., 100.));
params.text.add_run(
&mut *scene,
None,
32.,
Color::WHITE,
transform.then_translate((10., -30.).into()),
None,
&Style::Fill(Fill::EvenOdd),
"No Clip",
);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::BLUE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
scene.push_layer(
Mix::Multiply,
1.0,
transform,
&Triangle::from_coords((200., 0.), (0., 400.), (400., 400.)),
);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::AQUAMARINE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
scene.pop_layer();
let transform = Affine::translate((0., 600.));
params.text.add_run(
&mut *scene,
None,
32.,
Color::WHITE,
transform.then_translate((10., -30.).into()),
None,
&Style::Fill(Fill::EvenOdd),
"Mix::Normal",
);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::BLUE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
let layer_shape = Triangle::from_coords((200., 0.), (0., 400.), (400., 400.));
scene.push_layer(Mix::Normal, 1.0, transform, &layer_shape);
scene.push_layer(Mix::Multiply, 1.0, transform, &layer_shape);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::AQUAMARINE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
scene.pop_layer();
scene.pop_layer();
let transform = Affine::translate((500., 600.));
params.text.add_run(
&mut *scene,
None,
32.,
Color::WHITE,
transform.then_translate((10., -30.).into()),
None,
&Style::Fill(Fill::EvenOdd),
"Mix::Clip",
);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::BLUE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
let layer_shape = Triangle::from_coords((200., 0.), (0., 400.), (400., 400.));
scene.push_layer(Mix::Clip, 1.0, transform, &layer_shape);
scene.push_layer(Mix::Multiply, 1.0, transform, &layer_shape);
scene.fill(
Fill::EvenOdd,
transform,
palette::css::AQUAMARINE,
None,
&Rect::from_origin_size((0., 0.), (400., 400.)),
);
scene.pop_layer();
scene.pop_layer();
}This shows Mix::Clip followed by a Multiply blend, and both of the two reasonable rendering results from the blends; either the same as there not being a clip, or it being equivalent to Mix::Normal.
This however renders as:
This is discussed in #vello > Mix::Clip optimisation: Interaction with layers. Essentially, the fixes look like making the Clip act the same as No Clip, which likely requires us to implement non-isolated blending. For clip layers in particular, that's pretty easy, although the general case of non-isolated blending is pretty gnarly because the web compositing spec is pretty lax about properly specifying the semantics.