Support different joins for stroked rects in uber_sdf, fix incorrect aa#184395
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for stroke joins (Miter, Bevel, and Round) within the UberSDFContents class and the corresponding uber_sdf fragment shader. Key changes include updating MakeRect to handle join types, hardcoding anti-alias padding for rectangles to 1.0f, and implementing a new distanceFromChamferRect function in the shader to support beveled strokes. Feedback suggests extending the hardcoded anti-alias padding to circles in MakeCircle to ensure consistent sharpness and prevent excessive blurriness.
| Scalar aa_padding = geometry->GetAntialiasPadding(); | ||
| return std::unique_ptr<UberSDFContents>(new UberSDFContents( | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), stroked, | ||
| geometry, aa_padding)); | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), | ||
| Join::kMiter, stroked, geometry, aa_padding)); |
There was a problem hiding this comment.
The aa_padding for circles should also be hardcoded to 1.0f, consistent with the fix applied to rectangles in MakeRect. Currently, MakeCircle uses geometry->GetAntialiasPadding(), which for stroked circles includes half the stroke width. This causes the aa_pixels uniform in the shader to be much larger than intended, resulting in excessively blurry strokes for circles.
| Scalar aa_padding = geometry->GetAntialiasPadding(); | |
| return std::unique_ptr<UberSDFContents>(new UberSDFContents( | |
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), stroked, | |
| geometry, aa_padding)); | |
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), | |
| Join::kMiter, stroked, geometry, aa_padding)); | |
| Scalar aa_padding = 1.0f; | |
| return std::unique_ptr<UberSDFContents>(new UberSDFContents( | |
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), | |
| Join::kMiter, stroked, geometry, aa_padding)); |
There was a problem hiding this comment.
Sounds right, feel free to avoid touching it for now if you want though since it doesn't have to do with rects.
There was a problem hiding this comment.
Using aa_padding = geometry->GetAntialiasPadding() for circles doesn't cause any issues right now, because the UberSDF circle geometry does not add padding for strokes in the same way that the UberSDF rect geometry does.
UberSDF stroked circles use StrokedCircleGeometry which accounts for the expanded shape of the stroked circle. And filled UberSDF circles use FilledCircleGeometry, without the stroke padding, as expected.
But with rectangles, UberSDF uses FilledRectangleGeometry for both filled and stroked circles. It hacks the FilledRectangleGeometry to explicitly add padding for the stroke width. This caused the original AA pixel size issue, which this 1.0 hard-coding fixes. A better solution would be to make stroked SDF rectangles use StrokedRectangleGeometry. This would be more consistent with how the circle SDF works, and it is a more optimal geometry covering only the stroked region, so the fragment shader will not need to run on any of the "inside-the-shape" pixels. This is one of the improvements I have in mind for the "inconsistent logic and can be cleaned up" follow-ups that I mention in the PR description.
There was a problem hiding this comment.
This needs to be a lot less "side-effect-y" and more "here is the data you should use, ignore what other objects think".
Or just decide we're going to go with aa_pixels==1.0 and worry about making it configurable later when we come up with a reason.
There was a problem hiding this comment.
Definitely agree that the signature of these calls are weird and can be improved. I plan to clean this up in my next PR.
|
I just noticed: In StrokedRectsRenderCorrectly for the bottom right blue rectangle is still not being rendered correctly. This is a rect with a Miter join, but with a miter limit set to be less than a 90 degree angle, so it falls back to a Bevel join. The SDF doesn't support miter limits, so we'll need to add support for that. I added this to the "todo in a follow-up PR" section of the PR description. |
gaaclarke
left a comment
There was a problem hiding this comment.
LGTM, great work. I have one organization suggestion and question.
| const FillRectGeometry* geometry) { | ||
| Rect bounding_box = geometry->GetRect(); | ||
| Scalar aa_padding = geometry->GetAntialiasPadding(); | ||
| Scalar aa_padding = 1.0f; |
There was a problem hiding this comment.
Should this be hardcoded you think? Maybe this should be coming from the Canvas as well.
There was a problem hiding this comment.
I think we can do something better here, which I touch upon in my reply to gemini's comment. But I'm going to think through this and do it in a follow-up PR. It'll be a significant change so I want to keep it separate from this PR so they will both be smaller and easier to review.
| if (frag_info.type < 0.5) { // Circle | ||
| dist = distanceFromCircle(p, frag_info.size.x); | ||
| } else { // Rect | ||
| dist = distanceFromRect(p, frag_info.size); | ||
| } |
There was a problem hiding this comment.
Probably worth breaking this out into 2 different functions now, float ComputeFilledSDF() and float ComputeStrokedSDF()
| Scalar aa_padding = geometry->GetAntialiasPadding(); | ||
| return std::unique_ptr<UberSDFContents>(new UberSDFContents( | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), stroked, | ||
| geometry, aa_padding)); | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), | ||
| Join::kMiter, stroked, geometry, aa_padding)); |
There was a problem hiding this comment.
Sounds right, feel free to avoid touching it for now if you want though since it doesn't have to do with rects.
|
Also, please don't forget to fill out the form in the description and file issues for the followup work and assign them to the macos Impeller project. |
| return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0); | ||
| } | ||
|
|
||
| float distanceFromChamferRect(vec2 p, vec2 b, float chamfer) { |
There was a problem hiding this comment.
no action required: we should probably move these functions to a .glsl file at some point.
Filled in most of the form checkboxes. I'll fill in the test related ones once I update this PR with some tests. I filed #184402, #184403, and #184404 for the follow-up issues. |
|
Why don't the thin white lines (that show the original lines being stroked) show up in the SDF version? |
This is the I believe we'll need to add some special case logic in the SDFs to use a 1 pixel stroke width if the provided stroke_width is 0. Right now it uses the provided stroke_width directly, so a 0 stroke width has a literal width of 0. I plan to look into this and fix it in a follow up PR. |
flar
left a comment
There was a problem hiding this comment.
I have an outstanding question about why the thin shapes aren't appearing and I believe it is because the code isn't dealing with stroke_width==0. Since that is the default stroke width for Flutter, we need to deal with that.
|
|
||
| auto contents = UberSDFContents::MakeRect( | ||
| /*color=*/paint.color, /*stroke_width=*/paint.stroke.width, | ||
| /*stroke_join=*/paint.stroke.join, |
There was a problem hiding this comment.
For a rectangle you can simply test the miter limit here and back off to a bevel join if it is less than 90 degrees. The Uber shader doesn't even have to process this and the miter limit of 90 degrees is a constant value.
There was a problem hiding this comment.
This could be done here, or in the factory method (if you pass the miter limit in).
BTW, both the width and the join are in the "StrokeParamters" field of paint so you can pass both in by just passing paint.stroke and then the factory method can use any of the data if the stroke flag is set.
There was a problem hiding this comment.
I like the suggestion of checking for this in the factory method, and making it take paint.stroke (or the entire paint object, and we don't need to separately pass in color or the "stroked" bool).
My preference is to do all this cleanup in a follow-up, because I think it'll add a bunch more changes and I prefer to keep PRs smaller scoped and easily reviewable. But let me know if you feel differently and do want some of these changes as part of this PR.
There was a problem hiding this comment.
Alternatively, the FillRectGeometry contains both the stroke join and the stroke width. This signature can be reduced to MakeRect(color, geometry)
There was a problem hiding this comment.
FillRectGeometry has no stroke information. Only StrokeRectGeometry has stroke information. https://github.com/flutter/flutter/blob/0f401eea04390dc08eb939b6c0fee17c7d15f6ec/engine/src/flutter/impeller/entity/geometry/rect_geometry.h
I have a PR in progress that does a lot of refactoring which should clean up a lot of this. I'll send it out to you when it's ready.
| Scalar aa_padding = geometry->GetAntialiasPadding(); | ||
| return std::unique_ptr<UberSDFContents>(new UberSDFContents( | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), stroked, | ||
| geometry, aa_padding)); | ||
| Type::kCircle, bounding_box, color, geometry->GetStrokeWidth(), | ||
| Join::kMiter, stroked, geometry, aa_padding)); |
There was a problem hiding this comment.
This needs to be a lot less "side-effect-y" and more "here is the data you should use, ignore what other objects think".
Or just decide we're going to go with aa_pixels==1.0 and worry about making it configurable later when we come up with a reason.
|
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
flar
left a comment
There was a problem hiding this comment.
There's a mystery with an odd extra pixel suddenly appearing at the corner of filled rects that is worth figuring out before we push. We should at least understand why it's there before it gets committed to the approved goldens...
| distanceFromChamferRect(p, frag_info.size + half_stroke, half_stroke); | ||
| } else { // Round | ||
| // Rectangle sdf expanded by half_stroke, to give a half_stroke radius | ||
| outer = distanceFromRect(p, frag_info.size) - half_stroke; |
There was a problem hiding this comment.
Perhaps leave a link to a shadertoy that shows how the sdf field takes on the shape of nested rounded rects at increasing distances outside the rect and so subtracting half_stroke simply makes the rounded echo that is at that distance be our "0.0" distance for the outer stroke value.
There was a problem hiding this comment.
Done. I asked gemini to come up with a demo. Looks pretty good to me.
| if (frag_info.type < 0.5) { // Circle | ||
| return distanceFromCircle(p, frag_info.size.x); | ||
| } else { // Rect | ||
| return distanceFromRect(p, frag_info.size); |
There was a problem hiding this comment.
For some reason we are getting slightly non-transparent pixels just beyond the corners of the filled rects in the goldens. There is one golden result where the only real difference is a slightly non-transparent pixel beyond the corner.
What's really odd is that I don't see why it happens on this PR but didn't happen on the PR that introduced the filled rect equation...?
There was a problem hiding this comment.
Actually, there are a lot of corner differences for the filled rects - check out the golden for CoverageOriginShouldBeAccountedForInSubpasses_MetalSDF for instance. They might be due to the fact that none of those rects are pixel aligned (due to PixelScale() for instance?) and the new function now behaves differently estimating the coverage of a partiallly covered corner pixel.
Actually, I'm pretty sure that is true because a corner pixel that is only half intersected in X and half intersected in Y should produce a value that is 25%, but we now produce a value that is the area of a half-unit circle - i.e. 19%. The values shrink faster the less of the pixel that is covered.
But, the odd question is "why on this PR and not the other one"?
There was a problem hiding this comment.
But, the odd question is "why on this PR and not the other one"?
I messaged you directly, but will comment here to have it on record.
There are two approved goldens in the db. One is from before any rect SDFs. And one is after the original rect SDF implementation.
The "closest positive" result showing up in the golden tool is comparing my result with the very initial test before rects had any SDF implementation.
Comparing with the most recent positive instead, we get this: https://flutter-gold.skia.org/diff?grouping=name%3Dengine.impeller_Play_AiksTest_CoverageOriginShouldBeAccountedForInSubpasses_MetalSDF%26source_type%3Dflutter&left=d8691dbc3c8fdd2c6655392c7bd30e60&right=777903a4342eaf020a06f4f5e06ca1b7&changelist_id=184395&crs=github.
Looking at this one, there are a lot of differences around the outer yellow stroked rect, as expected because my PR changes stroked rects. The corner artifacting outside of filled rect corners is present in both this result and in my PR. It does not show up in the diff image for this comparison because it's the same in both.
|
Golden file changes are available for triage from new commit, Click here to view. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
flar
left a comment
There was a problem hiding this comment.
It's clear we're going to have to be more explicit about retiring old goldens while we slowly clear up issues in the SDF renderers, but the code itself looks fine now.
We should file an issue to look at why the rect SDF leaves some dirt outside the corners. It's not really visible, but it is very odd.
| distanceFromChamferRect(p, frag_info.size + half_stroke, half_stroke); | ||
| } else { // Round | ||
| // Rectangle sdf expanded by half_stroke, to give a half_stroke radius | ||
| outer = distanceFromRect(p, frag_info.size) - half_stroke; |
Hi @b-luk This seems to be the first commit to break |
|
@b-luk I think i'm gonna revert it while we investigate - the longer we suppress the test the higher the risk. |
|
Reason for revert: it breaks the tree |
|
@hellohuanlin if you look into the test failures, it looks like there were unapproved goldens. https://ci.chromium.org/ui/p/flutter/builders/prod/Mac%20Production%20Engine%20Drone/939114/overview I've approved the goldens. Please re-run the post submits - I don't think a revert is appropriate in this case if we can avoid it. |
flutter/flutter@0f401ee...7245c3f 2026-04-03 [email protected] Roll Skia from c07c67045b6d to 5d847ba5c4aa (1 revision) (flutter/flutter#184570) 2026-04-03 [email protected] Roll Dart SDK from 3c7a79045b8b to 46f49142acd9 (1 revision) (flutter/flutter#184567) 2026-04-03 [email protected] Roll ICU from ee5f27adc28b to ff7995a708a1 (5 revisions) (flutter/flutter#184566) 2026-04-03 [email protected] Roll Skia from 9ae8231be181 to c07c67045b6d (4 revisions) (flutter/flutter#184562) 2026-04-03 [email protected] Roll Fuchsia Linux SDK from BFLjk6Uwd0gs_Hkdk... to PpL3Bn2YMb2h9LbdK... (flutter/flutter#184556) 2026-04-03 [email protected] Roll Skia from 0566b2f5f0d1 to 9ae8231be181 (1 revision) (flutter/flutter#184547) 2026-04-03 [email protected] Roll Dart SDK from 6008eaddd589 to 3c7a79045b8b (3 revisions) (flutter/flutter#184551) 2026-04-03 [email protected] Fix wide gamut macos integration test (flutter/flutter#184427) 2026-04-02 [email protected] forward an application name to DDS (flutter/flutter#184459) 2026-04-02 [email protected] Roll Skia from 973117cfa875 to 0566b2f5f0d1 (8 revisions) (flutter/flutter#184534) 2026-04-02 [email protected] Support different joins for stroked rects in uber_sdf, fix incorrect aa (flutter/flutter#184395) 2026-04-02 [email protected] [ Widget Preview ] Handle collections and records in custom preview annotations (flutter/flutter#184518) 2026-04-02 [email protected] Moves android_semantics_integration_test out of staging (flutter/flutter#184079) 2026-04-02 [email protected] Roll Packages from b3fcf14 to 66bf7ec (4 revisions) (flutter/flutter#184514) 2026-04-02 [email protected] Fix line breaks being lost when copying after selection gesture in SelectableRegion (flutter/flutter#184421) 2026-04-02 [email protected] Add plugin version to SwiftPM package symlink directory (flutter/flutter#183668) 2026-04-02 [email protected] Add our own wrapper for `CommonExtension` due to change in signature from 8.x->9.0 (flutter/flutter#184433) 2026-04-02 [email protected] [Android] Use EdgeToEdge.enable/WindowCompat for edge-to-edge mode instead of deprecated View flags (flutter/flutter#183072) 2026-04-02 [email protected] [data_assets] Cleanup tests (flutter/flutter#184209) 2026-04-02 [email protected] Enable SPM by default on Stable (flutter/flutter#184495) 2026-04-02 [email protected] Roll Dart SDK from d84bdfeb45eb to 6008eaddd589 (2 revisions) (flutter/flutter#184513) 2026-04-02 [email protected] Reland "Even more awaits" (flutter/flutter#184467) 2026-04-02 [email protected] Roll Skia from bb9fd8653739 to 973117cfa875 (2 revisions) (flutter/flutter#184498) 2026-04-02 [email protected] [ Widget Preview ] Use analysis server for widget preview detection (flutter/flutter#184473) 2026-04-02 [email protected] [web_ui] Fix avoid_type_to_string lint violation (flutter/flutter#184342) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…aa (flutter#184395) Improves (but doesn't completely fix) flutter#184352. Add stroke join style support for stroked rects and revamp `uber_sdf` stroking logic: - Adds `stroke_join` input to `uber_sdf` shader - Changes how `uber_sdf.frag` handles stroked shapes. It calculates the outer and inner SDFs of the stroked shape, then subtracts the inner shape from the outer shape. The old code did something that always ends up with round-joined strokes, and I think this new version is easier to follow. - `stroke_join` is taken into account to use different outer-edge shapes for stroked rects Fix incorrect `aa_pixels` used for stroked rects: - Hard-code a 1.0 value for `UberSDFContents::MakeRect`'s `aa_padding`. This was using `geometry->GetAntialiasPadding()` before, which is misleadingly not the intended AA padding, but instead is the "total padding" for turning a filled rect geometry into the geometry for an sdf-stroked rect (adding a half-stroke-width padding to account for the width of the stroking). Planning to do in follow-up PRs: - I think the stroking/AA/geometry logic for UberSDFContents is inconsistent and can be cleaned up significantly. flutter#184402 - Hairline (stroke_width = 0.0) stroked rects do not show up. See the `CanRenderWideStrokedRectWithoutOverlap` golden images below. This needs a solution. flutter#184403 - In StrokedRectsRenderCorrectly for the bottom right blue rectangle is still not being rendered correctly. This is a rect with a Miter join, but with a miter limit set to be less than a 90 degree angle, so it falls back to a Bevel join. The SDF doesn't support miter limits, so we'll need to add support for that. flutter#184404 #### AiksTest.StrokedRectsRenderCorrectly ##### Before: <img width="484" height="320" alt="image" src="https://github.com/user-attachments/assets/aa395574-7af9-4f19-9afe-151b3726a1ed" /> ##### After: <img width="484" height="320" alt="image" src="https://github.com/user-attachments/assets/4cc13fbe-4a8a-4027-88c8-19a2366148d2" /> ##### Non-sdf: <img width="484" height="320" alt="image" src="https://github.com/user-attachments/assets/135c0cb7-3479-4ac9-8aa3-ec6b77adaff8" /> #### AiksTest.CanRenderWideStrokedRectWithoutOverlap ##### Before: <img width="404" height="281" alt="image" src="https://github.com/user-attachments/assets/2c5126b1-60b8-437a-bfbb-f93726317057" /> ##### After: <img width="404" height="280" alt="image" src="https://github.com/user-attachments/assets/0d78f1d5-89a6-4705-a2fb-3cebc086a3a9" /> ##### Non-sdf: <img width="404" height="280" alt="image" src="https://github.com/user-attachments/assets/c3f815b0-2eaf-4ecb-a0a2-ceebf18e33e7" /> ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…ather than manhattan distance. (#184984) Our golden tests showed that we were getting slightly non-transparent pixels just beyond the corners of filled rects. This was pointed out In #184395 (comment). This was due to incorrectly using manhattan distance rather than euclidean distance to determine pixel size for antialiasing. At non-axis-aligned angles (most egregious at 45 degrees), using manhattan distance overestimates the pixel size. This results in AA fading shape edges over a longer distance at the 45 degree edges of a shape compared to the axis-aligned edges of the shape. This caused: - Unexpected translucent pixels appeared past the corners of rectangles, because AA was fading the corner diagonally beyond the end of the rectangle. - Circles get slightly wider as their edges go closer to diagonal angles. Similar to #182708 for the Circle SDF. - Rectangles rotated to be non-axis aligned had slightly wider edges than expected. Changing from manhattan distance to euclidean distance fixes this. Part of #184352 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md


Improves (but doesn't completely fix) #184352.
Add stroke join style support for stroked rects and revamp
uber_sdfstroking logic:stroke_joininput touber_sdfshaderuber_sdf.fraghandles stroked shapes. It calculates the outer and inner SDFs of the stroked shape, then subtracts the inner shape from the outer shape. The old code did something that always ends up with round-joined strokes, and I think this new version is easier to follow.stroke_joinis taken into account to use different outer-edge shapes for stroked rectsFix incorrect
aa_pixelsused for stroked rects:UberSDFContents::MakeRect'saa_padding. This was usinggeometry->GetAntialiasPadding()before, which is misleadingly not the intended AA padding, but instead is the "total padding" for turning a filled rect geometry into the geometry for an sdf-stroked rect (adding a half-stroke-width padding to account for the width of the stroking).Planning to do in follow-up PRs:
CanRenderWideStrokedRectWithoutOverlapgolden images below. This needs a solution. Handle hairline strokes for Rect SDFs #184403AiksTest.StrokedRectsRenderCorrectly
Before:
After:
Non-sdf:
AiksTest.CanRenderWideStrokedRectWithoutOverlap
Before:
After:
Non-sdf:
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.