Skip to content

Support different joins for stroked rects in uber_sdf, fix incorrect aa#184395

Merged
auto-submit[bot] merged 4 commits into
flutter:masterfrom
b-luk:ubersdfstrokejoin
Apr 2, 2026
Merged

Support different joins for stroked rects in uber_sdf, fix incorrect aa#184395
auto-submit[bot] merged 4 commits into
flutter:masterfrom
b-luk:ubersdfstrokejoin

Conversation

@b-luk

@b-luk b-luk commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Improves (but doesn't completely fix) #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:

AiksTest.StrokedRectsRenderCorrectly

Before:
image
After:
image
Non-sdf:
image

AiksTest.CanRenderWideStrokedRectWithoutOverlap

Before:
image
After:
image
Non-sdf:
image

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-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.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests labels Mar 31, 2026
@b-luk b-luk changed the title Support stroke join types for rects in uber_sdf Support different joins for stroked rects in uber_sdf, fix incorrect aa Mar 31, 2026
@b-luk b-luk requested review from flar and gaaclarke March 31, 2026 17:23
@gaaclarke gaaclarke marked this pull request as ready for review March 31, 2026 17:23
@gaaclarke gaaclarke added the CICD Run CI/CD label Mar 31, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines 45 to +48
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));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

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.

Suggested change
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));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sounds right, feel free to avoid touching it for now if you want though since it doesn't have to do with rects.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Definitely agree that the signature of these calls are weird and can be improved. I plan to clean this up in my next PR.

@b-luk

b-luk commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

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 gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be hardcoded you think? Maybe this should be coming from the Canvas as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment on lines +59 to +63
if (frag_info.type < 0.5) { // Circle
dist = distanceFromCircle(p, frag_info.size.x);
} else { // Rect
dist = distanceFromRect(p, frag_info.size);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably worth breaking this out into 2 different functions now, float ComputeFilledSDF() and float ComputeStrokedSDF()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 45 to +48
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));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sounds right, feel free to avoid touching it for now if you want though since it doesn't have to do with rects.

@gaaclarke

Copy link
Copy Markdown
Member

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) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

no action required: we should probably move these functions to a .glsl file at some point.

@github-actions github-actions Bot removed the CICD Run CI/CD label Mar 31, 2026
@b-luk b-luk added the CICD Run CI/CD label Mar 31, 2026
@b-luk

b-luk commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

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.

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.

gaaclarke
gaaclarke previously approved these changes Mar 31, 2026

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm, thanks!

@flar

flar commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Why don't the thin white lines (that show the original lines being stroked) show up in the SDF version?

@b-luk

b-luk commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

This is the
"Hairline (stroke_width = 0.0) stroked rects do not show up. See the CanRenderWideStrokedRectWithoutOverlap golden images below. This needs a solution. #184403"
item from my list of follow-up fixes in the OP.

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 flar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Alternatively, the FillRectGeometry contains both the stroke join and the stroke width. This signature can be reduced to MakeRect(color, geometry)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment on lines 45 to +48
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));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@b-luk b-luk requested a review from flar March 31, 2026 21:52
@github-actions github-actions Bot removed the CICD Run CI/CD label Mar 31, 2026
@b-luk b-luk added the CICD Run CI/CD label Mar 31, 2026
@flutter-dashboard

Copy link
Copy Markdown

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 package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #184395 at sha f90f66a

@flutter-dashboard flutter-dashboard Bot added the will affect goldens Changes to golden files label Mar 31, 2026

@flar flar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. I asked gemini to come up with a demo. Looks pretty good to me.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's pretty cool.

if (frag_info.type < 0.5) { // Circle
return distanceFromCircle(p, frag_info.size.x);
} else { // Rect
return distanceFromRect(p, frag_info.size);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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...?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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"?

@b-luk b-luk Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

And looking at all the other golden diffs, this explains odd diffs you might see for all of them. If you compare with the latest goldens instead of the closet ones, all the diffs are related to stroked rectangles as expected.
image

@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 2, 2026
@b-luk b-luk added the CICD Run CI/CD label Apr 2, 2026
@flutter-dashboard

Copy link
Copy Markdown

Golden file changes are available for triage from new commit, Click here to view.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #184395 at sha 07ee671

@flar flar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's pretty cool.

@b-luk b-luk added the autosubmit Merge PR when tree becomes green via auto submit App label Apr 2, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue Apr 2, 2026
Merged via the queue into flutter:master with commit d24ebdc Apr 2, 2026
190 of 191 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Apr 2, 2026
@b-luk b-luk deleted the ubersdfstrokejoin branch April 2, 2026 23:24
@hellohuanlin

Copy link
Copy Markdown
Contributor
Screenshot 2026-04-02 at 11 26 12 PM

Hi @b-luk

This seems to be the first commit to break Mac mac_unopt test. I've suppressed it while investigating it.

See https://ci.chromium.org/ui/p/flutter/builders/prod/Mac%20mac_unopt/11889/overview

@hellohuanlin hellohuanlin mentioned this pull request Apr 3, 2026
@hellohuanlin

Copy link
Copy Markdown
Contributor

@b-luk I think i'm gonna revert it while we investigate - the longer we suppress the test the higher the risk.

@hellohuanlin hellohuanlin added the revert Autorevert PR (with "Reason for revert:" comment) label Apr 3, 2026
@hellohuanlin

hellohuanlin commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Reason for revert: it breaks the tree

auto-submit Bot pushed a commit that referenced this pull request Apr 3, 2026
@auto-submit auto-submit Bot removed the revert Autorevert PR (with "Reason for revert:" comment) label Apr 3, 2026
@walley892

Copy link
Copy Markdown
Contributor

@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.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Apr 3, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Apr 3, 2026
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
mbcorona pushed a commit to mbcorona/flutter that referenced this pull request Apr 15, 2026
…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
github-merge-queue Bot pushed a commit that referenced this pull request Apr 18, 2026
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels. will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants