prevent encoding empty paths for layers too

This commit is contained in:
Chad Brokaw 2022-11-22 15:17:50 -05:00
parent f19dbdb1b5
commit c1e91cb233
3 changed files with 22 additions and 34 deletions

View file

@ -226,7 +226,7 @@ pub fn render_blend_grid(sb: &mut SceneBuilder) {
fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affine) { fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affine) {
// Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode // Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
let rect = Rect::from_origin_size(Point::new(0., 0.), (200., 200.)); let rect = Rect::from_origin_size(Point::new(0., 0.), (200., 200.));
let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::BLACK, Color::WHITE]); let linear = LinearGradient::new((0.0, 0.0), (200.0, 0.0)).stops([Color::BLACK, Color::WHITE]);
sb.fill(Fill::NonZero, transform, &linear.into(), None, &rect); sb.fill(Fill::NonZero, transform, &linear.into(), None, &rect);
const GRADIENTS: &[(f64, f64, Color)] = &[ const GRADIENTS: &[(f64, f64, Color)] = &[
(150., 0., Color::rgb8(255, 240, 64)), (150., 0., Color::rgb8(255, 240, 64)),
@ -236,7 +236,7 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
for (x, y, c) in GRADIENTS { for (x, y, c) in GRADIENTS {
let mut color2 = c.clone(); let mut color2 = c.clone();
color2.a = 0; color2.a = 0;
let radial = RadialGradient::new((*x, *y), 100.0).stops([c.clone(), color2]); let radial = RadialGradient::new((*x, *y), 100.0).stops([*c, color2]);
sb.fill(Fill::NonZero, transform, &radial.into(), None, &rect); sb.fill(Fill::NonZero, transform, &radial.into(), None, &rect);
} }
const COLORS: &[Color] = &[ const COLORS: &[Color] = &[
@ -246,17 +246,7 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
]; ];
sb.push_layer(Mix::Normal.into(), transform, &rect); sb.push_layer(Mix::Normal.into(), transform, &rect);
for (i, c) in COLORS.iter().enumerate() { for (i, c) in COLORS.iter().enumerate() {
// let stops = &[ let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, *c]);
// GradientStop {
// color: Color::rgb8(255, 255, 255),
// offset: 0.0,
// },
// GradientStop {
// color: c.clone(),
// offset: 1.0,
// },
// ][..];
let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, c.clone()]);
sb.push_layer(blend, transform, &rect); sb.push_layer(blend, transform, &rect);
// squash the ellipse // squash the ellipse
let a = transform let a = transform

View file

@ -24,7 +24,7 @@ use smallvec::SmallVec;
/// Builder for constructing a scene or scene fragment. /// Builder for constructing a scene or scene fragment.
pub struct SceneBuilder<'a> { pub struct SceneBuilder<'a> {
scene: &'a mut SceneData, scene: &'a mut SceneData,
layers: SmallVec<[BlendMode; 8]>, layers: SmallVec<[(BlendMode, bool); 8]>,
} }
impl<'a> SceneBuilder<'a> { impl<'a> SceneBuilder<'a> {
@ -54,15 +54,23 @@ impl<'a> SceneBuilder<'a> {
pub fn push_layer(&mut self, blend: BlendMode, transform: Affine, shape: &impl Shape) { pub fn push_layer(&mut self, blend: BlendMode, transform: Affine, shape: &impl Shape) {
self.maybe_encode_transform(transform); self.maybe_encode_transform(transform);
self.linewidth(-1.0); self.linewidth(-1.0);
self.encode_path(shape, true); if self.encode_path(shape, true) {
self.begin_clip(blend); self.begin_clip(blend);
self.layers.push(blend); self.layers.push((blend, true));
} else {
// When the layer has an empty path, record an entry to prevent
// the stack from becoming unbalanced. This is handled in
// pop_layer.
self.layers.push((blend, false));
}
} }
/// Pops the current layer. /// Pops the current layer.
pub fn pop_layer(&mut self) { pub fn pop_layer(&mut self) {
if let Some(layer) = self.layers.pop() { if let Some((blend, active)) = self.layers.pop() {
self.end_clip(layer); if active {
self.end_clip(blend);
}
} }
} }
@ -117,8 +125,8 @@ impl<'a> SceneBuilder<'a> {
/// Completes construction and finalizes the underlying scene. /// Completes construction and finalizes the underlying scene.
pub fn finish(mut self) { pub fn finish(mut self) {
while let Some(layer) = self.layers.pop() { while !self.layers.is_empty() {
self.end_clip(layer); self.pop_layer();
} }
} }
} }

View file

@ -133,7 +133,7 @@ pub fn render_blend_grid(sb: &mut SceneBuilder) {
fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affine) { fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affine) {
// Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode // Inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
let rect = Rect::from_origin_size(Point::new(0., 0.), (200., 200.)); let rect = Rect::from_origin_size(Point::new(0., 0.), (200., 200.));
let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::BLACK, Color::WHITE]); let linear = LinearGradient::new((0.0, 0.0), (200.0, 0.0)).stops([Color::BLACK, Color::WHITE]);
sb.fill(Fill::NonZero, transform, &linear.into(), None, &rect); sb.fill(Fill::NonZero, transform, &linear.into(), None, &rect);
const GRADIENTS: &[(f64, f64, Color)] = &[ const GRADIENTS: &[(f64, f64, Color)] = &[
(150., 0., Color::rgb8(255, 240, 64)), (150., 0., Color::rgb8(255, 240, 64)),
@ -143,7 +143,7 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
for (x, y, c) in GRADIENTS { for (x, y, c) in GRADIENTS {
let mut color2 = c.clone(); let mut color2 = c.clone();
color2.a = 0; color2.a = 0;
let radial = RadialGradient::new((*x, *y), 100.0).stops([c.clone(), color2]); let radial = RadialGradient::new((*x, *y), 100.0).stops([*c, color2]);
sb.fill(Fill::NonZero, transform, &radial.into(), None, &rect); sb.fill(Fill::NonZero, transform, &radial.into(), None, &rect);
} }
const COLORS: &[Color] = &[ const COLORS: &[Color] = &[
@ -153,17 +153,7 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
]; ];
sb.push_layer(Mix::Normal.into(), transform, &rect); sb.push_layer(Mix::Normal.into(), transform, &rect);
for (i, c) in COLORS.iter().enumerate() { for (i, c) in COLORS.iter().enumerate() {
// let stops = &[ let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, *c]);
// GradientStop {
// color: Color::rgb8(255, 255, 255),
// offset: 0.0,
// },
// GradientStop {
// color: c.clone(),
// offset: 1.0,
// },
// ][..];
let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, c.clone()]);
sb.push_layer(blend, transform, &rect); sb.push_layer(blend, transform, &rect);
// squash the ellipse // squash the ellipse
let a = transform let a = transform