Skip to content

Add ShapeBorder hit test fast paths - #187962

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
bernaferrari:hit-test
Jul 30, 2026
Merged

auto-submit[bot] merged 3 commits into
flutter:masterfrom
bernaferrari:hit-test

Conversation

@bernaferrari

@bernaferrari bernaferrari commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Sequence to #108648 (4 year delay).

This adds a bool hitTest that makes code much faster by not using path. 4 years ago, the speed-up was 17%. Interaction happens less often than painting, but still seems like it is worth patching it up.

image ChatGPT Image Jun 13, 2026, 02_25_20 AM

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 12, 2026
@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Jun 12, 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 a hitTest method to ShapeBorder and its subclasses to optimize hit testing by avoiding path creation, and updates ShapeDecoration.hitTest to delegate to this new method. Feedback points out that the textDirection != null assertion in BoxBorder.hitTest should be removed, as BoxBorder's outer path does not depend on text direction and this assertion would cause runtime failures in debug mode when hit testing without a text direction.

Comment thread packages/flutter/lib/src/painting/box_border.dart
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 12, 2026
@bernaferrari bernaferrari added the CICD Run CI/CD label Jun 18, 2026
@Piinks
Piinks requested a review from dkwingsmt June 23, 2026 22:10
@Piinks

Piinks commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Excellent PR artifacts. 💯 😜

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

Generally LGTM. Thank you for the followup!

Should we optimize _CompoundBorder as well?


test('ShapeBorder.hitTest matches getOuterPath for primitive shapes', () {
const rect = Rect.fromLTWH(0.0, 0.0, 120.0, 80.0);
const positions = <Offset>[

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.

Can we add negative tests?

Also having two lists here seem pretty hard to maintain. Can you wrap subtest parameters into a tuple or a data class?

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.

The list is not related to the other list, it is basically a collection of points + a collection of shapes, if I use a tuple it would be more limiting. Do you agree?

@bernaferrari bernaferrari Jul 20, 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.

image

I added some comments for what each thing means, hopefully it is more clear?

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.

Good idea! That works, thank you!

@bernaferrari

Copy link
Copy Markdown
Contributor Author

Thanks. I forgot _CompoundBorder existed. Pushed.

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

LGTM. Thank you!

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 20, 2026
@bernaferrari

Copy link
Copy Markdown
Contributor Author

That autosubmit is very optimistic. Let's see if Google testing passes 😂 4 years ago there were like 100 tests that broke but they were minor pixel anti-alias. Let's see what happens now.

@dkwingsmt

Copy link
Copy Markdown
Contributor

Sometimes I apply autosubmit because I can be notified when they found an error :)

@Piinks

Piinks commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Sometimes I apply autosubmit because I can be notified when they found an error :)

++ 😁

@auto-submit

auto-submit Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/187962, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 21, 2026
@bernaferrari

Copy link
Copy Markdown
Contributor Author

Here we go. Good luck.

}

@override
bool hitTest(Rect rect, Offset position, {TextDirection? textDirection}) {

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.

At least one of the Google tests are failing because someone implements BoxBorder. That may be the case for the other classes that received hitTest methods too, I didn't look through all of them. Is there a way we can land this without a hard API breaking change?

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 I can make hitTest optional and then do something like return shape.hitTest?.(Offset.zero & size, position, textDirection: textDirection) ?? shape.getOuterPath(Offset.zero & size, textDirection: textDirection).contains(position); it is not pretty and not ideal, but will avoid being breaking. But you would loose the performance improvements in Google.

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.

Update: Dart doesn’t support optional virtual methods and the alternatives would require runtime type checks + extensions (which Flutter style avoids). I don’t see a clean way to preserve polymorphic fast paths without breaking existing implements ShapeBorder/implements BoxBorder classes.

I guess now it is up to you again, shall we do a breaking change? Hopefully it is easy for you on the Google side. There shouldn't be much surprises. I can write the breaking guide/etc but you need to tell me if you want this change in first place.

@dkwingsmt dkwingsmt Jul 29, 2026 •

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 is exactly one use case of implements BoxBorder in Google's codebase and it seems to me that it can be replaced by extends BoxRender without any problems. I've started a full run and I'll come back with the result.

Also I've searched throught Github and the only place that BoxBorder is implemented is in the mix package, which I think will not be broken by new properties.

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.

All tests have passed. I'll discuss with @justinmc to land the change.

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 30, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jul 30, 2026
Merged via the queue into flutter:master with commit 7027945 Jul 30, 2026
22 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 30, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Aug 9, 2026
…12401)

Manual roll Flutter from 2757a77a73df to e52f01c920ad (47 revisions)

Manual roll requested by [email protected]

flutter/flutter@2757a77...e52f01c

2026-07-31 [email protected] [Impeller] Execute PipelineCompileQueue jobs in the order that they were added (flutter/flutter#190262)
2026-07-31 [email protected] Roll Packages from 7d17fc8 to 5351d8c (5 revisions) (flutter/flutter#190351)
2026-07-31 [email protected] Roll Skia from dcbd015c9646 to 7ef86a5b0eb9 (4 revisions) (flutter/flutter#190347)
2026-07-31 [email protected] [Impeller] Do not acquire an unneeded image in KHRSwapchainVK if the swapchain must be recreated due to a size change (flutter/flutter#190116)
2026-07-31 [email protected] Remove the --enable-serial-gc engine flag (flutter/flutter#190310)
2026-07-31 [email protected] Migrate platform_channel_swift example to material_ui (flutter/flutter#190308)
2026-07-31 [email protected] macOS: Set static text accessibility role for read-only text fields (flutter/flutter#190330)
2026-07-31 [email protected] Roll Dart SDK from 96f49fc43f59 to c3acfc2479f6 (1 revision) (flutter/flutter#190336)
2026-07-31 [email protected] Roll Skia from 07f08414dd66 to dcbd015c9646 (1 revision) (flutter/flutter#190333)
2026-07-31 [email protected] [web] Autofill all AutofillGroup fields in semantics mode (flutter/flutter#187108)
2026-07-31 [email protected] iOS: Configure test task runner thread at display QoS (flutter/flutter#190283)
2026-07-31 [email protected] Roll Skia from a1109355de78 to 07f08414dd66 (5 revisions) (flutter/flutter#190328)
2026-07-31 [email protected] Support reduceMotion accessibility feature in MediaQuery (flutter/flutter#190287)
2026-07-30 [email protected] Roll Dart SDK from 43f7de5f4977 to 96f49fc43f59 (4 revisions) (flutter/flutter#190312)
2026-07-30 [email protected] fix: text selection two handles directionality. (flutter/flutter#179928)
2026-07-30 [email protected] Add java/gradle check when gradle crashes (flutter/flutter#189997)
2026-07-30 [email protected] [Impeller] Add filterQuality support to ImageFilter.shader (flutter/flutter#188544)
2026-07-30 [email protected] [flutter/flutter] Migrate multiple_windows example to material_ui (flutter/flutter#190313)
2026-07-30 [email protected] Roll Skia from 50cf67910462 to a1109355de78 (6 revisions) (flutter/flutter#190306)
2026-07-30 [email protected] Migrate swift xctests to Swift testing tests (flutter/flutter#187801)
2026-07-30 [email protected] Migrates the platform_channel example to material_ui (flutter/flutter#190253)
2026-07-30 [email protected] iOS: Drop unnecessary @mainactor from VSyncClientTests (flutter/flutter#190285)
2026-07-30 [email protected] Add nullptr check to isOpaque (flutter/flutter#189796)
2026-07-30 [email protected] [Flutter GPU] Bind uniforms and textures by cached reflection index (flutter/flutter#189820)
2026-07-30 [email protected] Migrate layers example to material_ui (flutter/flutter#190237)
2026-07-30 [email protected] Add `ShapeBorder` hit test fast paths (flutter/flutter#187962)
2026-07-30 [email protected] ci: mac-must-wait part duex (flutter/flutter#190295)
2026-07-30 [email protected] Roll Skia from 491301f393d1 to 50cf67910462 (3 revisions) (flutter/flutter#190294)
2026-07-30 [email protected] Roll Packages from dd11626 to 7d17fc8 (1 revision) (flutter/flutter#190293)
2026-07-30 [email protected] Roll Skia from 177de1940bf2 to 491301f393d1 (1 revision) (flutter/flutter#190279)
2026-07-30 [email protected] Roll Skia from b8bda91f02db to 177de1940bf2 (5 revisions) (flutter/flutter#190272)
2026-07-30 [email protected] Roll Fuchsia Linux SDK from J8rVTlBnjnUpuHYk3... to _J8wM3kyQpLN9wvRD... (flutter/flutter#190273)
2026-07-30 [email protected] Roll Skia from 78afc18c9ba0 to b8bda91f02db (3 revisions) (flutter/flutter#190268)
2026-07-30 [email protected] Revert: Split the platform and cpuArch part of TargetPlatform (flutter/flutter#190258)
2026-07-30 [email protected] Return null from RenderProxyBoxMixin.computeDryBaseline when the child has no baseline (flutter/flutter#189723)
2026-07-30 [email protected] Roll Skia from 6fea713d32ec to 78afc18c9ba0 (4 revisions) (flutter/flutter#190257)
2026-07-30 [email protected] Roll pub packages (flutter/flutter#190259)
2026-07-29 [email protected] [cross imports] Check examples cross imports (flutter/flutter#187662)
2026-07-29 [email protected] ci: mac verify binaries still has to wait on linux_host_engine (flutter/flutter#190239)
2026-07-29 [email protected] Adds analytics to macos impeller opt in/out (flutter/flutter#190220)
2026-07-29 [email protected] Roll Skia from 0f35bba4945c to 6fea713d32ec (6 revisions) (flutter/flutter#190230)
2026-07-29 [email protected] iOS: Fix Swift warning in TracingTests (flutter/flutter#190203)
2026-07-29 [email protected] Convert all gradle-wrapper.properties in /dev to use distribution 'bin' (flutter/flutter#190226)
2026-07-29 [email protected] Roll Packages from 3e63635 to dd11626 (11 revisions) (flutter/flutter#190216)
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD framework flutter/packages/flutter repository. See also f: labels.

Projects

Development

Successfully merging this pull request may close these issues.

4 participants