3
3
// found in the LICENSE file.
4
4
5
5
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterMutatorView.h"
6
- #include " flutter/fml/logging.h"
7
6
8
7
#include < QuartzCore/QuartzCore.h>
8
+
9
9
#include < vector>
10
10
11
+ #include " flutter/fml/logging.h"
12
+ #include " flutter/shell/platform/embedder/embedder.h"
13
+
11
14
@interface FlutterMutatorView () {
12
15
// / Each of these views clips to a CGPathRef. These views, if present,
13
16
// / are nested (first is child of FlutterMutatorView and last is parent of
@@ -85,6 +88,28 @@ FlutterRect ToFlutterRect(const CGRect& rect) {
85
88
};
86
89
}
87
90
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
+
88
113
// / Returns whether the point is inside ellipse with given radius (centered at 0, 0).
89
114
bool PointInsideEllipse (const CGPoint& point, const FlutterSize& radius) {
90
115
return (point.x * point.x ) / (radius.width * radius.width ) +
@@ -219,27 +244,29 @@ - (BOOL)isFlipped {
219
244
return YES ;
220
245
}
221
246
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
+
222
252
// / Whenever possible view will be clipped using layer bounds.
223
253
// / If clipping to path is needed, CAShapeLayer(s) will be used as mask.
224
254
// / Clipping to round rect only clips to path if round corners are intersected.
225
255
- (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);
232
258
233
259
// 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);
240
265
}
241
266
}
242
267
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.
243
270
CGRect untransformedBoundingRect =
244
271
CGRectMake (0 , 0 , layer->size .width / scale, layer->size .height / scale);
245
272
@@ -257,22 +284,23 @@ - (void)applyFlutterLayer:(const FlutterLayer*)layer {
257
284
// Gathered pairs of rounded rect in local coordinates + appropriate transform.
258
285
std::vector<std::pair<FlutterRoundedRect, CGAffineTransform>> roundedRects;
259
286
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 ),
266
294
CATransform3DGetAffineTransform (transform));
267
295
masterClip = CGRectIntersection (rect, masterClip);
268
- } else if (mutation-> type == kFlutterPlatformViewMutationTypeClipRoundedRect ) {
296
+ } else if (mutation. type == kFlutterPlatformViewMutationTypeClipRoundedRect ) {
269
297
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 ),
272
300
affineTransform);
273
301
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 ;
276
304
}
277
305
}
278
306
0 commit comments