Fix brush transforms

This fixes an incorrect application of the inverse transform for radial gradients in fine.

Also fixes an edge case in `SceneBuilder` where a brush transform is identical to the path transform leading to a corrupt encoding.
This commit is contained in:
Chad Brokaw 2023-02-22 20:10:00 -05:00
parent 0bb519c1ba
commit 033870d91e
3 changed files with 22 additions and 14 deletions

View file

@ -251,7 +251,7 @@ fn main(
for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) {
let my_xy = vec2(xy.x + f32(i), xy.y); let my_xy = vec2(xy.x + f32(i), xy.y);
// TODO: can hoist y, but for now stick to the GLSL version // TODO: can hoist y, but for now stick to the GLSL version
let xy_xformed = rad.matrx.xz * my_xy.x + rad.matrx.yw * my_xy.y - rad.xlat; let xy_xformed = rad.matrx.xy * my_xy.x + rad.matrx.zw * my_xy.y - rad.xlat;
let ba = dot(xy_xformed, rad.c1); let ba = dot(xy_xformed, rad.c1);
let ca = rad.ra * dot(xy_xformed, xy_xformed); let ca = rad.ra * dot(xy_xformed, xy_xformed);
let t = sqrt(ba * ba + ca) - ba - rad.roff; let t = sqrt(ba * ba + ca) - ba - rad.roff;

View file

@ -120,10 +120,16 @@ impl Encoding {
} }
/// Encodes a transform. /// Encodes a transform.
pub fn encode_transform(&mut self, transform: Transform) { ///
/// If the given transform is different from the current one, encodes it an
/// returns true. Otherwise, encodes nothing and returns false.
pub fn encode_transform(&mut self, transform: Transform) -> bool {
if self.transforms.last() != Some(&transform) { if self.transforms.last() != Some(&transform) {
self.path_tags.push(PathTag::TRANSFORM); self.path_tags.push(PathTag::TRANSFORM);
self.transforms.push(transform); self.transforms.push(transform);
true
} else {
false
} }
} }

View file

@ -140,14 +140,15 @@ impl<'a> SceneBuilder<'a> {
}); });
if self.scene.encode_shape(shape, true) { if self.scene.encode_shape(shape, true) {
if let Some(brush_transform) = brush_transform { if let Some(brush_transform) = brush_transform {
self.scene if self
.encode_transform(Transform::from_kurbo(&(transform * brush_transform))); .scene
.encode_transform(Transform::from_kurbo(&(transform * brush_transform)))
{
self.scene.swap_last_path_tags(); self.scene.swap_last_path_tags();
self.scene.encode_brush(brush, 1.0);
} else {
self.scene.encode_brush(brush, 1.0);
} }
} }
self.scene.encode_brush(brush, 1.0);
}
} }
/// Strokes a shape using the specified style and brush. /// Strokes a shape using the specified style and brush.
@ -164,14 +165,15 @@ impl<'a> SceneBuilder<'a> {
self.scene.encode_linewidth(style.width); self.scene.encode_linewidth(style.width);
if self.scene.encode_shape(shape, false) { if self.scene.encode_shape(shape, false) {
if let Some(brush_transform) = brush_transform { if let Some(brush_transform) = brush_transform {
self.scene if self
.encode_transform(Transform::from_kurbo(&(transform * brush_transform))); .scene
.encode_transform(Transform::from_kurbo(&(transform * brush_transform)))
{
self.scene.swap_last_path_tags(); self.scene.swap_last_path_tags();
self.scene.encode_brush(brush, 1.0);
} else {
self.scene.encode_brush(brush, 1.0);
} }
} }
self.scene.encode_brush(brush, 1.0);
}
} }
/// Appends a fragment to the scene. /// Appends a fragment to the scene.