Skip to content

Conversation

@definev
Copy link
Contributor

@definev definev commented Sep 26, 2025

This PR fixed visual bug when placing multiple ColoredBoxs together. (Fixes #176028)

Pre-launch Checklist

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@google-cla
Copy link

google-cla bot commented Sep 26, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@github-actions github-actions bot added the framework flutter/packages/flutter repository. See also f: labels. label Sep 26, 2025
Copy link
Contributor

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

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 an optimization to ColoredBox by disabling anti-aliasing when drawing its background rectangle. This is a good change that should fix visual artifacts, such as seams between adjacent boxes. I've added one suggestion for a further performance improvement by caching the Paint object to avoid re-allocating it on every paint call.

Comment on lines 8434 to 8436
Paint()
..color = color
..isAntiAlias = false,
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This is a good optimization. To further improve performance, consider caching the Paint object as a field in _RenderColoredBox to avoid allocating it on every paint call. The color can then be set on the cached Paint object before drawing.

For example:

class _RenderColoredBox extends RenderProxyBoxWithHitTestBehavior {
  // ...
  final Paint _paint = Paint()..isAntiAlias = false;

  @override
  void paint(PaintingContext context, Offset offset) {
    // ...
    if (size > Size.zero) {
      _paint.color = color;
      context.canvas.drawRect(offset & size, _paint);
    }
    // ...
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I really wonder if there is a performance benefit here in real life or not. After seeing #171194 it always makes me nervous. Fine as-is though.

Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

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

Hi @definev, thanks for the PR. Could you add a test to make sure this change does not get regressed?

@definev
Copy link
Contributor Author

definev commented Sep 27, 2025

Hi @victorsanni, I created the test. Feel free to let me know if you’d like me to write more tests for it. This is my first time contributing to Flutter, thank you so much ☺️

@definev definev requested a review from victorsanni September 27, 2025 08:19
Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

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

This golden test in the rfw package is failing with the changes in this PR.

@definev
Copy link
Contributor Author

definev commented Sep 29, 2025

I think that’s the expected behavior since it changes the way ColoredBox is rendered. The next step I should take is to either regenerate all the golden tests or declare this as a breaking change that may affect existing golden tests? cc: @victorsanni
Screenshot 2025-09-30 at 01 56 11

@definev
Copy link
Contributor Author

definev commented Oct 5, 2025

@victorsanni @dkwingsmt Are there any new updates for me to do?

Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

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

LGTM awaiting review from someone more knowledgeable about the subject such as @dkwingsmt.

For the failing customer test, the process is to disable it in a separate PR which will land before this one, then re-enable it after this PR lands while approving the new goldens. I can open a PR to do that.

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍 . I would guess that we were notting getting much benefit from setting isAntiAlias to true in this case, but I'm interested to see if the Google tests have any failures. We should watch out for any failures that appear to have benefitted from antialiasing.

And +1 to @dkwingsmt reviewing this as well.

Comment on lines 8440 to 8443
context.canvas.drawRect(offset & size, Paint()..color = color);
_paint.color = color;
context.canvas.drawRect(offset & size, _paint);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you instantiate the Paint here instead of reusing it each time? I avoid try to avoid this pattern after seeing #171194, even though that should be fixed by now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, that my initial approach to. Seeing Gemini suggest reuse paint object so i change to fit it comment :-) Let reverse that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Comment on lines 8434 to 8436
Paint()
..color = color
..isAntiAlias = false,
Copy link
Contributor

Choose a reason for hiding this comment

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

I really wonder if there is a performance benefit here in real life or not. After seeing #171194 it always makes me nervous. Fine as-is though.

@dkwingsmt
Copy link
Contributor

dkwingsmt commented Oct 7, 2025

Thanks for the nomination, although I wouldn't call myself an expert at all. :)

I played with this change locally and observed that there are visual changes to all ColoredBoxes, as expected. The edges are no longer as clear.
image

Even if we think this change is too small to notice or even healthy for having a clearer border, it's bound to break millions of golden tests. The impact is far too great. I don't think we can justify this breakage.

It might be better to expose the isAntiAlias as a parameter and keep the current behavior default. I'm not sure how viable it is, since the parameter might need to be propagated to some other widgets, such as Container. But it's definitely better than breakage like this.

@justinmc
Copy link
Contributor

justinmc commented Oct 7, 2025

Good find @dkwingsmt, I was worried something like that might happen. +1 to your recommendation of exploring exposing isAntiAlias.

@definev
Copy link
Contributor Author

definev commented Oct 8, 2025

I think the effect should apply to all ColoredBox widgets since they depend on each other. For example, placing one anti-aliased ColoredBox between two non-anti-aliased ones still causes the visual bug to appear.

We could introduce a new static variable in ColoredBox, called defaultIsAntiAlias, which would be set to true by default. However, users could set it to false if they prefer crisp borders.

If we still want to expose it, let add a 'bool? isAntiAlias' and set it to defaultIsAntiAlias if null.

@dkwingsmt
Copy link
Contributor

dkwingsmt commented Oct 8, 2025

I think the effect should apply to all ColoredBox widgets since they depend on each other. For example, placing one anti-aliased ColoredBox between two non-anti-aliased ones still causes the visual bug to appear.

Turning off anti-alias has many down sides, such as artifacts during rotation or zooming animation. Notice the borders in the following examples:

image
Screen.Recording.2025-10-08.at.9.39.31.AM.mp4

It should be up to the developers to decide if they really want to use, or need, the non-antialias version. In general, the antialias version should be more widely applicable.

@definev definev force-pushed the colored_box_optimization branch from 65319cd to e63e299 Compare October 9, 2025 06:27
@definev
Copy link
Contributor Author

definev commented Oct 9, 2025

Agree! I’ve updated the code based on your comment, exposing isAntiAlias in ColoredBox.
One small detail I observed in the SwiftUI framework is that they also use antiAlias, but they don’t have the same visual bug we encountered. Apparently, Flutter on mobile doesn’t have that issue either, so I think it’s related to the engine layer. The current solution is to expose isAntiAlias in ColoredBox.

Note: The stripe is still visible in SwiftUI, but it’s much thinner than in Flutter and only appears when rotating the child.

Screen.Recording.2025-10-09.at.12.14.23.mov
Screen.Recording.2025-10-09.at.12.13.53.mov
SwiftUI Flutter
Screenshot 2025-10-09 at 18 32 33 Screenshot 2025-10-09 at 18 38 24

}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Color>('color', color));
properties.add(DiagnosticsProperty<bool?>('isAntiAlias', isAntiAlias));
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe defaultValue: true?

Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't fixed?

Copy link
Contributor Author

@definev definev Oct 14, 2025

Choose a reason for hiding this comment

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

I already fixed it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I set default to true on constructor

@definev
Copy link
Contributor Author

definev commented Oct 13, 2025

@dkwingsmt i added the test but i don't know how to make it generate new golden test image and the CI is failing i don't know why. I follow the Writing-a-golden-file-test-for-package-flutter.md but seem i don't need to edit ci.yaml file

@dkwingsmt
Copy link
Contributor

The ci.yaml validation failure is simply due to the PR base being too old. I've updated it with the latest master. The golden file will be generated once all checks are green. Let's see how it goes. Thank you.

Comment on lines 330 to 331
/// The [ColoredBox.isAntiAlias] property.
///
Copy link
Contributor

Choose a reason for hiding this comment

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

The macro already has the first paragraph.

Suggested change
/// The [ColoredBox.isAntiAlias] property.
///

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done ✅

@definev definev requested a review from dkwingsmt October 14, 2025 07:42
@justinmc
Copy link
Contributor

@definev Looks like there are still analyzer failures FYI.

@definev
Copy link
Contributor Author

definev commented Oct 15, 2025

I will check on that

@definev
Copy link
Contributor Author

definev commented Oct 15, 2025

I’ve fixed the format, but I haven’t found a way to resolve the Mac framework_tests_impeller and tree-status issues yet.
One more question - I saw the flutter/goldens repository. Do I need to upload the golden test images before merging the PR into master?

@victorsanni
Copy link
Contributor

I’ve fixed the format, but I haven’t found a way to resolve the Mac framework_tests_impeller and tree-status issues yet.

Those are infra issues unrelated to this PR.

One more question - I saw the flutter/goldens repository. Do I need to upload the golden test images before merging the PR into master?

No, adding a golden test using matchesGoldenFile is sufficient. A contributor with commit access will then go ahead to triage the golden images in the flutter gold tool.

@flutter-dashboard
Copy link

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 #176073 at sha 04ad4ed

@dkwingsmt
Copy link
Contributor

LGTM. Thank you for the contribution!

@justinmc justinmc added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 28, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 28, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Oct 28, 2025

autosubmit label was removed for flutter/flutter/176073, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR.

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 2, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Nov 2, 2025
Merged via the queue into flutter:master with commit 7efa2ae Nov 2, 2025
77 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 2, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 4, 2025
reidbaker pushed a commit to AbdeMohlbi/flutter that referenced this pull request Dec 10, 2025
This PR fixed visual bug when placing multiple `ColoredBox`s together.
(Fixes flutter#176028)

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [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.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[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

---------

Co-authored-by: Victor Sanni <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels. will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ColoredBox create unwanted strip when placed close together due to the framework assuming isAntiAlias ​​= true

4 participants