-
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
Use a single mask view to clip platform view #20050
Use a single mask view to clip platform view #20050
Conversation
5e49efb
to
db33eae
Compare
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat. Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
Outdated
Show resolved
Hide resolved
@@ -16,6 +16,32 @@ | |||
#include "flutter/shell/platform/darwin/ios/ios_context.h" | |||
#include "third_party/skia/include/core/SkPictureRecorder.h" | |||
|
|||
// A UIView acts as a clipping mask for the |ChildClippingView|. | |||
// | |||
// On |DrawRect:|, this view performs a series of clipping operations and sets the alpha channel |
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.
should this interface contain the virtual drawRect
method?
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.
This View is an OBJC class, drawRect is inherited from the UIView. So I don't think any virtual keyword is necessary here.
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.
sg. do you where I can read about the doc format? I'm not sure what |DrawRect:|
means, but I can see it means what you described.
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.
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 mean the notation. It reads like a class to me, but I’m not sure what the colon symbol is used for.
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.
ah you are right, let me fix that
…s_Internal.h Co-authored-by: Emmanuel Garcia <egarciad@google.com>
…laz/engine into platform_view_mutation_single_view
@gaaclarke Chris mentioned that this PR is causing the scenario app UI test to fail even though there's not difference in pixels. (as reported by external image comparison tools). Would you mind taking a look? |
@gaaclarke I update committed the new screenshot into this PR. You should see that their pixels are identical. Maybe we should make the thread holder bigger? |
return NO; | ||
- (CGRect)getCGRectFromSkRect:(const SkRect&)clipSkRect { | ||
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, | ||
clipSkRect.fBottom - clipSkRect.fTop); | ||
} | ||
|
||
@end |
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.
gpus_ReturnNotPermittedKillClient crash on iOS 62403 Can you help us have a look,please?
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.
The issue doesn't seem to related to this PR?
@blasten @gaaclarke The new screenshots are identical with the old golden images. I think our image diff logic is just more strict than regular image diff tools. Let's update the golden images here? |
I'm fine updating the golden images if they are acceptable. I talked to @cyanglaz offline and I suspect this has to do with different handling of transparent / semi-transparent pixels. |
As discussed offline, @cyanglaz will add unit tests |
// Create embedded view params | ||
flutter::MutatorsStack stack; | ||
// Layer tree always pushes a screen scale factor to the stack | ||
SkMatrix screenScaleMatrix = SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); |
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'm not sure what [UIScreen mainScreen].scale
would be when executed on LUCI. Maybe pick a constant value?
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.
It has to be screenScale because the CompositeEmbeddedView
uses screenScale to add a reverse scale matrix to the final transform matrix.
// Create embedded view params | ||
flutter::MutatorsStack stack; | ||
// Layer tree always pushes a screen scale factor to the stack | ||
SkMatrix screenScaleMatrix = SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); |
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.
ditto
// Push a rotate matrix | ||
SkMatrix rotateMatrix; | ||
rotateMatrix.setRotate(10); | ||
stack.PushTransform(rotateMatrix); |
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.
This is fine, but what about PushClipPath
?
Line 133 in c57aff1
void PushClipPath(const SkPath& path); |
Should that be in a separate unit test?
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.
To test the clipping, we will probably have to render the view into an image, then check the pixels (sort like a screenshot). I think the scenario tests already covered all the clippings, it is kind of redundant.
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.
LGTM % nits
@blasten Added unit tests for clipping. PTAL. |
SkMatrix screenScaleMatrix = | ||
SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); | ||
stack.PushTransform(screenScaleMatrix); |
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.
nit: does it need this to test clip specifically?
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.
yes. as the clip paths will need to get scaled as well.
if (CGRectContainsPoint(insideClipping, point)) { | ||
XCTAssertEqual(alpha, 255); | ||
} else { | ||
XCTAssertLessThan(alpha, 255); |
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.
is there an exact value for the alpha?
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.
Thanks for adding the tests! LGTM
* 8a0e30b Roll Dart SDK from 2d98d25e71c3 to c59cdee365b9 (1 revision) (flutter/engine#20200) * 0519052 Roll Dart SDK from c59cdee365b9 to ad9c73cb3270 (1 revision) (flutter/engine#20201) * fc5b777 Roll Skia from 7225788b9070 to 8e77631a80f0 (8 revisions) (flutter/engine#20184) * cb8dfdb Roll Skia from 8e77631a80f0 to a6df9da28963 (17 revisions) (flutter/engine#20202) * ea811fc Roll Dart SDK from ad9c73cb3270 to 0f0e04ec3afa (3 revisions) (flutter/engine#20204) * 02d71d6 Use a single mask view to clip iOS platform view (flutter/engine#20050)
* 8a0e30b Roll Dart SDK from 2d98d25e71c3 to c59cdee365b9 (1 revision) (flutter/engine#20200) * 0519052 Roll Dart SDK from c59cdee365b9 to ad9c73cb3270 (1 revision) (flutter/engine#20201) * fc5b777 Roll Skia from 7225788b9070 to 8e77631a80f0 (8 revisions) (flutter/engine#20184) * cb8dfdb Roll Skia from 8e77631a80f0 to a6df9da28963 (17 revisions) (flutter/engine#20202) * ea811fc Roll Dart SDK from ad9c73cb3270 to 0f0e04ec3afa (3 revisions) (flutter/engine#20204) * 02d71d6 Use a single mask view to clip iOS platform view (flutter/engine#20050)
* Update 1.20.2 engine to use Dart 2.9.1 * Use a single mask view to clip iOS platform view (#20050) * Moved to RMSE for image comparison to account for slight variations in golden image tests (#19658) Moved to RMSE for image comparison to account for slight variations in golden image production. (also fixed a flakey test) Co-authored-by: Chris Yang <ychris@google.com> Co-authored-by: gaaclarke <30870216+gaaclarke@users.noreply.github.com>
* 8a0e30b Roll Dart SDK from 2d98d25e71c3 to c59cdee365b9 (1 revision) (flutter/engine#20200) * 0519052 Roll Dart SDK from c59cdee365b9 to ad9c73cb3270 (1 revision) (flutter/engine#20201) * fc5b777 Roll Skia from 7225788b9070 to 8e77631a80f0 (8 revisions) (flutter/engine#20184) * cb8dfdb Roll Skia from 8e77631a80f0 to a6df9da28963 (17 revisions) (flutter/engine#20202) * ea811fc Roll Dart SDK from ad9c73cb3270 to 0f0e04ec3afa (3 revisions) (flutter/engine#20204) * 02d71d6 Use a single mask view to clip iOS platform view (flutter/engine#20050)
Description
We used to use a logic that stacking
ChildClippingView
to achieve clippings for the iOS platform view. (Introduced in aa9b3a1)This approach has a drawback that the
ChildClippingView
needs to be detached and re-attached to the flutter view whenever there is a change to the mutator stack.This can cause a serious bug. (explained in the issue below)
This PR uses a single mask view to do the clipping. So we always only have one
ChildClippingView
.In
drawRect:
of the mask view, it fills the final clipping area with an opaque color. And theChildClippingView
replaces its alpha channel with the mask view's alpha channel by setting themaskView
property.https://developer.apple.com/documentation/uikit/uiview/1622557-maskview?language=objc
Related Issues
Fixes flutter/flutter#46167
Tests
There is no behavior change, but we need to make sure the scenario app passes the tests so we know the mutations still works.
I'm not sure how do we test the behavior of flutter/flutter#46167. I have manually tested to make sure it works now.
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]
). This will ensure a smooth and quick review process.Breaking Change
Did any tests fail when you ran them? Please read handling breaking changes.