summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Biedert <github@ericbiedert.de>2024-08-05 12:24:22 +0200
committerGitHub <noreply@github.com>2024-08-05 10:24:22 +0000
commited247797ac17e0975d6663d65b0976ab92130d80 (patch)
tree32e957ed0ce6da03a780fee0952452a8322d5cce
parentdfdcc197c019b4ca5bc09487ee5f36030704b334 (diff)
Fix alignment of gradients and patterns on strokes in PNG (#4634)
-rw-r--r--crates/typst-render/src/paint.rs16
-rw-r--r--tests/ref/gradient-linear-stroke-relative-parent.pngbin0 -> 139 bytes
-rw-r--r--tests/ref/pattern-stroke-relative-parent.pngbin0 -> 757 bytes
-rw-r--r--tests/ref/pattern-stroke.pngbin248 -> 383 bytes
-rw-r--r--tests/suite/visualize/gradient.typ16
-rw-r--r--tests/suite/visualize/pattern.typ24
6 files changed, 54 insertions, 2 deletions
diff --git a/crates/typst-render/src/paint.rs b/crates/typst-render/src/paint.rs
index 2b5c19c9..3a507ca4 100644
--- a/crates/typst-render/src/paint.rs
+++ b/crates/typst-render/src/paint.rs
@@ -185,6 +185,12 @@ pub fn to_sk_paint<'a>(
.container_transform
.post_concat(state.transform.invert().unwrap()),
};
+
+ let gradient_map = match relative {
+ RelativeTo::Self_ => gradient_map,
+ RelativeTo::Parent => None,
+ };
+
let width =
(container_size.x.to_f32().abs() * state.pixel_per_pt).ceil() as u32;
let height =
@@ -225,6 +231,13 @@ pub fn to_sk_paint<'a>(
let canvas = render_pattern_frame(&state, pattern);
*pixmap = Some(Arc::new(canvas));
+ let offset = match relative {
+ RelativeTo::Self_ => {
+ gradient_map.map(|(offset, _)| -offset).unwrap_or_default()
+ }
+ RelativeTo::Parent => Point::zero(),
+ };
+
// Create the shader
sk_paint.shader = sk::Pattern::new(
pixmap.as_ref().unwrap().as_ref().as_ref(),
@@ -232,7 +245,8 @@ pub fn to_sk_paint<'a>(
sk::FilterQuality::Nearest,
1.0,
fill_transform
- .pre_scale(1.0 / state.pixel_per_pt, 1.0 / state.pixel_per_pt),
+ .pre_scale(1.0 / state.pixel_per_pt, 1.0 / state.pixel_per_pt)
+ .pre_translate(offset.x.to_f32(), offset.y.to_f32()),
);
}
}
diff --git a/tests/ref/gradient-linear-stroke-relative-parent.png b/tests/ref/gradient-linear-stroke-relative-parent.png
new file mode 100644
index 00000000..60da4ee8
--- /dev/null
+++ b/tests/ref/gradient-linear-stroke-relative-parent.png
Binary files differ
diff --git a/tests/ref/pattern-stroke-relative-parent.png b/tests/ref/pattern-stroke-relative-parent.png
new file mode 100644
index 00000000..fe9b1174
--- /dev/null
+++ b/tests/ref/pattern-stroke-relative-parent.png
Binary files differ
diff --git a/tests/ref/pattern-stroke.png b/tests/ref/pattern-stroke.png
index 8b03783b..a9f30aa8 100644
--- a/tests/ref/pattern-stroke.png
+++ b/tests/ref/pattern-stroke.png
Binary files differ
diff --git a/tests/suite/visualize/gradient.typ b/tests/suite/visualize/gradient.typ
index c3794150..61f6b6d0 100644
--- a/tests/suite/visualize/gradient.typ
+++ b/tests/suite/visualize/gradient.typ
@@ -175,6 +175,22 @@
)
)
+--- gradient-linear-stroke-relative-parent ---
+// The image should look as if there is a single gradient that is being used for
+// both the circle stroke and the block fill.
+#align(
+ center + horizon,
+ block(
+ width: 50pt,
+ height: 50pt,
+ fill: gradient.linear(red, blue).sharp(4),
+ circle(
+ radius: 18pt,
+ stroke: 5pt + gradient.linear(red, blue, relative: "parent").sharp(4),
+ )
+ )
+)
+
--- gradient-linear-line ---
// Test gradient on lines
#set page(width: 100pt, height: 100pt)
diff --git a/tests/suite/visualize/pattern.typ b/tests/suite/visualize/pattern.typ
index b0c92efa..b87b7755 100644
--- a/tests/suite/visualize/pattern.typ
+++ b/tests/suite/visualize/pattern.typ
@@ -101,13 +101,35 @@
center + top,
square(
size: 50pt,
- stroke: 5pt + pattern(
+ fill: pattern(
size: (5pt, 5pt),
align(horizon + center, circle(fill: blue, radius: 2.5pt))
+ ),
+ stroke: 7.5pt + pattern(
+ size: (5pt, 5pt),
+ align(horizon + center, circle(fill: red, radius: 2.5pt))
)
)
)
+--- pattern-stroke-relative-parent ---
+// Test pattern on strokes with relative set to `"parent"`
+// The pattern on the circle should align with the pattern on the square.
+#align(
+ center + top,
+ block(
+ width: 50pt,
+ height: 50pt,
+ fill: pattern(size: (5pt, 5pt), circle(radius: 2.5pt, fill: blue)),
+ align(center + horizon, circle(
+ radius: 15pt,
+ stroke: 7.5pt + pattern(
+ size: (5pt, 5pt), circle(radius: 2.5pt, fill: red), relative: "parent"
+ ),
+ ))
+ )
+)
+
--- pattern-text ---
// Test a pattern on some text
// You shouldn't be able to see the text, if you can then