Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix gradient stroke for line and curve#7863

Open
eltos wants to merge 10 commits intotypst:mainfrom
eltos:eltos-fix-gradient-line-stroke
Open

Fix gradient stroke for line and curve#7863
eltos wants to merge 10 commits intotypst:mainfrom
eltos:eltos-fix-gradient-line-stroke

Conversation

@eltos
Copy link
Contributor

@eltos eltos commented Feb 13, 2026

Fixes issues with gradient strokes for lines and curves:

Tests added

Left / right shows before / after this PR. PDF screenshots are from Adobe Acrobat (report.html does not render them correctly with my firefox)

issue-6068-curve-stroke-gradient
PNG
grafik
SVG
canvas
PDF
canvascanvas

issue-5705-gradient-border-stroke paged
PNG

SVG

PDF
2026-02-16 19-34-00

In the test images below, each "star" consists of lines/curves at different angles, all using the same stroke gradient.

gradient-line-stroke
PNG

SVG

PDF
grafik

gradient-curve-stroke
PNG

SVG

PDF
canvas

gradient-curve-stroke-quad
PNG

SVG

PDF
canvas

@eltos eltos force-pushed the eltos-fix-gradient-line-stroke branch from 9a6cc10 to 8d1f4a6 Compare February 14, 2026 09:33
@laurmaedje laurmaedje added the waiting-on-author Pull request waits on author label Feb 16, 2026
@eltos eltos force-pushed the eltos-fix-gradient-line-stroke branch from 8d1f4a6 to e1c597c Compare February 16, 2026 17:10
@eltos eltos force-pushed the eltos-fix-gradient-line-stroke branch from e1c597c to f1d41e3 Compare February 16, 2026 18:59
@eltos eltos force-pushed the eltos-fix-gradient-line-stroke branch from f1d41e3 to 019e30a Compare February 16, 2026 19:17
@eltos eltos marked this pull request as ready for review February 16, 2026 19:25
@eltos eltos changed the title Fix gradient stroke for line Fix gradient stroke for line and curve Feb 17, 2026
@laurmaedje laurmaedje added waiting-on-review This PR is waiting to be reviewed. and removed waiting-on-author Pull request waits on author labels Feb 18, 2026
@laurmaedje laurmaedje requested a review from saecki February 18, 2026 10:13
@laurmaedje laurmaedje added visualize Related to the visualize category, which is about drawing and illustrating fix A bug fix. labels Feb 18, 2026
Copy link
Member

@saecki saecki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for your work on gradients! This looks like some great improvements.

I agree with closing #5647 as expected behavior.

I think you're not part of the discord server, but since you're quite involved with gradients I'd be interested in your opinion regarding conic gradients. I've opened an issue just now to discuss the design: #7890

@eltos eltos force-pushed the eltos-fix-gradient-line-stroke branch from cf45a21 to 977c510 Compare February 20, 2026 18:44
@eltos
Copy link
Contributor Author

eltos commented Feb 20, 2026

@saecki ready for 2nd review

Copy link
Member

@saecki saecki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! And sorry for the delay (we had quite a busy week).

Geometry::Line(_) | Geometry::Curve(_) => s.geometry.bbox(s.stroke.as_ref()),
// Special handling for fill of rectangles (mirrors gradients for negative sizes)
Geometry::Rect(_) => {
Rect::from_pos_size(Point::zero(), s.geometry.bbox_size())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation on Rect says that min is always smaller than max, and the from_pos_size function doesn't check that. Maybe this could return a Point and Size tuple for now, so that we don't misuse the documented API of Rect.
The same also applies to the code in typst-svg.

Geometry::Line(_) | Geometry::Curve(_) => s.geometry.bbox(s.stroke.as_ref()),
// Special handling for fill of rectangles (mirrors gradients for negative sizes)
Geometry::Rect(_) => {
Rect::from_pos_size(Point::zero(), s.geometry.bbox_size())
Copy link
Member

@saecki saecki Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just noticed that by not passing the stroke, the bbox will be wrong for rectangles created by the typst_layout::shapes::simple_rect function such as:

#rect(
  width: 100pt,
  height: 100pt,
  stroke: gradient.linear(green, black, yellow, angle: 90deg).sharp(8) + 20pt,
)

The gradient is not spreading to the edge of the stroke (the weird clipping in the converted PDF is an issue that should be fixed in a newer hayro version)
report.html

So essentially the special handling for rectangles also has to check if the paint is converted for the stroke or the fill of the rectangle shape.

EDIT: It's probably desirable to have the same transform as the rect fill here, so let's just leave this as is 🤔

bbox
};

let bbox = shape.geometry.bbox(shape.stroke.as_ref());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This comment should go on line 44, but I can't add comments to lines not modified in this PR)

I've found another issue only present in typst-render for rectangles that don't have a radius. This is the issue-5705-gradient-border-stroke test without the radius:

#rect(
  width: 100pt,
  height: 100pt,
  stroke: (
    top: gradient.linear(green, black, yellow, angle: 90deg) + 20pt,
    right: gradient.linear(green, black, yellow, angle: 180deg) + 20pt,
    bottom: gradient.linear(green, black, yellow, angle: 270deg) + 20pt,
    left: gradient.linear(green, black, yellow, angle: 0deg) + 20pt,
  )
)

report.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix A bug fix. visualize Related to the visualize category, which is about drawing and illustrating waiting-on-review This PR is waiting to be reviewed.

Projects

None yet

3 participants