Encode valid empty paths for empty clips There was logic to encode a valid empty path when the clip path was empty, but this logic was ineffective because of empty line segment culling. This patch Also includes a doc improvement for `push_layer`. Fixes #644
diff --git a/vello/src/scene.rs b/vello/src/scene.rs index 103e9b2..d958c4b 100644 --- a/vello/src/scene.rs +++ b/vello/src/scene.rs
@@ -66,6 +66,9 @@ /// until the layer is popped. /// /// **However, the transforms are *not* saved or modified by the layer stack.** + /// + /// Clip layers (`blend` = [`Mix::Clip`]) should have an alpha value of 1.0. + /// For an opacity group with non-unity alpha, specify [`Mix::Normal`]. pub fn push_layer( &mut self, blend: impl Into<BlendMode>, @@ -80,8 +83,7 @@ if !self.encoding.encode_shape(clip, true) { // If the layer shape is invalid, encode a valid empty path. This suppresses // all drawing until the layer is popped. - self.encoding - .encode_shape(&Rect::new(0.0, 0.0, 0.0, 0.0), true); + self.encoding.encode_empty_shape(); } else { #[cfg(feature = "bump_estimate")] self.estimator.count_path(clip.path_elements(0.1), &t, None);
diff --git a/vello_encoding/src/encoding.rs b/vello_encoding/src/encoding.rs index b83ec5a..d5c4684 100644 --- a/vello_encoding/src/encoding.rs +++ b/vello_encoding/src/encoding.rs
@@ -240,6 +240,12 @@ encoder.finish(true) != 0 } + pub fn encode_empty_shape(&mut self) { + let mut encoder = self.encode_path(true); + encoder.empty_path(); + encoder.finish(true); + } + /// Encodes a path element iterator. If `is_fill` is true, all subpaths will be automatically /// closed. Returns true if a non-zero number of segments were encoded. pub fn encode_path_elements(
diff --git a/vello_encoding/src/path.rs b/vello_encoding/src/path.rs index 7bb18cb..c4c2fa5 100644 --- a/vello_encoding/src/path.rs +++ b/vello_encoding/src/path.rs
@@ -599,6 +599,15 @@ self.n_encoded_segments += 1; } + /// Encodes an empty path (as placeholder for begin clip). + pub(crate) fn empty_path(&mut self) { + let coords = [0.0f32, 0., 0., 0.]; + let bytes = bytemuck::bytes_of(&coords); + self.data.extend_from_slice(bytes); + self.tags.push(PathTag::LINE_TO_F32); + self.n_encoded_segments += 1; + } + /// Closes the current subpath. pub fn close(&mut self) { match self.state {