33// found in the LICENSE file.
44
55#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterMutatorView.h"
6- #include " flutter/fml/logging.h"
76
87#include < QuartzCore/QuartzCore.h>
8+
99#include < vector>
1010
11+ #include " flutter/fml/logging.h"
12+ #include " flutter/shell/platform/embedder/embedder.h"
13+
1114@interface FlutterMutatorView () {
1215 // / Each of these views clips to a CGPathRef. These views, if present,
1316 // / are nested (first is child of FlutterMutatorView and last is parent of
@@ -85,6 +88,28 @@ FlutterRect ToFlutterRect(const CGRect& rect) {
8588 };
8689}
8790
91+ using MutationVector = std::vector<FlutterPlatformViewMutation>;
92+
93+ // / Returns a vector of FlutterPlatformViewMutation object pointers associated with a platform view.
94+ // / The transforms sent from the engine include a transform from logical to physical coordinates.
95+ // / Since Cocoa deals only in logical points, this function prepends a scale transform that scales
96+ // / back from physical to logical coordinates to compensate.
97+ MutationVector MutationsForPlatformView (const FlutterPlatformView* view, float scale) {
98+ MutationVector mutations;
99+ mutations.reserve (view->mutations_count + 1 );
100+ mutations.push_back ({
101+ .type = kFlutterPlatformViewMutationTypeTransformation ,
102+ .transformation {
103+ .scaleX = 1.0 / scale,
104+ .scaleY = 1.0 / scale,
105+ },
106+ });
107+ for (size_t i = 0 ; i < view->mutations_count ; ++i) {
108+ mutations.push_back (*view->mutations [i]);
109+ }
110+ return mutations;
111+ }
112+
88113// / Returns whether the point is inside ellipse with given radius (centered at 0, 0).
89114bool PointInsideEllipse (const CGPoint& point, const FlutterSize& radius) {
90115 return (point.x * point.x ) / (radius.width * radius.width ) +
@@ -219,27 +244,29 @@ - (BOOL)isFlipped {
219244 return YES ;
220245}
221246
247+ // / Returns the scale factor to translate logical pixels to physical pixels for this view.
248+ - (CGFloat)contentsScale {
249+ return self.superview != nil ? self.superview .layer .contentsScale : 1.0 ;
250+ }
251+
222252// / Whenever possible view will be clipped using layer bounds.
223253// / If clipping to path is needed, CAShapeLayer(s) will be used as mask.
224254// / Clipping to round rect only clips to path if round corners are intersected.
225255- (void )applyFlutterLayer : (const FlutterLayer*)layer {
226- CGFloat scale = self.superview != nil ? self.superview .layer .contentsScale : 1.0 ;
227-
228- // Initial transform to compensate for scale factor. This is needed because all
229- // cocoa coordinates are logical but Flutter will send the physical to logical
230- // transform in mutations.
231- CATransform3D transform = CATransform3DMakeScale (1.0 / scale, 1.0 / scale, 1 );
256+ CGFloat scale = [self contentsScale ];
257+ auto mutations = MutationsForPlatformView (layer->platform_view , scale);
232258
233259 // Platform view transform after applying all transformation mutations.
234- CATransform3D finalTransform = transform;
235- for (size_t i = 0 ; i < layer->platform_view ->mutations_count ; ++i) {
236- auto mutation = layer->platform_view ->mutations [i];
237- if (mutation->type == kFlutterPlatformViewMutationTypeTransformation ) {
238- finalTransform =
239- CATransform3DConcat (ToCATransform3D (mutation->transformation ), finalTransform);
260+ CATransform3D finalTransform = CATransform3DIdentity;
261+ for (auto mutation : mutations) {
262+ if (mutation.type == kFlutterPlatformViewMutationTypeTransformation ) {
263+ CATransform3D mutationTransform = ToCATransform3D (mutation.transformation );
264+ finalTransform = CATransform3DConcat (mutationTransform, finalTransform);
240265 }
241266 }
242267
268+ // Compute the untransformed bounding rect for the platform view in logical pixels.
269+ // FlutterLayer.size is in physical pixels but Cocoa uses logical points.
243270 CGRect untransformedBoundingRect =
244271 CGRectMake (0 , 0 , layer->size .width / scale, layer->size .height / scale);
245272
@@ -257,22 +284,23 @@ - (void)applyFlutterLayer:(const FlutterLayer*)layer {
257284 // Gathered pairs of rounded rect in local coordinates + appropriate transform.
258285 std::vector<std::pair<FlutterRoundedRect, CGAffineTransform>> roundedRects;
259286
260- for (size_t i = 0 ; i < layer->platform_view ->mutations_count ; ++i) {
261- auto mutation = layer->platform_view ->mutations [i];
262- if (mutation->type == kFlutterPlatformViewMutationTypeTransformation ) {
263- transform = CATransform3DConcat (ToCATransform3D (mutation->transformation ), transform);
264- } else if (mutation->type == kFlutterPlatformViewMutationTypeClipRect ) {
265- CGRect rect = CGRectApplyAffineTransform (FromFlutterRect (mutation->clip_rect ),
287+ // Create the initial transform.
288+ CATransform3D transform = CATransform3DIdentity;
289+ for (auto mutation : mutations) {
290+ if (mutation.type == kFlutterPlatformViewMutationTypeTransformation ) {
291+ transform = CATransform3DConcat (ToCATransform3D (mutation.transformation ), transform);
292+ } else if (mutation.type == kFlutterPlatformViewMutationTypeClipRect ) {
293+ CGRect rect = CGRectApplyAffineTransform (FromFlutterRect (mutation.clip_rect ),
266294 CATransform3DGetAffineTransform (transform));
267295 masterClip = CGRectIntersection (rect, masterClip);
268- } else if (mutation-> type == kFlutterPlatformViewMutationTypeClipRoundedRect ) {
296+ } else if (mutation. type == kFlutterPlatformViewMutationTypeClipRoundedRect ) {
269297 CGAffineTransform affineTransform = CATransform3DGetAffineTransform (transform);
270- roundedRects.push_back (std::make_pair (mutation-> clip_rounded_rect , affineTransform));
271- CGRect rect = CGRectApplyAffineTransform (FromFlutterRect (mutation-> clip_rounded_rect .rect ),
298+ roundedRects.push_back (std::make_pair (mutation. clip_rounded_rect , affineTransform));
299+ CGRect rect = CGRectApplyAffineTransform (FromFlutterRect (mutation. clip_rounded_rect .rect ),
272300 affineTransform);
273301 masterClip = CGRectIntersection (rect, masterClip);
274- } else if (mutation-> type == kFlutterPlatformViewMutationTypeOpacity ) {
275- self.layer .opacity *= mutation-> opacity ;
302+ } else if (mutation. type == kFlutterPlatformViewMutationTypeOpacity ) {
303+ self.layer .opacity *= mutation. opacity ;
276304 }
277305 }
278306
0 commit comments