Encode valid empty paths for empty clips (#651)

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 directly encodes an empty path (single zero-length
line).

Also includes a doc improvement for `push_layer`.

Fixes #644
diff --git a/vello/src/scene.rs b/vello/src/scene.rs
index 103e9b2..92aa373 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>,
@@ -74,14 +77,22 @@
         clip: &impl Shape,
     ) {
         let blend = blend.into();
+        if blend.mix == Mix::Clip && alpha != 1.0 {
+            log::warn!("Clip mix mode used with semitransparent alpha");
+        }
         let t = Transform::from_kurbo(&transform);
         self.encoding.encode_transform(t);
         self.encoding.encode_fill_style(Fill::NonZero);
         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();
+            #[cfg(feature = "bump_estimate")]
+            {
+                use peniko::kurbo::PathEl;
+                let path = [PathEl::MoveTo(Point::ZERO), PathEl::LineTo(Point::ZERO)];
+                self.estimator.count_path(path.into_iter(), &t, None);
+            }
         } 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..8cf6aff 100644
--- a/vello_encoding/src/encoding.rs
+++ b/vello_encoding/src/encoding.rs
@@ -240,6 +240,17 @@
         encoder.finish(true) != 0
     }
 
+    /// Encode an empty path.
+    ///
+    /// This is useful for bookkeeping when a path is absolutely required (for example in
+    /// pushing a clip layer). It is almost always the case, however, that an application
+    /// can be optimized to not use this method.
+    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 {