diff --git a/crates/typst-render/src/paint.rs b/crates/typst-render/src/paint.rs index 2b5c19c93..3a507ca4c 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 000000000..60da4ee89 Binary files /dev/null and b/tests/ref/gradient-linear-stroke-relative-parent.png differ diff --git a/tests/ref/pattern-stroke-relative-parent.png b/tests/ref/pattern-stroke-relative-parent.png new file mode 100644 index 000000000..fe9b1174f Binary files /dev/null and b/tests/ref/pattern-stroke-relative-parent.png differ diff --git a/tests/ref/pattern-stroke.png b/tests/ref/pattern-stroke.png index 8b03783b5..a9f30aa82 100644 Binary files a/tests/ref/pattern-stroke.png and b/tests/ref/pattern-stroke.png differ diff --git a/tests/suite/visualize/gradient.typ b/tests/suite/visualize/gradient.typ index c37941507..61f6b6d05 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 b0c92efaf..b87b77559 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