Fix issue in filling of clips (#914)
I noticed another issue in filling of clips (which already existed
previously, but unfortunately I didn't detect it in my last PR).
Currently, if I fill a rectangle with a black fill of opacity 0.5 onto a
white background, I get the RGB values 132 134 138 instead of the
expected values 127, 127, 127. I believe the issue was that we
mistakenly multiplied the alpha of the source color to the source, which
is not necessary because the color is already premultiplied.
With this PR, I get the expected values 127, 127, 127. It also fixes an
inconsistency with an existing test, where the color was not consistent
with the stripped part of the rectangle:
<img width="856" alt="image"
src="https://github.com/user-attachments/assets/25d274ad-e66d-4d09-8d70-5b3e24f8c334"
/>
Once gradients are merged, we can probably rewrite `clip_fill` and
`clip_stroke` to reuse the same method as for normal alpha compositing,
to avoid code duplication.
diff --git a/sparse_strips/vello_cpu/snapshots/clip_rectangle_and_circle.png b/sparse_strips/vello_cpu/snapshots/clip_rectangle_and_circle.png
index 9e11557..4c2c022 100644
--- a/sparse_strips/vello_cpu/snapshots/clip_rectangle_and_circle.png
+++ b/sparse_strips/vello_cpu/snapshots/clip_rectangle_and_circle.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ba1651c909d6b5b3080cf5c1399e3bb286262a0e21b52d704b26dcea94364f18
+oid sha256:0a3d7e6c32bb0d6a90218f2e02bb66d8873e7c3d35fc1c67e92f7f391934fa53
size 813
diff --git a/sparse_strips/vello_cpu/snapshots/clip_transformed_rect.png b/sparse_strips/vello_cpu/snapshots/clip_transformed_rect.png
index 11c1e88..ff5bf22 100644
--- a/sparse_strips/vello_cpu/snapshots/clip_transformed_rect.png
+++ b/sparse_strips/vello_cpu/snapshots/clip_transformed_rect.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a791ea6f3c2c3064efe62d2a9ee527f6f50f73df79e158397e4a28466fb5ad8e
-size 344
+oid sha256:6bd1da1a9e56743ee15c4285b492fb4c950a554ab0da5c7192e06958ad180d64
+size 336
diff --git a/sparse_strips/vello_cpu/snapshots/clip_triangle_with_star.png b/sparse_strips/vello_cpu/snapshots/clip_triangle_with_star.png
index 7282fee..0bcf4cb 100644
--- a/sparse_strips/vello_cpu/snapshots/clip_triangle_with_star.png
+++ b/sparse_strips/vello_cpu/snapshots/clip_triangle_with_star.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2a577d5d1950bd58f46510400b7c91d1c7b8a8fc5252a4a4857f475c951e6026
-size 1748
+oid sha256:d7af7733c8bf338555fa9a9a64fd1717467a92760ccff89f67b1d1dde32df579
+size 1735
diff --git a/sparse_strips/vello_cpu/snapshots/clip_with_multiple_transforms.png b/sparse_strips/vello_cpu/snapshots/clip_with_multiple_transforms.png
index aab8b98..42a243b 100644
--- a/sparse_strips/vello_cpu/snapshots/clip_with_multiple_transforms.png
+++ b/sparse_strips/vello_cpu/snapshots/clip_with_multiple_transforms.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:649e59dfb9f996d77cac55a6db704172a864b31febaf2b80dc11a2bafa47259d
-size 476
+oid sha256:dbb3ff2724c178f4610686bd50a2c330edbafaa116a8ec0b9e2b1a9a3614053f
+size 471
diff --git a/sparse_strips/vello_cpu/snapshots/clip_with_opacity.png b/sparse_strips/vello_cpu/snapshots/clip_with_opacity.png
new file mode 100644
index 0000000..43c9943
--- /dev/null
+++ b/sparse_strips/vello_cpu/snapshots/clip_with_opacity.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6bb8e071d932328c14680038a58f5f8207078b8750459fea48e2b0ded33867d9
+size 131
diff --git a/sparse_strips/vello_cpu/snapshots/clip_with_save_restore.png b/sparse_strips/vello_cpu/snapshots/clip_with_save_restore.png
index afdf623..b73a842 100644
--- a/sparse_strips/vello_cpu/snapshots/clip_with_save_restore.png
+++ b/sparse_strips/vello_cpu/snapshots/clip_with_save_restore.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8bf8baff9bb856e1b5864f6bf85f3cd3182dcec19434e12d343a68d6851b84c9
-size 444
+oid sha256:90816b2b794caf089ef94626a9d2bf2f6a8132e4905471d835b9894a4022eede
+size 437
diff --git a/sparse_strips/vello_cpu/src/fine.rs b/sparse_strips/vello_cpu/src/fine.rs
index 683ff54..773b07e 100644
--- a/sparse_strips/vello_cpu/src/fine.rs
+++ b/sparse_strips/vello_cpu/src/fine.rs
@@ -153,7 +153,7 @@
let dest = target_buffer[px_offset + channel_idx] as u16;
let src = source_buffer[px_offset + channel_idx] as u16;
target_buffer[px_offset + channel_idx] =
- div_255(dest * inverse_alpha + src * source_alpha) as u8;
+ (src + div_255(dest * inverse_alpha)) as u8;
}
}
}
diff --git a/sparse_strips/vello_cpu/tests/clip.rs b/sparse_strips/vello_cpu/tests/clip.rs
index 7420641..b9db8f5 100644
--- a/sparse_strips/vello_cpu/tests/clip.rs
+++ b/sparse_strips/vello_cpu/tests/clip.rs
@@ -5,7 +5,7 @@
use crate::util::{check_ref, circular_star, crossed_line_star, get_ctx};
use std::f64::consts::PI;
-use vello_common::color::palette::css::{DARK_BLUE, DARK_GREEN, REBECCA_PURPLE};
+use vello_common::color::palette::css::{BLACK, DARK_BLUE, DARK_GREEN, REBECCA_PURPLE};
use vello_common::kurbo::{Affine, BezPath, Circle, Point, Rect, Shape, Stroke};
use vello_common::peniko::Fill;
use vello_cpu::RenderContext;
@@ -259,6 +259,20 @@
check_ref(&ctx, "clip_with_save_restore");
}
+#[test]
+fn clip_with_opacity() {
+ // Main body of the shape should be RGB 127, 127, 127. Anti-aliased part should be
+ // 191, 191, 191.
+ let mut ctx = get_ctx(100, 100, false);
+ let clip_rect = Rect::new(10.5, 10.5, 89.5, 89.5);
+ ctx.clip(&clip_rect.to_path(0.1));
+ ctx.set_paint(BLACK.with_alpha(0.5).into());
+ ctx.fill_rect(&Rect::new(0.0, 0.0, 100.0, 100.0));
+ ctx.finish();
+
+ check_ref(&ctx, "clip_with_opacity");
+}
+
fn draw_clipping_outline(ctx: &mut RenderContext, path: &BezPath) {
let stroke = Stroke::new(1.0);
ctx.set_paint(DARK_BLUE.into());