Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from 1 commit
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
Next Next commit
[ios][platform_view]use cashapelayer as the backing layer for mask view
  • Loading branch information
hellohuanlin committed May 24, 2024
commit 4e5bb14e6df3d7e9b0db0a75d0f4ebbec5da73ee
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,12 @@ @interface FlutterClippingMaskView ()
// information about screen scale.
@property(nonatomic) CATransform3D reverseScreenScale;

- (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;
- (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;

@end

@implementation FlutterClippingMaskView {
std::vector<fml::CFRef<CGPathRef>> paths_;
CGMutablePathRef pathSoFar_;
}

- (instancetype)initWithFrame:(CGRect)frame {
Expand All @@ -271,15 +271,32 @@ - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = UIColor.clearColor;
_reverseScreenScale = CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1);
pathSoFar_ = CGPathCreateMutable();
}
return self;
}

+ (Class)layerClass {
return [CAShapeLayer class];
}

- (CAShapeLayer *)shapeLayer {
return (CAShapeLayer *)self.layer;
}

- (void)reset {
paths_.clear();
CGPathRelease(pathSoFar_);
pathSoFar_ = CGPathCreateMutable();
[self shapeLayer].path = nil;
[self setNeedsDisplay];
}


- (void)dealloc {
CGPathRelease(pathSoFar_);
[super dealloc];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jmagman fyi potentially code conflict with your ARC migration PRs

}

// In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added
// this view as a subview of the ChildClippingView.
// This results this view blocking touch events on the ChildClippingView.
Expand All @@ -289,28 +306,13 @@ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
return NO;
}

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);

// For mask view, only the alpha channel is used.
CGContextSetAlpha(context, 1);

for (size_t i = 0; i < paths_.size(); i++) {
CGContextAddPath(context, paths_.at(i));
CGContextClip(context);
}
CGContextFillRect(context, rect);
CGContextRestoreGState(context);
}

- (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix {
CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRect);
CGPathRef path = CGPathCreateWithRect(clipRect, nil);
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]);
[self addTransformedPath:path matrix:matrixInPoints];
}

- (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
Expand Down Expand Up @@ -379,7 +381,7 @@ - (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
// TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated that
// the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard edge
// clipping on iOS.
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
[self addTransformedPath:pathRef matrix:matrixInPoints];
}

- (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
Expand Down Expand Up @@ -444,15 +446,15 @@ - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
// The `matrix` is based on the physical pixels, convert it to UIKit points.
CATransform3D matrixInPoints =
CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
[self addTransformedPath:pathRef matrix:matrixInPoints];
}

- (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
- (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
CGAffineTransform affine =
CGAffineTransformMake(matrix.m11, matrix.m12, matrix.m21, matrix.m22, matrix.m41, matrix.m42);
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(path, &affine);
CGPathAddPath(pathSoFar_, &affine, path);
[self shapeLayer].path = pathSoFar_;
CGPathRelease(path);
return fml::CFRef<CGPathRef>(transformedPath);
}

@end
Expand Down