Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// found in the LICENSE file.

#include <Metal/Metal.h>
#include <QuartzCore/QuartzCore.h>
#import <UIKit/UIGestureRecognizerSubclass.h>
#include "third_party/skia/include/core/SkRRect.h"

#include <list>
#include <map>
Expand Down Expand Up @@ -476,6 +478,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
clipView.maskView = nil;
}
CGFloat screenScale = [UIScreen mainScreen].scale;
std::optional<SkRect> clip_rect;
auto iter = mutators_stack.Begin();
while (iter != mutators_stack.End()) {
switch ((*iter)->GetType()) {
Expand All @@ -488,9 +491,8 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
transformMatrix)) {
break;
}
ClipViewSetMaskView(clipView);
[(FlutterClippingMaskView*)clipView.maskView clipRect:(*iter)->GetRect()
matrix:transformMatrix];
clip_rect = transformMatrix.mapRect((*iter)->GetRect());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might not be correct, its possible that a skew transform makes a rect non rectangular, we'd need to check that. Also I think once we hit a case where there is a non-clipRect, we'd need to stop using clipsToBounds.

Copy link
Contributor

Choose a reason for hiding this comment

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

There is a mapRect variant that tells you if it was rect-to-rect, I think you have to use bool mapRect(src,dst) to get this info. Alternately, SkMatrix has a getter to ask if it preserves rects.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh nice, thank you!

// TODO: If there is already a clip rect, compute a new clip rect with an intersection.
break;
}
case kClipRRect: {
Expand Down Expand Up @@ -571,11 +573,32 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
// Thus, this translate needs to be reversed so the platform view can layout at the correct
// offset.
//
// Note that the transforms are not applied to the clipping paths because clipping paths happen on
// Note that the transforms are not applied to the clipping paths because clipping paths happen
// on
// the mask view, whose origin is always (0,0) to the flutter_view.
transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y);

embedded_view.layer.transform = flutter::GetCATransform3DFromSkMatrix(transformMatrix);

if (clip_rect.has_value()) {
// The fully transformed clip rect includes the screen scale, while the clipView frame
// will not.
SkRect new_rect =
SkRect::MakeXYWH(clip_rect->x() / screenScale, clip_rect->y() / screenScale,
clip_rect->width() / screenScale, clip_rect->height() / screenScale);
CGRect clipRect = flutter::GetCGRectFromSkRect(new_rect);
CGRect intersected = CGRectIntersection(clipRect, clipView.frame);

// The rect intersection may result in a different origin. However, changing the frame
// origin will result in UIView being incorrectly positioned. To account for this, we
// apply a corresponding offset to the child UIView.
CGPoint origin_offset = CGPointMake(intersected.origin.x - clipView.frame.origin.x,
intersected.origin.y - clipView.frame.origin.y);
for (auto i = 0u; i < [clipView.subviews count]; i++) {
clipView.subviews[i].frame.origin = origin_offset;
}
clipView.clipsToBounds = YES;
}
}

// Composite the PlatformView with `view_id`.
Expand Down Expand Up @@ -907,6 +930,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
FML_DCHECK([[NSThread currentThread] isMainThread]);
FML_DCHECK(!catransaction_added_);
[CATransaction begin];
[CATransaction setDisableActions:YES];
catransaction_added_ = true;
}

Expand Down