-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ios_platform_view] more precision when determine if a clip rrect is necessary #38965
Merged
auto-submit
merged 3 commits into
flutter:main
from
cyanglaz:platform_view_cliprrect_fix
Jan 18, 2023
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,20 +32,52 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree { | |
} | ||
@end | ||
|
||
// Determines if the final `clipBounds` from a clipRect/clipRRect/clipPath mutator contains the | ||
// Determines if the `clip_rect` from a clipRect mutator contains the | ||
// `platformview_boundingrect`. | ||
// | ||
// `clip_bounds` is the bounding rect of the rect/rrect/path in the clipRect/clipRRect/clipPath | ||
// mutator. This rect is in its own coordinate space. The rect needs to be transformed by | ||
// `clip_rect` is in its own coordinate space. The rect needs to be transformed by | ||
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. | ||
// | ||
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate | ||
// space where the PlatformView is displayed. | ||
static bool ClipBoundsContainsPlatformViewBoundingRect(const SkRect& clip_bounds, | ||
const SkRect& platformview_boundingrect, | ||
const SkMatrix& transform_matrix) { | ||
SkRect transforme_clip_bounds = transform_matrix.mapRect(clip_bounds); | ||
return transforme_clip_bounds.contains(platformview_boundingrect); | ||
static bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect, | ||
const SkRect& platformview_boundingrect, | ||
const SkMatrix& transform_matrix) { | ||
SkRect transformed_rect = transform_matrix.mapRect(clip_rect); | ||
return transformed_rect.contains(platformview_boundingrect); | ||
} | ||
|
||
// Determines if the `clipRRect` from a clipRRect mutator contains the | ||
// `platformview_boundingrect`. | ||
// | ||
// `clip_rrect` is in its own coordinate space. The rrect needs to be transformed by | ||
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed. | ||
// | ||
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate | ||
// space where the PlatformView is displayed. | ||
static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, | ||
const SkRect& platformview_boundingrect, | ||
const SkMatrix& transform_matrix) { | ||
SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner); | ||
SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner); | ||
SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner); | ||
SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner); | ||
SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x()); | ||
SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y()); | ||
SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x()); | ||
SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y()); | ||
SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x()); | ||
SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y()); | ||
SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x()); | ||
SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y()); | ||
SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect()); | ||
SkRRect transformed_rrect; | ||
SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y}, | ||
{transformed_upper_right_x, transformed_upper_right_y}, | ||
{transformed_lower_right_x, transformed_lower_right_y}, | ||
{transformed_lower_left_x, transformed_lower_left_y}}; | ||
transformed_rrect.setRectRadii(transformed_clip_rect, corners); | ||
return transformed_rrect.contains(platformview_boundingrect); | ||
} | ||
|
||
namespace flutter { | ||
|
@@ -450,28 +482,27 @@ static bool ClipBoundsContainsPlatformViewBoundingRect(const SkRect& clip_bounds | |
break; | ||
} | ||
case kClipRect: { | ||
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetRect(), bounding_rect, | ||
transformMatrix)) { | ||
if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), bounding_rect, | ||
transformMatrix)) { | ||
break; | ||
} | ||
[maskView clipRect:(*iter)->GetRect() matrix:transformMatrix]; | ||
clipView.maskView = maskView; | ||
break; | ||
} | ||
case kClipRRect: { | ||
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetRRect().getBounds(), | ||
bounding_rect, transformMatrix)) { | ||
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), bounding_rect, | ||
transformMatrix)) { | ||
break; | ||
} | ||
[maskView clipRRect:(*iter)->GetRRect() matrix:transformMatrix]; | ||
clipView.maskView = maskView; | ||
break; | ||
} | ||
case kClipPath: { | ||
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetPath().getBounds(), | ||
bounding_rect, transformMatrix)) { | ||
break; | ||
} | ||
// TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is probably a hard geometry problem. but i bet most clipping actions are just simple shapes like RRect |
||
// rect. See `ClipRRectContainsPlatformViewBoundingRect`. | ||
// https://github.com/flutter/flutter/issues/118650 | ||
[maskView clipPath:(*iter)->GetPath() matrix:transformMatrix]; | ||
clipView.maskView = maskView; | ||
break; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+24.5 KB
...enariosUITests/golden_platform_view_large_cliprrect_iPhone 8_16.0_simulator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+26.6 KB
...golden_platform_view_large_cliprrect_with_transform_iPhone 8_16.0_simulator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i assume this
contains
actually take its radii into consideration (rather than just checking rectangular bounds)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it does. the new scenario app test covers it. The new unit test also covered it. I had to use (-1, -1) as the origin for the clipRRect with a 1 radius to avoid clipping the PlatformView at (0, 0) origin.