fix(🐛): trim a path before stroking it - #4018
Merged
Merged
Conversation
drawPath applied the stroke prop before start/end, so trimming walked
the perimeter of the generated outline rather than the path the caller
drew. <Path path="M 20 128 L 236 128" stroke={{ width: 20 }} end={0.5} />
painted the right half of the line instead of the left.
The native recorder already trims first (PathCmd in
cpp/api/recorder/Drawings.h), so this only affected the JS player - Web
and the static container.
wcandillon
requested changes
Aug 22, 2026
wcandillon
left a comment
Contributor
There was a problem hiding this comment.
Very nice catch :)
please use checkImage(img...) instead of expect(alphaAt(...
Move it to renderer/__tests__/e2e so it also runs against native, draw through surface.draw and compare with checkImage instead of sampling alpha by hand. An untrimmed baseline sits next to the trimmed one so the two halves are easy to tell apart.
Contributor
Author
|
@wcandillon appreciate it! |
wcandillon
approved these changes
Aug 22, 2026
Contributor
|
the native implementation side disappeared somehow? I added it back |
Contributor
|
🎉 This PR is included in version 2.11.1 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
drawPathapplies thestrokeprop beforestart/end:Path.Strokereplaces the path with the outline of the stroke — a closed loop around it. Trimming afterwards walks that loop's perimeter, sostart/endno longer refer to anything the caller drew.mainend={0.5}paints the right half of the line — the halves are inverted, because half the outline's perimeter happens to land there.The native recorder already gets this right —
PathCmd::drawincpp/api/recorder/Drawings.hruns trim → fill type → stroke:So this is a JS-player divergence: Web and the static container were affected, iOS and Android were not.
Fix
Reorder the JS player to match: trim → fill type → stroke.
Tests
packages/skia/src/sksg/__tests__/PathTrim.spec.tsxrenders the case above and samples both halves. It fails onmain(Expected: 255, Received: 0) and passes with the fix.No baselines move — nothing in the suite combined
strokewithstart/end, which is why this went unnoticed. Full suite: 747 passed,tsc --noEmitandeslint --max-warnings 0clean.