From 853cbd6759d6b17ae1d6422ea9932a6824a800d3 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 16 May 2019 16:33:07 -0700 Subject: [PATCH 01/56] get the stack ready --- flow/embedded_views.cc | 38 +++++++++++++ flow/embedded_views.h | 54 ++++++++++++++++++- flow/layers/clip_rect_layer.cc | 2 + .../framework/Source/FlutterPlatformViews.mm | 7 +-- .../Source/FlutterPlatformViews_Internal.h | 2 +- shell/platform/darwin/ios/ios_surface_gl.mm | 2 +- .../darwin/ios/ios_surface_software.mm | 2 +- 7 files changed, 99 insertions(+), 8 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index e37a837deec0e..6d79d68e87bbf 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -6,7 +6,45 @@ namespace flutter { +ExternalViewEmbedder::ExternalViewEmbedder() + :transfromStack_(std::unique_ptr(new FlutterEmbededViewTransformStack())) { +}; + bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; }; + +void ExternalViewEmbedder::clipRect(const SkRect& rect) { + transfromStack_.get()->pushClipRect(rect); +}; + +void ExternalViewEmbedder::popTransform() { + transfromStack_.get()->pop(); +} + +std::vector::iterator ExternalViewEmbedder::getTransformStackIterator() { + return transfromStack_.get()->begin(); +} + + +#pragma mark - FlutterEmbededViewTransformStack + +void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { + FlutterEmbededViewTransformElement element = FlutterEmbededViewTransformElement(); + element.setType(clip_rect); + element.setRect(rect); + vector_.push_back(element); +}; + + +void FlutterEmbededViewTransformStack::pop() { + vector_.pop_back(); +} + +std::vector::iterator FlutterEmbededViewTransformStack::begin() { + return vector_.begin(); +} + + +#pragma mark - FlutterEmbededViewTransformElement } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index e7b34f753bc38..c98906a1d6925 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -11,6 +11,8 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "third_party/skia/include/core/SkRect.h" namespace flutter { @@ -20,12 +22,15 @@ class EmbeddedViewParams { SkSize sizePoints; }; +class FlutterEmbededViewTransformStack; +class FlutterEmbededViewTransformElement; + // This is only used on iOS when running in a non headless mode, // in this case ExternalViewEmbedder is a reference to the // FlutterPlatformViewsController which is owned by FlutterViewController. class ExternalViewEmbedder { public: - ExternalViewEmbedder() = default; + ExternalViewEmbedder(); virtual void BeginFrame(SkISize frame_size) = 0; @@ -42,7 +47,52 @@ class ExternalViewEmbedder { virtual ~ExternalViewEmbedder() = default; FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); -}; + +#pragma mark - transforms + void clipRect(const SkRect& rect); + void clipRRect(const SkRRect& rect); + + void popTransform(); + std::vector::iterator getTransformStackIterator(); +private: + std::unique_ptr transfromStack_; +}; // ExternalViewEmbedder + +class FlutterEmbededViewTransformStack { + +public: + void pushClipRect(const SkRect& rect); + void pushClipRRect(const SkRRect& rect); + void pushClipPath(const SkPath& rect); + + // Removes the `FlutterEmbededViewTransformElement` on the top of the stack and destroys it. + void pop(); + + // Returns the iterator points to the bottom of the stack. + std::vector::iterator begin(); +private: + + std::vector vector_; +}; //FlutterEmbededViewTransformStack + +enum FlutterEmbededViewTransformType {clip_rect, clip_rrect}; + +class FlutterEmbededViewTransformElement { +public: + + void setType(const FlutterEmbededViewTransformType type) {type_ = type;} + void setRect(const SkRect &rect){rect_ = rect;} + + FlutterEmbededViewTransformType type() {return type_;} + SkRect rect() {return rect_;} + SkRRect rrect() {return rrect_;} + +private: + + FlutterEmbededViewTransformType type_; + SkRect rect_; + SkRRect rrect_; +}; // FlutterEmbededViewTransformElement } // namespace flutter diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 3f41d8768c6b3..eab165dee3413 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,6 +50,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); + context.view_embedder->clipRect(clip_rect_); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); } @@ -57,6 +58,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } + context.view_embedder->popTransform(); } } // namespace flutter diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index d912e0d136f22..3d03575874da5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -182,9 +182,10 @@ return canvases; } -SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView( - int view_id, - const flutter::EmbeddedViewParams& params) { +SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView + (int view_id, + const flutter::EmbeddedViewParams& params, + const std::vector::iterator &transformIterator) { // TODO(amirh): assert that this is running on the platform thread once we support the iOS // embedded views thread configuration. // TODO(amirh): do nothing if the params didn't change. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 5361fced0cc10..9028d709526b1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -70,7 +70,7 @@ class FlutterPlatformViewsController { std::vector GetCurrentCanvases(); - SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); + SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params, const std::vector::iterator &transformIterator); // Discards all platform views instances and auxiliary resources. void Reset(); diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index f9279cc5116fe..632594856e9d8 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -105,7 +105,7 @@ const flutter::EmbeddedViewParams& params) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); - return platform_views_controller->CompositeEmbeddedView(view_id, params); + return platform_views_controller->CompositeEmbeddedView(view_id, params, getTransformStackIterator()); } bool IOSSurfaceGL::SubmitFrame(GrContext* context) { diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index 32cb5a2bbeef1..a891fae3e1d14 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -157,7 +157,7 @@ const flutter::EmbeddedViewParams& params) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); - return platform_views_controller->CompositeEmbeddedView(view_id, params); + return platform_views_controller->CompositeEmbeddedView(view_id, params, getTransformStackIterator()); } bool IOSSurfaceSoftware::SubmitFrame(GrContext* context) { From 72042cf70fe5cbfa14eef8611fb16f1396344fed Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 17 May 2019 11:50:27 -0700 Subject: [PATCH 02/56] draft --- flow/embedded_views.cc | 9 ++- flow/embedded_views.h | 13 ++-- flow/layers/platform_view_layer.cc | 4 +- .../framework/Source/FlutterPlatformViews.mm | 63 +++++++++++++++---- .../Source/FlutterPlatformViews_Internal.h | 3 +- shell/platform/darwin/ios/ios_surface_gl.mm | 2 +- .../darwin/ios/ios_surface_software.mm | 2 +- 7 files changed, 74 insertions(+), 22 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 6d79d68e87bbf..94d0044106477 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -22,10 +22,14 @@ void ExternalViewEmbedder::popTransform() { transfromStack_.get()->pop(); } -std::vector::iterator ExternalViewEmbedder::getTransformStackIterator() { +std::vector::iterator ExternalViewEmbedder::getTransformStackIteratorBegin() { return transfromStack_.get()->begin(); } +std::vector::iterator ExternalViewEmbedder::getTransformStackIteratorEnd() { + return transfromStack_.get()->end(); +} + #pragma mark - FlutterEmbededViewTransformStack @@ -45,6 +49,9 @@ std::vector::iterator FlutterEmbededViewTran return vector_.begin(); } +std::vector::iterator FlutterEmbededViewTransformStack::end() { + return vector_.end(); +} #pragma mark - FlutterEmbededViewTransformElement } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index c98906a1d6925..cdaf121813fcf 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -16,15 +16,17 @@ namespace flutter { +class FlutterEmbededViewTransformStack; +class FlutterEmbededViewTransformElement; + class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; + std::vector::iterator transformIteratorBegin; + std::vector::iterator transformIteratorEnd; }; -class FlutterEmbededViewTransformStack; -class FlutterEmbededViewTransformElement; - // This is only used on iOS when running in a non headless mode, // in this case ExternalViewEmbedder is a reference to the // FlutterPlatformViewsController which is owned by FlutterViewController. @@ -53,7 +55,8 @@ class ExternalViewEmbedder { void clipRRect(const SkRRect& rect); void popTransform(); - std::vector::iterator getTransformStackIterator(); + std::vector::iterator getTransformStackIteratorBegin(); + std::vector::iterator getTransformStackIteratorEnd(); private: std::unique_ptr transfromStack_; }; // ExternalViewEmbedder @@ -70,6 +73,8 @@ class FlutterEmbededViewTransformStack { // Returns the iterator points to the bottom of the stack. std::vector::iterator begin(); + // Returns the iterator points to the top of the stack. + std::vector::iterator end(); private: std::vector vector_; diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 0c9741c474cdf..8b18dd76f2bad 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,7 +34,9 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - + params.transformIteratorBegin = context.view_embedder->getTransformStackIteratorBegin(); + params.transformIteratorEnd = context.view_embedder->getTransformStackIteratorEnd(); + SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); context.leaf_nodes_canvas = canvas; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3d03575874da5..4a0bc157a2fbb 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -16,6 +16,16 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" +// A set of utility methods to handle transforms in platform views. +static UIView* getClippedRectView(CGRect frame, CGRect clipRect) { + UIView *view = [[UIView alloc] initWithFrame:frame]; + UIBezierPath *path = [UIBezierPath bezierPathWithRect:clipRect]; + CAShapeLayer *clip = [[CAShapeLayer alloc] init]; + clip.path = path.CGPath; + view.layer.mask = clip; + return view; +} + namespace flutter { void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) { @@ -91,6 +101,7 @@ touch_interceptors_[viewId] = fml::scoped_nsobject([touch_interceptor retain]); + root_views_[viewId] = fml::scoped_nsobject([touch_interceptor retain]); result(nil); } @@ -184,8 +195,8 @@ SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView (int view_id, - const flutter::EmbeddedViewParams& params, - const std::vector::iterator &transformIterator) { + const flutter::EmbeddedViewParams& params) { + // TODO(amirh): assert that this is running on the platform thread once we support the iOS // embedded views thread configuration. // TODO(amirh): do nothing if the params didn't change. @@ -194,8 +205,23 @@ CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale, params.sizePoints.width(), params.sizePoints.height()); + //==== + UIView *root = nil; + std::vector::iterator iter = params.transformIteratorBegin; + if (iter != params.transformIteratorEnd) { + SkRect clipSkRect = iter->rect(); + CGRect clipRect = CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight-clipSkRect.fLeft, clipSkRect.fBottom-clipSkRect.fTop); + root = getClippedRectView(rect, clipRect); + ++iter; + } + + //==== UIView* touch_interceptor = touch_interceptors_[view_id].get(); - [touch_interceptor setFrame:rect]; + if (root) { + root_views_[view_id] = fml::scoped_nsobject([root retain]); + } else { + touch_interceptor.frame = rect; + } return picture_recorders_[view_id]->getRecordingCanvas(); } @@ -242,15 +268,19 @@ for (size_t i = 0; i < composition_order_.size(); i++) { int view_id = composition_order_[i]; - UIView* intercepter = touch_interceptors_[view_id].get(); + UIView* root = root_views_[view_id].get(); UIView* overlay = overlays_[view_id]->overlay_view; - FML_CHECK(intercepter.superview == overlay.superview); - - if (intercepter.superview == flutter_view) { - [flutter_view bringSubviewToFront:intercepter]; + FML_CHECK(root.superview == overlay.superview); + if (root.superview == flutter_view) { + [flutter_view bringSubviewToFront:root]; [flutter_view bringSubviewToFront:overlay]; } else { - [flutter_view addSubview:intercepter]; + [flutter_view addSubview:root]; + if (![root isKindOfClass:[FlutterTouchInterceptingView class]]) { + [touch_interceptor setFrame:root.bounds]; + [root addSubview:touch_interceptor]; + } + NSLog(@"root view added"); [flutter_view addSubview:overlay]; } @@ -269,10 +299,11 @@ for (int64_t view_id : active_composition_order_) { if (composition_order_set.find(view_id) == composition_order_set.end()) { - if (touch_interceptors_.find(view_id) == touch_interceptors_.end()) { + if (root_views_.find(view_id) == root_views_.end()) { continue; } - [touch_interceptors_[view_id].get() removeFromSuperview]; + UIView *root = root_views_[view_id].get(); + [root removeFromSuperview]; [overlays_[view_id]->overlay_view.get() removeFromSuperview]; } } @@ -284,10 +315,11 @@ } for (int64_t viewId : views_to_dispose_) { - UIView* touch_interceptor = touch_interceptors_[viewId].get(); - [touch_interceptor removeFromSuperview]; + UIView* root_view = root_views_[viewId].get(); + [root_view removeFromSuperview]; views_.erase(viewId); touch_interceptors_.erase(viewId); + root_views_.erase(viewId); overlays_.erase(viewId); } views_to_dispose_.clear(); @@ -507,3 +539,8 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer return YES; } @end + + + + + diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 9028d709526b1..d46f15b145e22 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -70,7 +70,7 @@ class FlutterPlatformViewsController { std::vector GetCurrentCanvases(); - SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params, const std::vector::iterator &transformIterator); + SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); // Discards all platform views instances and auxiliary resources. void Reset(); @@ -88,6 +88,7 @@ class FlutterPlatformViewsController { std::map>> factories_; std::map>> views_; std::map> touch_interceptors_; + std::map> root_views_; std::map> overlays_; // The GrContext that is currently used by all of the overlay surfaces. // We track this to know when the GrContext for the Flutter app has changed diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index 632594856e9d8..f9279cc5116fe 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -105,7 +105,7 @@ const flutter::EmbeddedViewParams& params) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); - return platform_views_controller->CompositeEmbeddedView(view_id, params, getTransformStackIterator()); + return platform_views_controller->CompositeEmbeddedView(view_id, params); } bool IOSSurfaceGL::SubmitFrame(GrContext* context) { diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index a891fae3e1d14..32cb5a2bbeef1 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -157,7 +157,7 @@ const flutter::EmbeddedViewParams& params) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); - return platform_views_controller->CompositeEmbeddedView(view_id, params, getTransformStackIterator()); + return platform_views_controller->CompositeEmbeddedView(view_id, params); } bool IOSSurfaceSoftware::SubmitFrame(GrContext* context) { From 8489c085488b706af614e2c774f4304d4053f9ca Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 17 May 2019 13:19:55 -0700 Subject: [PATCH 03/56] Do nothing if the params didn't change when compositing platform views. --- flow/embedded_views.h | 5 +++++ .../ios/framework/Source/FlutterPlatformViews.mm | 10 +++++++++- .../framework/Source/FlutterPlatformViews_Internal.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index e7b34f753bc38..cb8137e664034 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -18,6 +18,11 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; + + friend bool operator==(const EmbeddedViewParams &lhs, const EmbeddedViewParams &rhs) { + return lhs.offsetPixels == rhs.offsetPixels + &&lhs.sizePoints == rhs.sizePoints; + } }; // This is only used on iOS when running in a non headless mode, diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index d912e0d136f22..6a93c2949c758 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -187,7 +187,13 @@ const flutter::EmbeddedViewParams& params) { // TODO(amirh): assert that this is running on the platform thread once we support the iOS // embedded views thread configuration. - // TODO(amirh): do nothing if the params didn't change. + + // Do nothing if the params didn't change. + if (composite_params_.count(view_id) == 1 && composite_params_[view_id] == params) { + return picture_recorders_[view_id]->getRecordingCanvas(); + } + composite_params_[view_id] = params; + CGFloat screenScale = [[UIScreen mainScreen] scale]; CGRect rect = CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale, @@ -209,6 +215,7 @@ composition_order_.clear(); active_composition_order_.clear(); picture_recorders_.clear(); + composite_params_.clear(); } bool FlutterPlatformViewsController::SubmitFrame(bool gl_rendering, @@ -288,6 +295,7 @@ views_.erase(viewId); touch_interceptors_.erase(viewId); overlays_.erase(viewId); + composite_params_.erase(viewId); } views_to_dispose_.clear(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 5361fced0cc10..6b0f30e6fed80 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -88,6 +88,7 @@ class FlutterPlatformViewsController { std::map>> factories_; std::map>> views_; std::map> touch_interceptors_; + std::map composite_params_; std::map> overlays_; // The GrContext that is currently used by all of the overlay surfaces. // We track this to know when the GrContext for the Flutter app has changed From f7d7aaa6c02f60a7e27b26447f4e333dbfb77f95 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 17 May 2019 13:49:52 -0700 Subject: [PATCH 04/56] draft --- flow/embedded_views.h | 4 +++- .../framework/Source/FlutterPlatformViews.mm | 20 +++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index b2100c82f8502..dbc2c960b6e48 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -28,7 +28,9 @@ class EmbeddedViewParams { friend bool operator==(const EmbeddedViewParams &lhs, const EmbeddedViewParams &rhs) { return lhs.offsetPixels == rhs.offsetPixels - &&lhs.sizePoints == rhs.sizePoints; + &&lhs.sizePoints == rhs.sizePoints + &&lhs.transformIteratorBegin == rhs.transformIteratorBegin + &&lhs.transformIteratorEnd == rhs.transformIteratorEnd; } }; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 66653ce7a2fd8..9ca33b2fe150f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -18,6 +18,8 @@ // A set of utility methods to handle transforms in platform views. static UIView* getClippedRectView(CGRect frame, CGRect clipRect) { + NSLog(@"view frame %@", @(frame)); + NSLog(@"clip rect %@", @(clipRect)); UIView *view = [[UIView alloc] initWithFrame:frame]; UIBezierPath *path = [UIBezierPath bezierPathWithRect:clipRect]; CAShapeLayer *clip = [[CAShapeLayer alloc] init]; @@ -211,17 +213,15 @@ CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale, params.sizePoints.width(), params.sizePoints.height()); - //==== - UIView *root = nil; - std::vector::iterator iter = params.transformIteratorBegin; - if (iter != params.transformIteratorEnd) { - SkRect clipSkRect = iter->rect(); - CGRect clipRect = CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight-clipSkRect.fLeft, clipSkRect.fBottom-clipSkRect.fTop); - root = getClippedRectView(rect, clipRect); - ++iter; - } + UIView *root = nil; + std::vector::iterator iter = params.transformIteratorBegin; + if (iter != params.transformIteratorEnd) { + SkRect clipSkRect = iter->rect(); + CGRect clipRect = CGRectMake(clipSkRect.fLeft-rect.origin.x, clipSkRect.fTop-rect.origin.y, clipSkRect.fRight-clipSkRect.fLeft, clipSkRect.fBottom-clipSkRect.fTop); + root = getClippedRectView(rect, clipRect); + ++iter; + } - //==== UIView* touch_interceptor = touch_interceptors_[view_id].get(); if (root) { root_views_[view_id] = fml::scoped_nsobject([root retain]); From c0741b2684ef243d277d583164fd3f55be4ebeb4 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 17 May 2019 17:23:13 -0700 Subject: [PATCH 05/56] draft --- flow/embedded_views.cc | 20 +----------- flow/embedded_views.h | 28 ++++++++++------- flow/layers/clip_rect_layer.cc | 4 +-- flow/layers/platform_view_layer.cc | 5 ++- .../framework/Source/FlutterPlatformViews.mm | 31 +++++++++++++++---- 5 files changed, 47 insertions(+), 41 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 94d0044106477..a7c379b04be86 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -7,30 +7,13 @@ namespace flutter { ExternalViewEmbedder::ExternalViewEmbedder() - :transfromStack_(std::unique_ptr(new FlutterEmbededViewTransformStack())) { + :transformStack(std::make_shared()) { }; bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; }; -void ExternalViewEmbedder::clipRect(const SkRect& rect) { - transfromStack_.get()->pushClipRect(rect); -}; - -void ExternalViewEmbedder::popTransform() { - transfromStack_.get()->pop(); -} - -std::vector::iterator ExternalViewEmbedder::getTransformStackIteratorBegin() { - return transfromStack_.get()->begin(); -} - -std::vector::iterator ExternalViewEmbedder::getTransformStackIteratorEnd() { - return transfromStack_.get()->end(); -} - - #pragma mark - FlutterEmbededViewTransformStack void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { @@ -53,5 +36,4 @@ std::vector::iterator FlutterEmbededViewTran return vector_.end(); } -#pragma mark - FlutterEmbededViewTransformElement } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index dbc2c960b6e48..2c67ac4f1624c 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -23,14 +23,12 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - std::vector::iterator transformIteratorBegin; - std::vector::iterator transformIteratorEnd; + std::shared_ptr transformStack; friend bool operator==(const EmbeddedViewParams &lhs, const EmbeddedViewParams &rhs) { return lhs.offsetPixels == rhs.offsetPixels &&lhs.sizePoints == rhs.sizePoints - &&lhs.transformIteratorBegin == rhs.transformIteratorBegin - &&lhs.transformIteratorEnd == rhs.transformIteratorEnd; + &&lhs.transformStack == rhs.transformStack; } }; @@ -58,14 +56,8 @@ class ExternalViewEmbedder { FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); #pragma mark - transforms - void clipRect(const SkRect& rect); - void clipRRect(const SkRRect& rect); + std::shared_ptr transformStack; - void popTransform(); - std::vector::iterator getTransformStackIteratorBegin(); - std::vector::iterator getTransformStackIteratorEnd(); -private: - std::unique_ptr transfromStack_; }; // ExternalViewEmbedder class FlutterEmbededViewTransformStack { @@ -82,6 +74,10 @@ class FlutterEmbededViewTransformStack { std::vector::iterator begin(); // Returns the iterator points to the top of the stack. std::vector::iterator end(); + + friend bool operator==(const FlutterEmbededViewTransformStack& lhs, const FlutterEmbededViewTransformStack& rhs) { + return lhs.vector_ == rhs.vector_; + } private: std::vector vector_; @@ -99,6 +95,16 @@ class FlutterEmbededViewTransformElement { SkRect rect() {return rect_;} SkRRect rrect() {return rrect_;} + friend bool operator==(const FlutterEmbededViewTransformElement& lhs, const FlutterEmbededViewTransformElement& rhs) { + if (lhs.type_ != rhs.type_) { + return false; + } + if (lhs.type_ == clip_rect && lhs.rect_ != rhs.rect_) { + return false; + } + return true; + } + private: FlutterEmbededViewTransformType type_; diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index eab165dee3413..54fd1563aa887 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,7 +50,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); - context.view_embedder->clipRect(clip_rect_); + context.view_embedder->transformStack->pushClipRect(clip_rect_); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); } @@ -58,7 +58,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - context.view_embedder->popTransform(); + context.view_embedder->transformStack->pop(); } } // namespace flutter diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 8b18dd76f2bad..e2f012df6d88d 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,9 +34,8 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - params.transformIteratorBegin = context.view_embedder->getTransformStackIteratorBegin(); - params.transformIteratorEnd = context.view_embedder->getTransformStackIteratorEnd(); - + params.transformStack = context.view_embedder->transformStack; + SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); context.leaf_nodes_canvas = canvas; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 9ca33b2fe150f..3022b23d66865 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -204,8 +204,10 @@ // Do nothing if the params didn't change. if (composite_params_.count(view_id) == 1 && composite_params_[view_id] == params) { + NSLog(@"not changed"); return picture_recorders_[view_id]->getRecordingCanvas(); } + NSLog(@"changed"); composite_params_[view_id] = params; CGFloat screenScale = [[UIScreen mainScreen] scale]; @@ -214,19 +216,36 @@ params.sizePoints.width(), params.sizePoints.height()); UIView *root = nil; - std::vector::iterator iter = params.transformIteratorBegin; - if (iter != params.transformIteratorEnd) { + std::vector::iterator iter = params.transformStack->end()-1; + if (iter != params.transformStack->begin()-1) { + UIView *view = root_views_[view_id].get(); + if ([view isKindOfClass:[FlutterTouchInterceptingView class]]) { + root = [[UIView alloc] initWithFrame:rect]; + root_views_[view_id] = fml::scoped_nsobject([root retain]); + } else { + root = view; + } + } + NSLog(@"root frame %@", @(root.frame)); + for (UIView *subview in root.subviews) { + [subview removeFromSuperview]; + [subview release]; + } + UIView *lastView = root; + while(iter != params.transformStack->begin()-1) { SkRect clipSkRect = iter->rect(); CGRect clipRect = CGRectMake(clipSkRect.fLeft-rect.origin.x, clipSkRect.fTop-rect.origin.y, clipSkRect.fRight-clipSkRect.fLeft, clipSkRect.fBottom-clipSkRect.fTop); - root = getClippedRectView(rect, clipRect); - ++iter; + UIView *view = getClippedRectView(lastView.bounds, clipRect); + [lastView addSubview:view]; + lastView = view; + --iter; } UIView* touch_interceptor = touch_interceptors_[view_id].get(); if (root) { - root_views_[view_id] = fml::scoped_nsobject([root retain]); [touch_interceptor setFrame:root.bounds]; - [root addSubview:touch_interceptor]; + [lastView addSubview:touch_interceptor]; + NSLog(@"transformed"); } else { touch_interceptor.frame = rect; } From 6e95d2655cf2db06c83ea1bfe9c41e5415cc29cc Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 23 May 2019 18:31:15 -0700 Subject: [PATCH 06/56] draft2 --- flow/embedded_views.cc | 19 +- flow/embedded_views.h | 70 ++++--- flow/layers/transform_layer.cc | 2 + .../framework/Source/FlutterPlatformViews.mm | 175 ++++++++++++------ .../Source/FlutterPlatformViews_Internal.h | 3 + 5 files changed, 179 insertions(+), 90 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index a7c379b04be86..3043e25f06234 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -7,8 +7,7 @@ namespace flutter { ExternalViewEmbedder::ExternalViewEmbedder() - :transformStack(std::make_shared()) { -}; + : transformStack(std::make_shared()){}; bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; @@ -17,22 +16,32 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { #pragma mark - FlutterEmbededViewTransformStack void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { - FlutterEmbededViewTransformElement element = FlutterEmbededViewTransformElement(); + FlutterEmbededViewTransformElement element = + FlutterEmbededViewTransformElement(); element.setType(clip_rect); element.setRect(rect); vector_.push_back(element); }; +void FlutterEmbededViewTransformStack::pushTransform(const SkMatrix& matrix) { + FlutterEmbededViewTransformElement element = + FlutterEmbededViewTransformElement(); + element.setType(transform); + element.setMatrix(matrix); + vector_.push_back(element); +}; void FlutterEmbededViewTransformStack::pop() { vector_.pop_back(); } -std::vector::iterator FlutterEmbededViewTransformStack::begin() { +std::vector::iterator +FlutterEmbededViewTransformStack::begin() { return vector_.begin(); } -std::vector::iterator FlutterEmbededViewTransformStack::end() { +std::vector::iterator +FlutterEmbededViewTransformStack::end() { return vector_.end(); } diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 2c67ac4f1624c..5710496661317 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -10,9 +10,9 @@ #include "flutter/fml/memory/ref_counted.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPoint.h" -#include "third_party/skia/include/core/SkSize.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkSize.h" namespace flutter { @@ -25,10 +25,11 @@ class EmbeddedViewParams { SkSize sizePoints; std::shared_ptr transformStack; - friend bool operator==(const EmbeddedViewParams &lhs, const EmbeddedViewParams &rhs) { - return lhs.offsetPixels == rhs.offsetPixels - &&lhs.sizePoints == rhs.sizePoints - &&lhs.transformStack == rhs.transformStack; + friend bool operator==(const EmbeddedViewParams& lhs, + const EmbeddedViewParams& rhs) { + return lhs.offsetPixels == rhs.offsetPixels && + lhs.sizePoints == rhs.sizePoints && + lhs.transformStack == rhs.transformStack; } }; @@ -58,16 +59,18 @@ class ExternalViewEmbedder { #pragma mark - transforms std::shared_ptr transformStack; -}; // ExternalViewEmbedder +}; // ExternalViewEmbedder class FlutterEmbededViewTransformStack { - -public: + public: void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rect); void pushClipPath(const SkPath& rect); - // Removes the `FlutterEmbededViewTransformElement` on the top of the stack and destroys it. + void pushTransform(const SkMatrix& matrix); + + // Removes the `FlutterEmbededViewTransformElement` on the top of the stack + // and destroys it. void pop(); // Returns the iterator points to the bottom of the stack. @@ -75,42 +78,57 @@ class FlutterEmbededViewTransformStack { // Returns the iterator points to the top of the stack. std::vector::iterator end(); - friend bool operator==(const FlutterEmbededViewTransformStack& lhs, const FlutterEmbededViewTransformStack& rhs) { + friend bool operator==(const FlutterEmbededViewTransformStack& lhs, + const FlutterEmbededViewTransformStack& rhs) { return lhs.vector_ == rhs.vector_; } -private: + private: std::vector vector_; -}; //FlutterEmbededViewTransformStack +}; // FlutterEmbededViewTransformStack -enum FlutterEmbededViewTransformType {clip_rect, clip_rrect}; +enum FlutterEmbededViewTransformType { + clip_rect, + clip_rrect, + clip_path, + transform +}; class FlutterEmbededViewTransformElement { -public: - - void setType(const FlutterEmbededViewTransformType type) {type_ = type;} - void setRect(const SkRect &rect){rect_ = rect;} + public: + void setType(const FlutterEmbededViewTransformType type) { type_ = type; } + void setRect(const SkRect& rect) { rect_ = rect; } + void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } - FlutterEmbededViewTransformType type() {return type_;} - SkRect rect() {return rect_;} - SkRRect rrect() {return rrect_;} + FlutterEmbededViewTransformType type() { return type_; } + SkRect rect() { return rect_; } + SkRRect rrect() { return rrect_; } + SkMatrix matrix() { return matrix_; } - friend bool operator==(const FlutterEmbededViewTransformElement& lhs, const FlutterEmbededViewTransformElement& rhs) { + friend bool operator==(const FlutterEmbededViewTransformElement& lhs, + const FlutterEmbededViewTransformElement& rhs) { if (lhs.type_ != rhs.type_) { return false; } - if (lhs.type_ == clip_rect && lhs.rect_ != rhs.rect_) { - return false; + if (lhs.type_ == clip_rect && lhs.rect_ == rhs.rect_) { + return true; } - return true; + if (lhs.type_ == transform && lhs.matrix_ == rhs.matrix_) { + return true; + } + return false; } -private: + bool isClipType() { + return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; + } + private: FlutterEmbededViewTransformType type_; SkRect rect_; SkRRect rrect_; -}; // FlutterEmbededViewTransformElement + SkMatrix matrix_; +}; // FlutterEmbededViewTransformElement } // namespace flutter diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 37d5b606258fe..c7a9bc8fbe5a2 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -66,7 +66,9 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); + context.view_embedder->transformStack->pushTransform(transform_); PaintChildren(context); + context.view_embedder->transformStack->pop(); } } // namespace flutter diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3022b23d66865..487584b1c145a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -16,16 +16,50 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -// A set of utility methods to handle transforms in platform views. -static UIView* getClippedRectView(CGRect frame, CGRect clipRect) { - NSLog(@"view frame %@", @(frame)); - NSLog(@"clip rect %@", @(clipRect)); - UIView *view = [[UIView alloc] initWithFrame:frame]; - UIBezierPath *path = [UIBezierPath bezierPathWithRect:clipRect]; - CAShapeLayer *clip = [[CAShapeLayer alloc] init]; +#pragma mark - Transforms Utils + +static void ClipRect(UIView* view, CGRect clipRect) { + UIBezierPath* path = [UIBezierPath bezierPathWithRect:clipRect]; + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; clip.path = path.CGPath; view.layer.mask = clip; - return view; +} + +static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { + // TODO TEST(cyanglaz): test perspective transform + CATransform3D transform = CATransform3DIdentity; + transform.m11 = matrix.getScaleX(); + transform.m21 = matrix.getSkewX(); + transform.m41 = matrix.getTranslateX(); + transform.m14 = matrix.getPerspX(); + + transform.m12 = matrix.getSkewY(); + transform.m22 = matrix.getScaleY(); + transform.m42 = matrix.getTranslateY(); + transform.m24 = matrix.getPerspY(); + + NSLog(@"========="); + + NSLog(@"%.2f %.2f %.2f\n%.2f %.2f %.2f\n%.2f %.2f %.2f\n", matrix.getScaleX(), matrix.getSkewX(), + matrix.getTranslateX(), matrix.getSkewY(), matrix.getScaleY(), matrix.getTranslateY(), + matrix.getPerspX(), matrix.getPerspY(), 1.0); + + NSLog(@"----------"); + + NSLog(@"%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n", + transform.m11, transform.m12, transform.m13, transform.m14, transform.m21, transform.m22, + transform.m23, transform.m24, transform.m31, transform.m32, transform.m33, transform.m34, + transform.m41, transform.m42, transform.m43, transform.m44); + NSLog(@"========="); + return transform; +} + +static void ReadyUIViewForTranslate(UIView* view) { + view.layer.transform = CATransform3DIdentity; + view.layer.anchorPoint = CGPointMake( + 0, 0); // Quartz's default anchor point is the center, we set it to (0,0) to match flow. + view.layer.position = CGPointMake(0, 0); // After changing the anchor point, the layer's position + // is changed, we need to reset it back to (0,0). } namespace flutter { @@ -195,60 +229,88 @@ return canvases; } -SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView - (int view_id, - const flutter::EmbeddedViewParams& params) { +void FlutterPlatformViewsController::CompositeWithParams( + int view_id, + const flutter::EmbeddedViewParams& params) { + UIView* touch_interceptor = touch_interceptors_[view_id].get(); + CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); + touch_interceptor.frame = frame; + UIView* lastView = touch_interceptor; + + ReadyUIViewForTranslate(lastView); + std::vector::iterator iter = params.transformStack->end() - 1; + // TODO(cyanglaz): figure out how to handle the root transform layer (2x, 2y) + bool hasMoreClipOperations = false; + while (iter != params.transformStack->begin()) { + switch (iter->type()) { + case transform: { + CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); + lastView.layer.transform = CATransform3DConcat(lastView.layer.transform, transform); + break; + } + case clip_rect: { + SkRect clipSkRect = iter->rect(); + CGRect clipRect = + CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, + clipSkRect.fBottom - clipSkRect.fTop); + UIView* view = lastView.superview; + // if we need more clips operations than last time, create a new view. + if (!view || view == flutter_view_.get()) { + [lastView removeFromSuperview]; + view = [[UIView alloc] initWithFrame:lastView.bounds]; + [view addSubview:lastView]; + hasMoreClipOperations = true; + } + ClipRect(view, clipRect); + lastView = view; + ReadyUIViewForTranslate(lastView); + break; + } + // TODO(cyanglaz): Add other clippings + case clip_rrect: { + break; + } + case clip_path: { + break; + } + } + --iter; + } + // If we have less cilp operations this time, remove unnecessary views. + // We skip this process if we have more clip operations this time. + // TODO TEST(cyanglaz): + if (!hasMoreClipOperations) { + UIView* superview = lastView.superview; + if (superview != flutter_view_.get()) { + [lastView removeFromSuperview]; + } + while (superview != flutter_view_.get()) { + UIView* superSuperView = superview.superview; + [superview removeFromSuperview]; + [superview release]; + superview = superSuperView; + } + } + + // If we have clips + if (lastView != touch_interceptor) { + root_views_[view_id] = fml::scoped_nsobject([lastView retain]); + } +} + +SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView( + int view_id, + const flutter::EmbeddedViewParams& params) { // TODO(amirh): assert that this is running on the platform thread once we support the iOS // embedded views thread configuration. // Do nothing if the params didn't change. if (composite_params_.count(view_id) == 1 && composite_params_[view_id] == params) { - NSLog(@"not changed"); return picture_recorders_[view_id]->getRecordingCanvas(); } - NSLog(@"changed"); composite_params_[view_id] = params; - - CGFloat screenScale = [[UIScreen mainScreen] scale]; - CGRect rect = - CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale, - params.sizePoints.width(), params.sizePoints.height()); - - UIView *root = nil; - std::vector::iterator iter = params.transformStack->end()-1; - if (iter != params.transformStack->begin()-1) { - UIView *view = root_views_[view_id].get(); - if ([view isKindOfClass:[FlutterTouchInterceptingView class]]) { - root = [[UIView alloc] initWithFrame:rect]; - root_views_[view_id] = fml::scoped_nsobject([root retain]); - } else { - root = view; - } - } - NSLog(@"root frame %@", @(root.frame)); - for (UIView *subview in root.subviews) { - [subview removeFromSuperview]; - [subview release]; - } - UIView *lastView = root; - while(iter != params.transformStack->begin()-1) { - SkRect clipSkRect = iter->rect(); - CGRect clipRect = CGRectMake(clipSkRect.fLeft-rect.origin.x, clipSkRect.fTop-rect.origin.y, clipSkRect.fRight-clipSkRect.fLeft, clipSkRect.fBottom-clipSkRect.fTop); - UIView *view = getClippedRectView(lastView.bounds, clipRect); - [lastView addSubview:view]; - lastView = view; - --iter; - } - - UIView* touch_interceptor = touch_interceptors_[view_id].get(); - if (root) { - [touch_interceptor setFrame:root.bounds]; - [lastView addSubview:touch_interceptor]; - NSLog(@"transformed"); - } else { - touch_interceptor.frame = rect; - } + CompositeWithParams(view_id, params); return picture_recorders_[view_id]->getRecordingCanvas(); } @@ -325,7 +387,7 @@ if (root_views_.find(view_id) == root_views_.end()) { continue; } - UIView *root = root_views_[view_id].get(); + UIView* root = root_views_[view_id].get(); [root removeFromSuperview]; [overlays_[view_id]->overlay_view.get() removeFromSuperview]; } @@ -563,8 +625,3 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer return YES; } @end - - - - - diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 4a8f03f628a27..6677f8b9f5d57 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -70,6 +70,8 @@ class FlutterPlatformViewsController { std::vector GetCurrentCanvases(); + void extracted(); + SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); // Discards all platform views instances and auxiliary resources. @@ -122,6 +124,7 @@ class FlutterPlatformViewsController { void EnsureGLOverlayInitialized(int64_t overlay_id, std::shared_ptr gl_context, GrContext* gr_context); + void CompositeWithParams(int view_id, const flutter::EmbeddedViewParams& params); FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); }; From a3e1d61682449c750d06428cd47e3733287b9bc5 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 28 May 2019 12:40:10 -0700 Subject: [PATCH 07/56] clip rrect --- flow/embedded_views.cc | 8 ++ flow/embedded_views.h | 4 + flow/layers/clip_rrect_layer.cc | 2 + .../framework/Source/FlutterPlatformViews.mm | 131 ++++++++++++++---- .../Source/FlutterPlatformViews_Internal.h | 2 - 5 files changed, 115 insertions(+), 32 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 3043e25f06234..b727c2368db0c 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -23,6 +23,14 @@ void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { vector_.push_back(element); }; +void FlutterEmbededViewTransformStack::pushClipRRect(const SkRRect& rrect) { + FlutterEmbededViewTransformElement element = + FlutterEmbededViewTransformElement(); + element.setType(clip_rrect); + element.setRRect(rrect); + vector_.push_back(element); +}; + void FlutterEmbededViewTransformStack::pushTransform(const SkMatrix& matrix) { FlutterEmbededViewTransformElement element = FlutterEmbededViewTransformElement(); diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 5710496661317..eccef51ed7b75 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -13,6 +13,7 @@ #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/core/SkPath.h" namespace flutter { @@ -98,11 +99,13 @@ class FlutterEmbededViewTransformElement { public: void setType(const FlutterEmbededViewTransformType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } + void setRRect(const SkRRect& rrect) { rrect_ = rrect; } void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } FlutterEmbededViewTransformType type() { return type_; } SkRect rect() { return rect_; } SkRRect rrect() { return rrect_; } + SkPath path() {return path_;} SkMatrix matrix() { return matrix_; } friend bool operator==(const FlutterEmbededViewTransformElement& lhs, @@ -127,6 +130,7 @@ class FlutterEmbededViewTransformElement { FlutterEmbededViewTransformType type_; SkRect rect_; SkRRect rrect_; + SkPath path_; SkMatrix matrix_; }; // FlutterEmbededViewTransformElement diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index d387f58b1dc72..34a2d0664581d 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -58,10 +58,12 @@ void ClipRRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); + context.view_embedder->transformStack->pushClipRRect(clip_rrect_); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } PaintChildren(context); + context.view_embedder->transformStack->pop(); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 487584b1c145a..bccb354497ce2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -18,11 +18,89 @@ #pragma mark - Transforms Utils -static void ClipRect(UIView* view, CGRect clipRect) { - UIBezierPath* path = [UIBezierPath bezierPathWithRect:clipRect]; +static CGRect GetCGRectFromSkRect(const SkRect &clipSkRect) { + return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, + clipSkRect.fBottom - clipSkRect.fTop); +} + +static void ClipRect(UIView* view, const SkRect &clipSkRect) { + CGRect clipRect = GetCGRectFromSkRect(clipSkRect); + CGPathRef pathRef = CGPathCreateWithRect(clipRect, nil); + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; + clip.path = pathRef; + view.layer.mask = clip; + CGPathRelease(pathRef); +} + +static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { + CGPathRef pathRef = nullptr; + switch (clipSkRRect.getType()) { + case SkRRect::kEmpty_Type: { + break; + } + case SkRRect::kRect_Type: { + ClipRect(view, clipSkRRect.rect()); + return; + } + case SkRRect::kOval_Type: + case SkRRect::kSimple_Type: { + CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); + pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), clipSkRRect.getSimpleRadii().y(), nil); + break; + } + case SkRRect::kNinePatch_Type: + case SkRRect::kComplex_Type: { + CGMutablePathRef mutablePathRef = CGPathCreateMutable(); + + // Complex types, we manually add cornors. + SkRect clipSkRect = clipSkRRect.rect(); + SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); + SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); + SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner); + SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner); + + // Start drawing RRect + // Move point to the top left cornor adding the top left radii's x. + CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop); + // Move point horizontally right to the top right cornor and add the top right curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight-topRightRadii.x(), clipSkRect.fTop); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, clipSkRect.fRight, clipSkRect.fTop+topRightRadii.y(), clipSkRect.fRight, clipSkRect.fTop+topRightRadii.y()); + // Move point vertically down to the bottom right cornor and add the bottom right curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom - bottomRightRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, clipSkRect.fRight-bottomRightRadii.x(), clipSkRect.fBottom, clipSkRect.fRight-bottomRightRadii.x(), clipSkRect.fBottom); + // Move point horizontally left to the bottom left cornor and add the bottom left curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft+bottomLeftRadii.x(), clipSkRect.fBottom); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, clipSkRect.fLeft, clipSkRect.fBottom-bottomLeftRadii.y(), clipSkRect.fLeft, clipSkRect.fBottom-bottomLeftRadii.y()); + // Move point vertically up to the top left cornor and add the top left curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop+topLeftRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop); + CGPathCloseSubpath(mutablePathRef); + + pathRef = mutablePathRef; + break; + } + } CAShapeLayer* clip = [[CAShapeLayer alloc] init]; - clip.path = path.CGPath; + clip.path = pathRef; view.layer.mask = clip; + CGPathRelease(pathRef); +} + +static void PerformClip(UIView *view, flutter::FlutterEmbededViewTransformType type, const SkRect &rect, const SkRRect &rrect, const SkPath &path) { + FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || type == flutter::clip_path); + // TODO(cyanglaz): Add other clippings + switch (type) { + case flutter::clip_rect: + ClipRect(view, rect); + break; + case flutter::clip_rrect: + ClipRRect(view, rrect); + break; + case flutter::clip_path: + break; + default: + break; + } } static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { @@ -37,20 +115,20 @@ static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { transform.m22 = matrix.getScaleY(); transform.m42 = matrix.getTranslateY(); transform.m24 = matrix.getPerspY(); - - NSLog(@"========="); - - NSLog(@"%.2f %.2f %.2f\n%.2f %.2f %.2f\n%.2f %.2f %.2f\n", matrix.getScaleX(), matrix.getSkewX(), - matrix.getTranslateX(), matrix.getSkewY(), matrix.getScaleY(), matrix.getTranslateY(), - matrix.getPerspX(), matrix.getPerspY(), 1.0); - - NSLog(@"----------"); - - NSLog(@"%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n", - transform.m11, transform.m12, transform.m13, transform.m14, transform.m21, transform.m22, - transform.m23, transform.m24, transform.m31, transform.m32, transform.m33, transform.m34, - transform.m41, transform.m42, transform.m43, transform.m44); - NSLog(@"========="); +// +// NSLog(@"========="); +// +// NSLog(@"%.2f %.2f %.2f\n%.2f %.2f %.2f\n%.2f %.2f %.2f\n", matrix.getScaleX(), matrix.getSkewX(), +// matrix.getTranslateX(), matrix.getSkewY(), matrix.getScaleY(), matrix.getTranslateY(), +// matrix.getPerspX(), matrix.getPerspY(), 1.0); +// +// NSLog(@"----------"); +// +// NSLog(@"%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n", +// transform.m11, transform.m12, transform.m13, transform.m14, transform.m21, transform.m22, +// transform.m23, transform.m24, transform.m31, transform.m32, transform.m33, transform.m34, +// transform.m41, transform.m42, transform.m43, transform.m44); +// NSLog(@"========="); return transform; } @@ -242,6 +320,7 @@ static void ReadyUIViewForTranslate(UIView* view) { std::vector::iterator iter = params.transformStack->end() - 1; // TODO(cyanglaz): figure out how to handle the root transform layer (2x, 2y) bool hasMoreClipOperations = false; + while (iter != params.transformStack->begin()) { switch (iter->type()) { case transform: { @@ -249,11 +328,9 @@ static void ReadyUIViewForTranslate(UIView* view) { lastView.layer.transform = CATransform3DConcat(lastView.layer.transform, transform); break; } - case clip_rect: { - SkRect clipSkRect = iter->rect(); - CGRect clipRect = - CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, - clipSkRect.fBottom - clipSkRect.fTop); + case clip_rect: + case clip_rrect: + case clip_path: { UIView* view = lastView.superview; // if we need more clips operations than last time, create a new view. if (!view || view == flutter_view_.get()) { @@ -262,18 +339,12 @@ static void ReadyUIViewForTranslate(UIView* view) { [view addSubview:lastView]; hasMoreClipOperations = true; } - ClipRect(view, clipRect); + PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); lastView = view; ReadyUIViewForTranslate(lastView); break; } - // TODO(cyanglaz): Add other clippings - case clip_rrect: { - break; - } - case clip_path: { - break; - } + // TODO(cyanglaz): Add other clippings } --iter; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 6677f8b9f5d57..ad4ef76989ff1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -70,8 +70,6 @@ class FlutterPlatformViewsController { std::vector GetCurrentCanvases(); - void extracted(); - SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); // Discards all platform views instances and auxiliary resources. From 4cf9f8a405b5e7d273bb39b2b24e92ba98b570d3 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 28 May 2019 16:31:12 -0700 Subject: [PATCH 08/56] typo fix --- flow/embedded_views.h | 4 ++-- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index eccef51ed7b75..1946d068de87c 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -65,8 +65,8 @@ class ExternalViewEmbedder { class FlutterEmbededViewTransformStack { public: void pushClipRect(const SkRect& rect); - void pushClipRRect(const SkRRect& rect); - void pushClipPath(const SkPath& rect); + void pushClipRRect(const SkRRect& rrect); + void pushClipPath(const SkPath& path); void pushTransform(const SkMatrix& matrix); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index bccb354497ce2..8e01c8ff54d74 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -51,7 +51,8 @@ static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { case SkRRect::kNinePatch_Type: case SkRRect::kComplex_Type: { CGMutablePathRef mutablePathRef = CGPathCreateMutable(); - +// CGContextRef context = UIGraphicsGetCurrentContext(); +// CGContextSetAllowsAntialiasing(context, NO); // Complex types, we manually add cornors. SkRect clipSkRect = clipSkRRect.rect(); SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); @@ -75,6 +76,7 @@ static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop+topLeftRadii.y()); CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop); CGPathCloseSubpath(mutablePathRef); + pathRef = mutablePathRef; break; From 04d1f40b671e05fa4669bf6aa4e91911a9cea35b Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 28 May 2019 17:54:24 -0700 Subject: [PATCH 09/56] counting previous clips and only add and remove uiview when number of clips dont match --- flow/embedded_views.cc | 2 +- flow/embedded_views.h | 4 +- .../framework/Source/FlutterPlatformViews.mm | 94 ++++++++++--------- .../Source/FlutterPlatformViews_Internal.h | 1 + 4 files changed, 53 insertions(+), 48 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index b727c2368db0c..9885be14cf598 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -25,7 +25,7 @@ void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { void FlutterEmbededViewTransformStack::pushClipRRect(const SkRRect& rrect) { FlutterEmbededViewTransformElement element = - FlutterEmbededViewTransformElement(); + FlutterEmbededViewTransformElement(); element.setType(clip_rrect); element.setRRect(rrect); vector_.push_back(element); diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 1946d068de87c..7f63b8ed6ccbe 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -9,11 +9,11 @@ #include "flutter/fml/memory/ref_counted.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkPath.h" namespace flutter { @@ -105,7 +105,7 @@ class FlutterEmbededViewTransformElement { FlutterEmbededViewTransformType type() { return type_; } SkRect rect() { return rect_; } SkRRect rrect() { return rrect_; } - SkPath path() {return path_;} + SkPath path() { return path_; } SkMatrix matrix() { return matrix_; } friend bool operator==(const FlutterEmbededViewTransformElement& lhs, diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index d35e10c331949..71b955991b79c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -18,12 +18,12 @@ #pragma mark - Transforms Utils -static CGRect GetCGRectFromSkRect(const SkRect &clipSkRect) { +static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, - clipSkRect.fBottom - clipSkRect.fTop); + clipSkRect.fBottom - clipSkRect.fTop); } -static void ClipRect(UIView* view, const SkRect &clipSkRect) { +static void ClipRect(UIView* view, const SkRect& clipSkRect) { CGRect clipRect = GetCGRectFromSkRect(clipSkRect); CGPathRef pathRef = CGPathCreateWithRect(clipRect, nil); CAShapeLayer* clip = [[CAShapeLayer alloc] init]; @@ -32,7 +32,7 @@ static void ClipRect(UIView* view, const SkRect &clipSkRect) { CGPathRelease(pathRef); } -static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { +static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { CGPathRef pathRef = nullptr; switch (clipSkRRect.getType()) { case SkRRect::kEmpty_Type: { @@ -45,14 +45,13 @@ static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { case SkRRect::kOval_Type: case SkRRect::kSimple_Type: { CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); - pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), clipSkRRect.getSimpleRadii().y(), nil); + pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), + clipSkRRect.getSimpleRadii().y(), nil); break; } case SkRRect::kNinePatch_Type: case SkRRect::kComplex_Type: { CGMutablePathRef mutablePathRef = CGPathCreateMutable(); -// CGContextRef context = UIGraphicsGetCurrentContext(); -// CGContextSetAllowsAntialiasing(context, NO); // Complex types, we manually add cornors. SkRect clipSkRect = clipSkRRect.rect(); SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); @@ -62,35 +61,53 @@ static void ClipRRect(UIView* view, const SkRRect &clipSkRRect) { // Start drawing RRect // Move point to the top left cornor adding the top left radii's x. - CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop); + CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); // Move point horizontally right to the top right cornor and add the top right curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight-topRightRadii.x(), clipSkRect.fTop); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, clipSkRect.fRight, clipSkRect.fTop+topRightRadii.y(), clipSkRect.fRight, clipSkRect.fTop+topRightRadii.y()); + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(), + clipSkRect.fTop); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, + clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(), + clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y()); // Move point vertically down to the bottom right cornor and add the bottom right curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom - bottomRightRadii.y()); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, clipSkRect.fRight-bottomRightRadii.x(), clipSkRect.fBottom, clipSkRect.fRight-bottomRightRadii.x(), clipSkRect.fBottom); + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, + clipSkRect.fBottom - bottomRightRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, + clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom, + clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom); // Move point horizontally left to the bottom left cornor and add the bottom left curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft+bottomLeftRadii.x(), clipSkRect.fBottom); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, clipSkRect.fLeft, clipSkRect.fBottom-bottomLeftRadii.y(), clipSkRect.fLeft, clipSkRect.fBottom-bottomLeftRadii.y()); + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(), + clipSkRect.fBottom); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, + clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(), + clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y()); // Move point vertically up to the top left cornor and add the top left curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop+topLeftRadii.y()); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop, clipSkRect.fLeft+topLeftRadii.x(), clipSkRect.fTop); + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, + clipSkRect.fTop + topLeftRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, + clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop, + clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); CGPathCloseSubpath(mutablePathRef); - pathRef = mutablePathRef; break; } } + // TODO(cyanglaz): iOS seems does not 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. CAShapeLayer* clip = [[CAShapeLayer alloc] init]; clip.path = pathRef; view.layer.mask = clip; CGPathRelease(pathRef); } -static void PerformClip(UIView *view, flutter::FlutterEmbededViewTransformType type, const SkRect &rect, const SkRRect &rrect, const SkPath &path) { - FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || type == flutter::clip_path); - // TODO(cyanglaz): Add other clippings +static void PerformClip(UIView* view, + flutter::FlutterEmbededViewTransformType type, + const SkRect& rect, + const SkRRect& rrect, + const SkPath& path) { + FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || + type == flutter::clip_path); switch (type) { case flutter::clip_rect: ClipRect(view, rect); @@ -99,6 +116,7 @@ static void PerformClip(UIView *view, flutter::FlutterEmbededViewTransformType t ClipRRect(view, rrect); break; case flutter::clip_path: + // TODO(cyanglaz): Add clip path break; default: break; @@ -106,7 +124,6 @@ static void PerformClip(UIView *view, flutter::FlutterEmbededViewTransformType t } static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { - // TODO TEST(cyanglaz): test perspective transform CATransform3D transform = CATransform3DIdentity; transform.m11 = matrix.getScaleX(); transform.m21 = matrix.getSkewX(); @@ -117,20 +134,6 @@ static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { transform.m22 = matrix.getScaleY(); transform.m42 = matrix.getTranslateY(); transform.m24 = matrix.getPerspY(); -// -// NSLog(@"========="); -// -// NSLog(@"%.2f %.2f %.2f\n%.2f %.2f %.2f\n%.2f %.2f %.2f\n", matrix.getScaleX(), matrix.getSkewX(), -// matrix.getTranslateX(), matrix.getSkewY(), matrix.getScaleY(), matrix.getTranslateY(), -// matrix.getPerspX(), matrix.getPerspY(), 1.0); -// -// NSLog(@"----------"); -// -// NSLog(@"%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n%.2f %.2f %.2f %.2f\n", -// transform.m11, transform.m12, transform.m13, transform.m14, transform.m21, transform.m22, -// transform.m23, transform.m24, transform.m31, transform.m32, transform.m33, transform.m34, -// transform.m41, transform.m42, transform.m43, transform.m44); -// NSLog(@"========="); return transform; } @@ -321,7 +324,7 @@ static void ReadyUIViewForTranslate(UIView* view) { ReadyUIViewForTranslate(lastView); std::vector::iterator iter = params.transformStack->end() - 1; // TODO(cyanglaz): figure out how to handle the root transform layer (2x, 2y) - bool hasMoreClipOperations = false; + int64_t clipCount = 0; while (iter != params.transformStack->begin()) { switch (iter->type()) { @@ -335,37 +338,36 @@ static void ReadyUIViewForTranslate(UIView* view) { case clip_path: { UIView* view = lastView.superview; // if we need more clips operations than last time, create a new view. - if (!view || view == flutter_view_.get()) { + ++clipCount; + if (clipCount > clip_count_[view_id]) { [lastView removeFromSuperview]; view = [[UIView alloc] initWithFrame:lastView.bounds]; [view addSubview:lastView]; - hasMoreClipOperations = true; } PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); lastView = view; ReadyUIViewForTranslate(lastView); break; } - // TODO(cyanglaz): Add other clippings } --iter; } // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. // TODO TEST(cyanglaz): - if (!hasMoreClipOperations) { + int64_t extraClipsFromLastTime = clip_count_[view_id] - clipCount; + if (extraClipsFromLastTime > 0 && lastView.superview) { + [lastView removeFromSuperview]; UIView* superview = lastView.superview; - if (superview != flutter_view_.get()) { - [lastView removeFromSuperview]; - } - while (superview != flutter_view_.get()) { + while (extraClipsFromLastTime > 0) { UIView* superSuperView = superview.superview; [superview removeFromSuperview]; [superview release]; superview = superSuperView; } + [flutter_view_.get() addSubview:lastView]; } - + clip_count_[view_id] = clipCount; // If we have clips if (lastView != touch_interceptor) { root_views_[view_id] = fml::scoped_nsobject([lastView retain]); @@ -399,6 +401,7 @@ static void ReadyUIViewForTranslate(UIView* view) { active_composition_order_.clear(); picture_recorders_.clear(); composite_params_.clear(); + clip_count_.clear(); } bool FlutterPlatformViewsController::SubmitFrame(bool gl_rendering, @@ -480,6 +483,7 @@ static void ReadyUIViewForTranslate(UIView* view) { root_views_.erase(viewId); overlays_.erase(viewId); composite_params_.erase(viewId); + clip_count_.erase(viewId); } views_to_dispose_.clear(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index ad4ef76989ff1..6fe699011cd0a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -90,6 +90,7 @@ class FlutterPlatformViewsController { std::map> touch_interceptors_; std::map> root_views_; std::map composite_params_; + std::map clip_count_; std::map> overlays_; // The GrContext that is currently used by all of the overlay surfaces. // We track this to know when the GrContext for the Flutter app has changed From 5b05eb2e9261ca4bc7637cc72dad628f839535b9 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 30 May 2019 16:54:23 -0700 Subject: [PATCH 10/56] draft --- flow/embedded_views.cc | 12 ++--- flow/embedded_views.h | 4 +- .../framework/Source/FlutterPlatformViews.mm | 45 ++++++++++++------- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 9885be14cf598..ba26f01a8bfd1 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -43,14 +43,14 @@ void FlutterEmbededViewTransformStack::pop() { vector_.pop_back(); } -std::vector::iterator -FlutterEmbededViewTransformStack::begin() { - return vector_.begin(); +std::vector::reverse_iterator +FlutterEmbededViewTransformStack::rbegin() { + return vector_.rbegin(); } -std::vector::iterator -FlutterEmbededViewTransformStack::end() { - return vector_.end(); +std::vector::reverse_iterator +FlutterEmbededViewTransformStack::rend() { + return vector_.rend(); } } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 7f63b8ed6ccbe..9f791dd9ab601 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -75,9 +75,9 @@ class FlutterEmbededViewTransformStack { void pop(); // Returns the iterator points to the bottom of the stack. - std::vector::iterator begin(); + std::vector::reverse_iterator rbegin(); // Returns the iterator points to the top of the stack. - std::vector::iterator end(); + std::vector::reverse_iterator rend(); friend bool operator==(const FlutterEmbededViewTransformStack& lhs, const FlutterEmbededViewTransformStack& rhs) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 71b955991b79c..5112c1039a3b2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -124,25 +124,27 @@ static void PerformClip(UIView* view, } static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { + CGFloat screenScale = [UIScreen mainScreen].scale; CATransform3D transform = CATransform3DIdentity; transform.m11 = matrix.getScaleX(); transform.m21 = matrix.getSkewX(); - transform.m41 = matrix.getTranslateX(); + transform.m41 = matrix.getTranslateX()/screenScale; transform.m14 = matrix.getPerspX(); transform.m12 = matrix.getSkewY(); transform.m22 = matrix.getScaleY(); - transform.m42 = matrix.getTranslateY(); + transform.m42 = matrix.getTranslateY()/screenScale; transform.m24 = matrix.getPerspY(); return transform; } -static void ReadyUIViewForTranslate(UIView* view) { - view.layer.transform = CATransform3DIdentity; - view.layer.anchorPoint = CGPointMake( - 0, 0); // Quartz's default anchor point is the center, we set it to (0,0) to match flow. - view.layer.position = CGPointMake(0, 0); // After changing the anchor point, the layer's position - // is changed, we need to reset it back to (0,0). +static void SetAnchor(CALayer *layer, CGPoint transformPosition) { + NSLog(@"subview original in view %@", @(transformPosition)); + NSLog(@"current position %@", @(layer.position)); + layer.anchorPoint = CGPointMake(transformPosition.x/layer.bounds.size.width, transformPosition.y/layer.bounds.size.height); + layer.position = transformPosition; + NSLog(@"transform anchor %@", @(layer.anchorPoint)); + NSLog(@"transform position %@", @(layer.position)); } namespace flutter { @@ -317,16 +319,19 @@ static void ReadyUIViewForTranslate(UIView* view) { const flutter::EmbeddedViewParams& params) { UIView* touch_interceptor = touch_interceptors_[view_id].get(); + CGFloat screenScale = [UIScreen mainScreen].scale; CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); touch_interceptor.frame = frame; UIView* lastView = touch_interceptor; - - ReadyUIViewForTranslate(lastView); - std::vector::iterator iter = params.transformStack->end() - 1; - // TODO(cyanglaz): figure out how to handle the root transform layer (2x, 2y) + CGPoint transformAnchor = CGPointZero; + lastView.layer.transform = CATransform3DIdentity; + SetAnchor(lastView.layer, transformAnchor); + // Reverse transform based on screen scale. + // We needed to do that because in our layer tree, we have a transform layer at the root to transform based on the sreen scale. + lastView.layer.transform = CATransform3DMakeScale(1/screenScale, 1/screenScale, 1); + std::vector::reverse_iterator iter = params.transformStack->rbegin(); int64_t clipCount = 0; - - while (iter != params.transformStack->begin()) { + while (iter != params.transformStack->rend()) { switch (iter->type()) { case transform: { CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); @@ -345,13 +350,18 @@ static void ReadyUIViewForTranslate(UIView* view) { [view addSubview:lastView]; } PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); + + CGPoint transformPosition = [view convertPoint:touch_interceptor.bounds.origin fromView:touch_interceptor]; + SetAnchor(view.layer, transformPosition); + lastView = view; - ReadyUIViewForTranslate(lastView); break; } } - --iter; + NSLog(@"last view frame %@", @(lastView.frame)); + ++iter; } + // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. // TODO TEST(cyanglaz): @@ -368,7 +378,7 @@ static void ReadyUIViewForTranslate(UIView* view) { [flutter_view_.get() addSubview:lastView]; } clip_count_[view_id] = clipCount; - // If we have clips + // If we have clips, replace root view with the top parent view. if (lastView != touch_interceptor) { root_views_[view_id] = fml::scoped_nsobject([lastView retain]); } @@ -443,6 +453,7 @@ static void ReadyUIViewForTranslate(UIView* view) { } else { [flutter_view addSubview:root]; [flutter_view addSubview:overlay]; + NSLog(@"root view frame %@", @(root.frame)); } active_composition_order_.push_back(view_id); From 9b290cbb4f58cc4b9a0de716468948cb165cb54d Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 30 May 2019 16:59:59 -0700 Subject: [PATCH 11/56] draft --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 5112c1039a3b2..c0a5cb8436f09 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -328,7 +328,6 @@ static void SetAnchor(CALayer *layer, CGPoint transformPosition) { SetAnchor(lastView.layer, transformAnchor); // Reverse transform based on screen scale. // We needed to do that because in our layer tree, we have a transform layer at the root to transform based on the sreen scale. - lastView.layer.transform = CATransform3DMakeScale(1/screenScale, 1/screenScale, 1); std::vector::reverse_iterator iter = params.transformStack->rbegin(); int64_t clipCount = 0; while (iter != params.transformStack->rend()) { @@ -361,6 +360,7 @@ static void SetAnchor(CALayer *layer, CGPoint transformPosition) { NSLog(@"last view frame %@", @(lastView.frame)); ++iter; } + lastView.layer.transform = CATransform3DMakeScale(1/screenScale, 1/screenScale, 1); // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. From 52a8252b6c9f52544ce03121f2bc82e09f011334 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 31 May 2019 10:12:28 -0700 Subject: [PATCH 12/56] comments and formatting --- .../framework/Source/FlutterPlatformViews.mm | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index c0a5cb8436f09..fad1fc27599b5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -52,7 +52,7 @@ static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { case SkRRect::kNinePatch_Type: case SkRRect::kComplex_Type: { CGMutablePathRef mutablePathRef = CGPathCreateMutable(); - // Complex types, we manually add cornors. + // Complex types, we manually add each cornor. SkRect clipSkRect = clipSkRRect.rect(); SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); @@ -124,27 +124,24 @@ static void PerformClip(UIView* view, } static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { - CGFloat screenScale = [UIScreen mainScreen].scale; + // Skia only supports 2D transform so we don't map z. CATransform3D transform = CATransform3DIdentity; transform.m11 = matrix.getScaleX(); transform.m21 = matrix.getSkewX(); - transform.m41 = matrix.getTranslateX()/screenScale; + transform.m41 = matrix.getTranslateX(); transform.m14 = matrix.getPerspX(); transform.m12 = matrix.getSkewY(); transform.m22 = matrix.getScaleY(); - transform.m42 = matrix.getTranslateY()/screenScale; + transform.m42 = matrix.getTranslateY(); transform.m24 = matrix.getPerspY(); return transform; } -static void SetAnchor(CALayer *layer, CGPoint transformPosition) { - NSLog(@"subview original in view %@", @(transformPosition)); - NSLog(@"current position %@", @(layer.position)); - layer.anchorPoint = CGPointMake(transformPosition.x/layer.bounds.size.width, transformPosition.y/layer.bounds.size.height); - layer.position = transformPosition; - NSLog(@"transform anchor %@", @(layer.anchorPoint)); - NSLog(@"transform position %@", @(layer.position)); +static void ResetAnchor(CALayer* layer) { + // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. + layer.anchorPoint = CGPointZero; + layer.position = CGPointZero; } namespace flutter { @@ -319,16 +316,17 @@ static void SetAnchor(CALayer *layer, CGPoint transformPosition) { const flutter::EmbeddedViewParams& params) { UIView* touch_interceptor = touch_interceptors_[view_id].get(); - CGFloat screenScale = [UIScreen mainScreen].scale; CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); touch_interceptor.frame = frame; UIView* lastView = touch_interceptor; - CGPoint transformAnchor = CGPointZero; + + // Reset everything related to transform. lastView.layer.transform = CATransform3DIdentity; - SetAnchor(lastView.layer, transformAnchor); - // Reverse transform based on screen scale. - // We needed to do that because in our layer tree, we have a transform layer at the root to transform based on the sreen scale. - std::vector::reverse_iterator iter = params.transformStack->rbegin(); + ResetAnchor(lastView.layer); + + // Start loop to apply transforms/clips. + std::vector::reverse_iterator iter = + params.transformStack->rbegin(); int64_t clipCount = 0; while (iter != params.transformStack->rend()) { switch (iter->type()) { @@ -349,22 +347,27 @@ static void SetAnchor(CALayer *layer, CGPoint transformPosition) { [view addSubview:lastView]; } PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); - - CGPoint transformPosition = [view convertPoint:touch_interceptor.bounds.origin fromView:touch_interceptor]; - SetAnchor(view.layer, transformPosition); - + ResetAnchor(view.layer); lastView = view; break; } } - NSLog(@"last view frame %@", @(lastView.frame)); ++iter; } - lastView.layer.transform = CATransform3DMakeScale(1/screenScale, 1/screenScale, 1); + + // Reverse scale based on screen scale. + // + // The UIKit frame is set based on the logical resolution instead of physical. + // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). + // However, flow is based on the physical resolution. For eaxmple, 1000 pixels in flow equals + // 500 points in UIKit. And until this point, we did all the calculation based on the flow + // resolution. So we need to scale down to match UIKit's logical resolution. + CGFloat screenScale = [UIScreen mainScreen].scale; + lastView.layer.transform = CATransform3DConcat( + lastView.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. - // TODO TEST(cyanglaz): int64_t extraClipsFromLastTime = clip_count_[view_id] - clipCount; if (extraClipsFromLastTime > 0 && lastView.superview) { [lastView removeFromSuperview]; @@ -453,7 +456,6 @@ static void SetAnchor(CALayer *layer, CGPoint transformPosition) { } else { [flutter_view addSubview:root]; [flutter_view addSubview:overlay]; - NSLog(@"root view frame %@", @(root.frame)); } active_composition_order_.push_back(view_id); From 3a899face5a340178de64d29d5395e2480207e2b Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 31 May 2019 10:13:49 -0700 Subject: [PATCH 13/56] english --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index fad1fc27599b5..83894cb548454 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -92,7 +92,7 @@ static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { break; } } - // TODO(cyanglaz): iOS seems does not support hard edge on CAShapeLayer. It clearly stated that + // 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. CAShapeLayer* clip = [[CAShapeLayer alloc] init]; From cabc67a2d91e8f2a1687bbd66fbd495c93b7ce03 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 31 May 2019 10:42:29 -0700 Subject: [PATCH 14/56] remove friend from operator== --- flow/embedded_views.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 9f791dd9ab601..1025561b1431c 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -79,9 +79,8 @@ class FlutterEmbededViewTransformStack { // Returns the iterator points to the top of the stack. std::vector::reverse_iterator rend(); - friend bool operator==(const FlutterEmbededViewTransformStack& lhs, - const FlutterEmbededViewTransformStack& rhs) { - return lhs.vector_ == rhs.vector_; + bool operator==(const FlutterEmbededViewTransformStack& other) const { + return vector_ == other.vector_; } private: @@ -108,15 +107,20 @@ class FlutterEmbededViewTransformElement { SkPath path() { return path_; } SkMatrix matrix() { return matrix_; } - friend bool operator==(const FlutterEmbededViewTransformElement& lhs, - const FlutterEmbededViewTransformElement& rhs) { - if (lhs.type_ != rhs.type_) { + bool operator==(const FlutterEmbededViewTransformElement& other) const { + if (type_ != other.type_) { return false; } - if (lhs.type_ == clip_rect && lhs.rect_ == rhs.rect_) { + if (type_ == clip_rect && rect_ == other.rect_) { return true; } - if (lhs.type_ == transform && lhs.matrix_ == rhs.matrix_) { + if (type_ == clip_rect && rrect_ == other.rrect_) { + return true; + } + if (type_ == clip_path && path_ == other.path_) { + return true; + } + if (type_ == transform && matrix_ == other.matrix_) { return true; } return false; From 4bdae98b6dd3c873a98b32c3d179edcaabfc840f Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 3 Jun 2019 14:35:46 -0700 Subject: [PATCH 15/56] fix issue caused by merging --- flow/embedded_views.h | 1 + 1 file changed, 1 insertion(+) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index a5be63a501db1..571055a8348cc 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -24,6 +24,7 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; + std::shared_ptr transformStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && transformStack == other.transformStack; From 33513b9f16bd620e6778cda10324ca9cbf1fdef7 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 3 Jun 2019 16:10:13 -0700 Subject: [PATCH 16/56] review fixes --- flow/embedded_views.cc | 29 +++++----- flow/embedded_views.h | 53 ++++++++++--------- flow/layers/clip_rect_layer.cc | 8 ++- flow/layers/clip_rrect_layer.cc | 8 ++- flow/layers/transform_layer.cc | 8 ++- .../framework/Source/FlutterPlatformViews.mm | 22 ++++---- .../Source/FlutterPlatformViews_Internal.h | 2 +- 7 files changed, 68 insertions(+), 62 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index ba26f01a8bfd1..537ae9fa22046 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -7,49 +7,44 @@ namespace flutter { ExternalViewEmbedder::ExternalViewEmbedder() - : transformStack(std::make_shared()){}; + : transformStack(std::make_shared()){}; bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; }; -#pragma mark - FlutterEmbededViewTransformStack - -void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { - FlutterEmbededViewTransformElement element = - FlutterEmbededViewTransformElement(); +void EmbeddedViewMutatorStack::pushClipRect(const SkRect& rect) { + EmbeddedViewMutator element = EmbeddedViewMutator(); element.setType(clip_rect); element.setRect(rect); vector_.push_back(element); }; -void FlutterEmbededViewTransformStack::pushClipRRect(const SkRRect& rrect) { - FlutterEmbededViewTransformElement element = - FlutterEmbededViewTransformElement(); +void EmbeddedViewMutatorStack::pushClipRRect(const SkRRect& rrect) { + EmbeddedViewMutator element = EmbeddedViewMutator(); element.setType(clip_rrect); element.setRRect(rrect); vector_.push_back(element); }; -void FlutterEmbededViewTransformStack::pushTransform(const SkMatrix& matrix) { - FlutterEmbededViewTransformElement element = - FlutterEmbededViewTransformElement(); +void EmbeddedViewMutatorStack::pushTransform(const SkMatrix& matrix) { + EmbeddedViewMutator element = EmbeddedViewMutator(); element.setType(transform); element.setMatrix(matrix); vector_.push_back(element); }; -void FlutterEmbededViewTransformStack::pop() { +void EmbeddedViewMutatorStack::pop() { vector_.pop_back(); } -std::vector::reverse_iterator -FlutterEmbededViewTransformStack::rbegin() { +std::vector::reverse_iterator +EmbeddedViewMutatorStack::rbegin() { return vector_.rbegin(); } -std::vector::reverse_iterator -FlutterEmbededViewTransformStack::rend() { +std::vector::reverse_iterator +EmbeddedViewMutatorStack::rend() { return vector_.rend(); } diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 571055a8348cc..36e94fb125605 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -17,17 +17,19 @@ namespace flutter { -class FlutterEmbededViewTransformStack; -class FlutterEmbededViewTransformElement; +class EmbeddedViewMutatorStack; +class EmbeddedViewMutator; class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - std::shared_ptr transformStack; + std::shared_ptr transformStack; bool operator==(const EmbeddedViewParams& other) const { - return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && transformStack == other.transformStack; + return offsetPixels == other.offsetPixels && + sizePoints == other.sizePoints && + transformStack == other.transformStack; } }; @@ -54,12 +56,11 @@ class ExternalViewEmbedder { FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); -#pragma mark - transforms - std::shared_ptr transformStack; + std::shared_ptr transformStack; }; // ExternalViewEmbedder -class FlutterEmbededViewTransformStack { +class EmbeddedViewMutatorStack { public: void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); @@ -67,44 +68,44 @@ class FlutterEmbededViewTransformStack { void pushTransform(const SkMatrix& matrix); - // Removes the `FlutterEmbededViewTransformElement` on the top of the stack + // Removes the `EmbeddedViewMutator` on the top of the stack // and destroys it. void pop(); // Returns the iterator points to the bottom of the stack. - std::vector::reverse_iterator rbegin(); + // When we composite a embedded view, this is the first mutator we should + // apply to the view. And we should iterate through all the mutators until we + // reach `rend()` and apply all the mutations to the view along the way. + std::vector::reverse_iterator rbegin(); // Returns the iterator points to the top of the stack. - std::vector::reverse_iterator rend(); + // When we composite a embedded view, this is the last mutator we apply to the + // view. + std::vector::reverse_iterator rend(); - bool operator==(const FlutterEmbededViewTransformStack& other) const { + bool operator==(const EmbeddedViewMutatorStack& other) const { return vector_ == other.vector_; } private: - std::vector vector_; -}; // FlutterEmbededViewTransformStack - -enum FlutterEmbededViewTransformType { - clip_rect, - clip_rrect, - clip_path, - transform -}; + std::vector vector_; +}; // EmbeddedViewMutatorStack + +enum EmbeddedViewMutationType { clip_rect, clip_rrect, clip_path, transform }; -class FlutterEmbededViewTransformElement { +class EmbeddedViewMutator { public: - void setType(const FlutterEmbededViewTransformType type) { type_ = type; } + void setType(const EmbeddedViewMutationType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } void setRRect(const SkRRect& rrect) { rrect_ = rrect; } void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } - FlutterEmbededViewTransformType type() { return type_; } + EmbeddedViewMutationType type() { return type_; } SkRect rect() { return rect_; } SkRRect rrect() { return rrect_; } SkPath path() { return path_; } SkMatrix matrix() { return matrix_; } - bool operator==(const FlutterEmbededViewTransformElement& other) const { + bool operator==(const EmbeddedViewMutator& other) const { if (type_ != other.type_) { return false; } @@ -128,12 +129,12 @@ class FlutterEmbededViewTransformElement { } private: - FlutterEmbededViewTransformType type_; + EmbeddedViewMutationType type_; SkRect rect_; SkRRect rrect_; SkPath path_; SkMatrix matrix_; -}; // FlutterEmbededViewTransformElement +}; // EmbeddedViewMutator } // namespace flutter diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 54fd1563aa887..e0befe0ab94b1 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,7 +50,9 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); - context.view_embedder->transformStack->pushClipRect(clip_rect_); + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pushClipRect(clip_rect_); + } if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); } @@ -58,7 +60,9 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - context.view_embedder->transformStack->pop(); + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pop(); + } } } // namespace flutter diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 34a2d0664581d..9dd14727d7115 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -58,15 +58,19 @@ void ClipRRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); - context.view_embedder->transformStack->pushClipRRect(clip_rrect_); + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pushClipRRect(clip_rrect_); + } if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } PaintChildren(context); - context.view_embedder->transformStack->pop(); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pop(); + } } } // namespace flutter diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index c7a9bc8fbe5a2..a232090cd856f 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -66,9 +66,13 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); - context.view_embedder->transformStack->pushTransform(transform_); + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pushTransform(transform_); + } PaintChildren(context); - context.view_embedder->transformStack->pop(); + if (context.view_embedder != nullptr) { + context.view_embedder->transformStack->pop(); + } } } // namespace flutter diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index bf1cfa16b864f..ad5ae2d13d243 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -16,8 +16,6 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -#pragma mark - Transforms Utils - static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, clipSkRect.fBottom - clipSkRect.fTop); @@ -52,7 +50,7 @@ static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { case SkRRect::kNinePatch_Type: case SkRRect::kComplex_Type: { CGMutablePathRef mutablePathRef = CGPathCreateMutable(); - // Complex types, we manually add each cornor. + // Complex types, we manually add each corner. SkRect clipSkRect = clipSkRRect.rect(); SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); @@ -60,27 +58,27 @@ static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner); // Start drawing RRect - // Move point to the top left cornor adding the top left radii's x. + // Move point to the top left corner adding the top left radii's x. CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); - // Move point horizontally right to the top right cornor and add the top right curve. + // Move point horizontally right to the top right corner and add the top right curve. CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(), clipSkRect.fTop); CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(), clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y()); - // Move point vertically down to the bottom right cornor and add the bottom right curve. + // Move point vertically down to the bottom right corner and add the bottom right curve. CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom - bottomRightRadii.y()); CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom, clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom); - // Move point horizontally left to the bottom left cornor and add the bottom left curve. + // Move point horizontally left to the bottom left corner and add the bottom left curve. CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(), clipSkRect.fBottom); CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(), clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y()); - // Move point vertically up to the top left cornor and add the top left curve. + // Move point vertically up to the top left corner and add the top left curve. CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop + topLeftRadii.y()); CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, @@ -102,7 +100,7 @@ static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { } static void PerformClip(UIView* view, - flutter::FlutterEmbededViewTransformType type, + flutter::EmbeddedViewMutationType type, const SkRect& rect, const SkRRect& rrect, const SkPath& path) { @@ -325,8 +323,7 @@ static void ResetAnchor(CALayer* layer) { ResetAnchor(lastView.layer); // Start loop to apply transforms/clips. - std::vector::reverse_iterator iter = - params.transformStack->rbegin(); + std::vector::reverse_iterator iter = params.transformStack->rbegin(); int64_t clipCount = 0; while (iter != params.transformStack->rend()) { switch (iter->type()) { @@ -394,7 +391,8 @@ static void ResetAnchor(CALayer* layer) { // embedded views thread configuration. // Do nothing if the params didn't change. - if (current_composition_params_.count(view_id) == 1 && current_composition_params_[view_id] == params) { + if (current_composition_params_.count(view_id) == 1 && + current_composition_params_[view_id] == params) { return picture_recorders_[view_id]->getRecordingCanvas(); } current_composition_params_[view_id] = params; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 54d181381c64d..e3096107ac10e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -90,7 +90,7 @@ class FlutterPlatformViewsController { std::map> touch_interceptors_; std::map> root_views_; // Mapping a platform view ID to its latest composition params. - std::map current_composition_params_; + std::map current_composition_params_; std::map clip_count_; std::map> overlays_; // The GrContext that is currently used by all of the overlay surfaces. From e8926a52ce1289ca811aeba37bd4cc873accb416 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 4 Jun 2019 09:08:25 -0700 Subject: [PATCH 17/56] remove tranform\cilpping util method into a different file and add them to the flutter name space --- .../framework/Source/FlutterPlatformViews.mm | 126 ------------------ .../Source/FlutterPlatformViews_Internal.h | 25 ++++ .../Source/FlutterPlatformViews_Internal.mm | 126 ++++++++++++++++++ 3 files changed, 151 insertions(+), 126 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index ad5ae2d13d243..914674ffafaea 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -16,132 +16,6 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { - return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, - clipSkRect.fBottom - clipSkRect.fTop); -} - -static void ClipRect(UIView* view, const SkRect& clipSkRect) { - CGRect clipRect = GetCGRectFromSkRect(clipSkRect); - CGPathRef pathRef = CGPathCreateWithRect(clipRect, nil); - CAShapeLayer* clip = [[CAShapeLayer alloc] init]; - clip.path = pathRef; - view.layer.mask = clip; - CGPathRelease(pathRef); -} - -static void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { - CGPathRef pathRef = nullptr; - switch (clipSkRRect.getType()) { - case SkRRect::kEmpty_Type: { - break; - } - case SkRRect::kRect_Type: { - ClipRect(view, clipSkRRect.rect()); - return; - } - case SkRRect::kOval_Type: - case SkRRect::kSimple_Type: { - CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); - pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), - clipSkRRect.getSimpleRadii().y(), nil); - break; - } - case SkRRect::kNinePatch_Type: - case SkRRect::kComplex_Type: { - CGMutablePathRef mutablePathRef = CGPathCreateMutable(); - // Complex types, we manually add each corner. - SkRect clipSkRect = clipSkRRect.rect(); - SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); - SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); - SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner); - SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner); - - // Start drawing RRect - // Move point to the top left corner adding the top left radii's x. - CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); - // Move point horizontally right to the top right corner and add the top right curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(), - clipSkRect.fTop); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, - clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(), - clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y()); - // Move point vertically down to the bottom right corner and add the bottom right curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, - clipSkRect.fBottom - bottomRightRadii.y()); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, - clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom, - clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom); - // Move point horizontally left to the bottom left corner and add the bottom left curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(), - clipSkRect.fBottom); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, - clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(), - clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y()); - // Move point vertically up to the top left corner and add the top left curve. - CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, - clipSkRect.fTop + topLeftRadii.y()); - CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, - clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop, - clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); - CGPathCloseSubpath(mutablePathRef); - - pathRef = mutablePathRef; - break; - } - } - // 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. - CAShapeLayer* clip = [[CAShapeLayer alloc] init]; - clip.path = pathRef; - view.layer.mask = clip; - CGPathRelease(pathRef); -} - -static void PerformClip(UIView* view, - flutter::EmbeddedViewMutationType type, - const SkRect& rect, - const SkRRect& rrect, - const SkPath& path) { - FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || - type == flutter::clip_path); - switch (type) { - case flutter::clip_rect: - ClipRect(view, rect); - break; - case flutter::clip_rrect: - ClipRRect(view, rrect); - break; - case flutter::clip_path: - // TODO(cyanglaz): Add clip path - break; - default: - break; - } -} - -static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { - // Skia only supports 2D transform so we don't map z. - CATransform3D transform = CATransform3DIdentity; - transform.m11 = matrix.getScaleX(); - transform.m21 = matrix.getSkewX(); - transform.m41 = matrix.getTranslateX(); - transform.m14 = matrix.getPerspX(); - - transform.m12 = matrix.getSkewY(); - transform.m22 = matrix.getScaleY(); - transform.m42 = matrix.getTranslateY(); - transform.m24 = matrix.getPerspY(); - return transform; -} - -static void ResetAnchor(CALayer* layer) { - // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. - layer.anchorPoint = CGPointZero; - layer.position = CGPointZero; -} - namespace flutter { void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index e3096107ac10e..5eded76756b7e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -30,6 +30,31 @@ namespace flutter { +// Converts a SkRect to CGRect. +CGRect GetCGRectFromSkRect(const SkRect& clipSkRect); + +// Perform clip rect on the `view` using `clipSkRect`. +void ClipRect(UIView* view, const SkRect& clipSkRect); + +// Perform clip rounded rect on the `view` using `clipSkRRect`. +void ClipRRect(UIView* view, const SkRRect& clipSkRRect); + +// Perform a clip operation on the `view`. +// Uses either `rect`, `rrect` or `path` to perform the clip based on the `type`. +void PerformClip(UIView* view, + flutter::EmbeddedViewMutationType type, + const SkRect& rect, + const SkRRect& rrect, + const SkPath& path); + +// Converts a SkMatrix to CATransform3D. +// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. +CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix); + +// Reset the anchor of `layer` to match the tranform operation from flow. +// The position of the `layer` should be unchanged after resetting the anchor. +void ResetAnchor(CALayer* layer); + class IOSGLContext; class IOSSurface; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 7c2fb3e6ca5a2..25f2242174344 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -21,4 +21,130 @@ FlutterPlatformViewsController::~FlutterPlatformViewsController() = default; +CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { + return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, + clipSkRect.fBottom - clipSkRect.fTop); +} + +void ClipRect(UIView* view, const SkRect& clipSkRect) { + CGRect clipRect = GetCGRectFromSkRect(clipSkRect); + CGPathRef pathRef = CGPathCreateWithRect(clipRect, nil); + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; + clip.path = pathRef; + view.layer.mask = clip; + CGPathRelease(pathRef); +} + +void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { + CGPathRef pathRef = nullptr; + switch (clipSkRRect.getType()) { + case SkRRect::kEmpty_Type: { + break; + } + case SkRRect::kRect_Type: { + ClipRect(view, clipSkRRect.rect()); + return; + } + case SkRRect::kOval_Type: + case SkRRect::kSimple_Type: { + CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); + pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), + clipSkRRect.getSimpleRadii().y(), nil); + break; + } + case SkRRect::kNinePatch_Type: + case SkRRect::kComplex_Type: { + CGMutablePathRef mutablePathRef = CGPathCreateMutable(); + // Complex types, we manually add each corner. + SkRect clipSkRect = clipSkRRect.rect(); + SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner); + SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner); + SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner); + SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner); + + // Start drawing RRect + // Move point to the top left corner adding the top left radii's x. + CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); + // Move point horizontally right to the top right corner and add the top right curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(), + clipSkRect.fTop); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop, + clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(), + clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y()); + // Move point vertically down to the bottom right corner and add the bottom right curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight, + clipSkRect.fBottom - bottomRightRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom, + clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom, + clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom); + // Move point horizontally left to the bottom left corner and add the bottom left curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(), + clipSkRect.fBottom); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom, + clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(), + clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y()); + // Move point vertically up to the top left corner and add the top left curve. + CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft, + clipSkRect.fTop + topLeftRadii.y()); + CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop, + clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop, + clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop); + CGPathCloseSubpath(mutablePathRef); + + pathRef = mutablePathRef; + break; + } + } + // 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. + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; + clip.path = pathRef; + view.layer.mask = clip; + CGPathRelease(pathRef); +} + +void PerformClip(UIView* view, + flutter::EmbeddedViewMutationType type, + const SkRect& rect, + const SkRRect& rrect, + const SkPath& path) { + FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || + type == flutter::clip_path); + switch (type) { + case flutter::clip_rect: + ClipRect(view, rect); + break; + case flutter::clip_rrect: + ClipRRect(view, rrect); + break; + case flutter::clip_path: + // TODO(cyanglaz): Add clip path + break; + default: + break; + } +} + +CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { + // Skia only supports 2D transform so we don't map z. + CATransform3D transform = CATransform3DIdentity; + transform.m11 = matrix.getScaleX(); + transform.m21 = matrix.getSkewX(); + transform.m41 = matrix.getTranslateX(); + transform.m14 = matrix.getPerspX(); + + transform.m12 = matrix.getSkewY(); + transform.m22 = matrix.getScaleY(); + transform.m42 = matrix.getTranslateY(); + transform.m24 = matrix.getPerspY(); + return transform; +} + +void ResetAnchor(CALayer* layer) { + // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. + layer.anchorPoint = CGPointZero; + layer.position = CGPointZero; +} + } // namespace flutter From 3f4c586e7df472b78cc330a55e66862e8b031c2f Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 4 Jun 2019 11:24:50 -0700 Subject: [PATCH 18/56] rename after review --- flow/embedded_views.cc | 28 +++++----- flow/embedded_views.h | 54 ++++++++++--------- .../framework/Source/FlutterPlatformViews.mm | 4 +- .../Source/FlutterPlatformViews_Internal.h | 2 +- .../Source/FlutterPlatformViews_Internal.mm | 2 +- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 537ae9fa22046..d8b346c0be04a 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -7,45 +7,45 @@ namespace flutter { ExternalViewEmbedder::ExternalViewEmbedder() - : transformStack(std::make_shared()){}; + : transformStack(std::make_shared()){}; bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; }; -void EmbeddedViewMutatorStack::pushClipRect(const SkRect& rect) { - EmbeddedViewMutator element = EmbeddedViewMutator(); +void MutatorsStack::pushClipRect(const SkRect& rect) { + Mutator element = Mutator(); element.setType(clip_rect); element.setRect(rect); vector_.push_back(element); }; -void EmbeddedViewMutatorStack::pushClipRRect(const SkRRect& rrect) { - EmbeddedViewMutator element = EmbeddedViewMutator(); +void MutatorsStack::pushClipRRect(const SkRRect& rrect) { + Mutator element = Mutator(); element.setType(clip_rrect); element.setRRect(rrect); vector_.push_back(element); }; -void EmbeddedViewMutatorStack::pushTransform(const SkMatrix& matrix) { - EmbeddedViewMutator element = EmbeddedViewMutator(); +void MutatorsStack::pushTransform(const SkMatrix& matrix) { + Mutator element = Mutator(); element.setType(transform); element.setMatrix(matrix); vector_.push_back(element); }; -void EmbeddedViewMutatorStack::pop() { +void MutatorsStack::pop() { vector_.pop_back(); } -std::vector::reverse_iterator -EmbeddedViewMutatorStack::rbegin() { - return vector_.rbegin(); +std::vector::reverse_iterator +MutatorsStack::top() { + return vector_.rend(); } -std::vector::reverse_iterator -EmbeddedViewMutatorStack::rend() { - return vector_.rend(); +std::vector::reverse_iterator +MutatorsStack::bottom() { + return vector_.rbegin(); } } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 36e94fb125605..07833ceb9a3f4 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -17,14 +17,14 @@ namespace flutter { -class EmbeddedViewMutatorStack; -class EmbeddedViewMutator; +class MutatorsStack; +class Mutator; class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - std::shared_ptr transformStack; + std::shared_ptr transformStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && @@ -56,11 +56,18 @@ class ExternalViewEmbedder { FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); - std::shared_ptr transformStack; + std::shared_ptr transformStack; }; // ExternalViewEmbedder -class EmbeddedViewMutatorStack { +// A stack of mutators that can be applied to an embedded platform view. +// +// The stack may include mutators like transforms and clips, each mutator applies to all the mutators that are below it in the stack +// and to the embedded view. +// +// For example consider the following stack: [T1, T2, T3], where T1 is the top of the stack and T3 is the bottom of the stack. +// Applying this mutators stack to a platform view P1 will result in T1(T2(T2(P1))). +class MutatorsStack { public: void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); @@ -68,44 +75,39 @@ class EmbeddedViewMutatorStack { void pushTransform(const SkMatrix& matrix); - // Removes the `EmbeddedViewMutator` on the top of the stack + // Removes the `Mutator` on the top of the stack // and destroys it. void pop(); - // Returns the iterator points to the bottom of the stack. - // When we composite a embedded view, this is the first mutator we should - // apply to the view. And we should iterate through all the mutators until we - // reach `rend()` and apply all the mutations to the view along the way. - std::vector::reverse_iterator rbegin(); - // Returns the iterator points to the top of the stack. - // When we composite a embedded view, this is the last mutator we apply to the - // view. - std::vector::reverse_iterator rend(); - - bool operator==(const EmbeddedViewMutatorStack& other) const { + // Returns the iterator points to the top of the stack.. + std::vector::reverse_iterator top(); + // Returns an iterator pointing to the bottom of the stack. + std::vector::reverse_iterator bottom(); + + bool operator==(const MutatorsStack& other) const { return vector_ == other.vector_; } private: - std::vector vector_; -}; // EmbeddedViewMutatorStack + std::vector vector_; +}; // MutatorsStack -enum EmbeddedViewMutationType { clip_rect, clip_rrect, clip_path, transform }; +enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; -class EmbeddedViewMutator { +class Mutator { public: - void setType(const EmbeddedViewMutationType type) { type_ = type; } + void setType(const MutatorType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } void setRRect(const SkRRect& rrect) { rrect_ = rrect; } void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } - EmbeddedViewMutationType type() { return type_; } + MutatorType type() { return type_; } SkRect rect() { return rect_; } SkRRect rrect() { return rrect_; } SkPath path() { return path_; } SkMatrix matrix() { return matrix_; } - bool operator==(const EmbeddedViewMutator& other) const { + bool operator==(const Mutator& other) const { if (type_ != other.type_) { return false; } @@ -129,12 +131,12 @@ class EmbeddedViewMutator { } private: - EmbeddedViewMutationType type_; + MutatorType type_; SkRect rect_; SkRRect rrect_; SkPath path_; SkMatrix matrix_; -}; // EmbeddedViewMutator +}; // Mutator } // namespace flutter diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 914674ffafaea..82ff2332c6bfd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -197,9 +197,9 @@ ResetAnchor(lastView.layer); // Start loop to apply transforms/clips. - std::vector::reverse_iterator iter = params.transformStack->rbegin(); + std::vector::reverse_iterator iter = params.transformStack->bottom(); int64_t clipCount = 0; - while (iter != params.transformStack->rend()) { + while (iter != params.transformStack->top()) { switch (iter->type()) { case transform: { CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 5eded76756b7e..376faf0b77c6a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -42,7 +42,7 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect); // Perform a clip operation on the `view`. // Uses either `rect`, `rrect` or `path` to perform the clip based on the `type`. void PerformClip(UIView* view, - flutter::EmbeddedViewMutationType type, + flutter::MutatorType type, const SkRect& rect, const SkRRect& rrect, const SkPath& path); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 25f2242174344..f49333bf3631f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -105,7 +105,7 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { } void PerformClip(UIView* view, - flutter::EmbeddedViewMutationType type, + flutter::MutatorType type, const SkRect& rect, const SkRRect& rrect, const SkPath& path) { From d4f88f2490dbe4bf416b8946c3fabe3053267492 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 4 Jun 2019 13:01:40 -0700 Subject: [PATCH 19/56] move stack to paint context --- flow/compositor_context.cc | 4 +++- flow/compositor_context.h | 11 +++++++++++ flow/embedded_views.cc | 3 --- flow/embedded_views.h | 8 +++----- flow/layers/clip_rect_layer.cc | 8 ++++---- flow/layers/clip_rrect_layer.cc | 8 ++++---- flow/layers/layer.h | 1 + flow/layers/layer_tree.cc | 2 ++ flow/layers/performance_overlay_layer_unittests.cc | 2 +- flow/layers/platform_view_layer.cc | 2 +- flow/layers/transform_layer.cc | 8 ++++---- flow/raster_cache.cc | 1 + .../ios/framework/Source/FlutterPlatformViews.mm | 6 ++++-- 13 files changed, 39 insertions(+), 25 deletions(-) diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index bf38894b10813..8c974754d8544 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -11,7 +11,9 @@ namespace flutter { CompositorContext::CompositorContext() = default; -CompositorContext::~CompositorContext() = default; + CompositorContext::~CompositorContext() { + delete mutator_statck_; + } void CompositorContext::BeginFrame(ScopedFrame& frame, bool enable_instrumentation) { diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 4266c943d107e..58f5ef6d687f6 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -37,6 +37,16 @@ class CompositorContext { ExternalViewEmbedder* view_embedder() { return view_embedder_; } + MutatorsStack* mutator_statck() { + if (view_embedder_ == nullptr) { + return nullptr; + } + if (context_.mutator_statck_ == nullptr) { + context_.mutator_statck_ = new MutatorsStack(); + } + return context_.mutator_statck_; + } + CompositorContext& context() const { return context_; } const SkMatrix& root_surface_transformation() const { @@ -89,6 +99,7 @@ class CompositorContext { Counter frame_count_; Stopwatch raster_time_; Stopwatch ui_time_; + MutatorsStack* mutator_statck_; void BeginFrame(ScopedFrame& frame, bool enable_instrumentation); diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index d8b346c0be04a..f6749814903cd 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -6,9 +6,6 @@ namespace flutter { -ExternalViewEmbedder::ExternalViewEmbedder() - : transformStack(std::make_shared()){}; - bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { return false; }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 07833ceb9a3f4..1bd44a16f211f 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -24,12 +24,12 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - std::shared_ptr transformStack; + MutatorsStack* mutatorsStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && - transformStack == other.transformStack; + mutatorsStack == other.mutatorsStack; } }; @@ -38,7 +38,7 @@ class EmbeddedViewParams { // FlutterPlatformViewsController which is owned by FlutterViewController. class ExternalViewEmbedder { public: - ExternalViewEmbedder(); + ExternalViewEmbedder() = default; virtual void BeginFrame(SkISize frame_size) = 0; @@ -56,8 +56,6 @@ class ExternalViewEmbedder { FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); - std::shared_ptr transformStack; - }; // ExternalViewEmbedder // A stack of mutators that can be applied to an embedded platform view. diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index e0befe0ab94b1..c42df8aeb447d 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,8 +50,8 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pushClipRect(clip_rect_); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pushClipRect(clip_rect_); } if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); @@ -60,8 +60,8 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pop(); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pop(); } } diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 9dd14727d7115..e15e12d198ea2 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -58,8 +58,8 @@ void ClipRRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pushClipRRect(clip_rrect_); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pushClipRRect(clip_rrect_); } if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); @@ -68,8 +68,8 @@ void ClipRRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pop(); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pop(); } } diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 7400af5468214..efe238f6c3cf7 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -83,6 +83,7 @@ class Layer { SkCanvas* leaf_nodes_canvas; GrContext* gr_context; ExternalViewEmbedder* view_embedder; + MutatorsStack* mutator_stack; const Stopwatch& raster_time; const Stopwatch& ui_time; TextureRegistry& texture_registry; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 70c21604dedb3..44e5438d61bb2 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -83,6 +83,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, frame.canvas(), frame.gr_context(), frame.view_embedder(), + frame.mutator_statck(), frame.context().raster_time(), frame.context().ui_time(), frame.context().texture_registry(), @@ -130,6 +131,7 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { canvas, // canvas nullptr, nullptr, + nullptr, unused_stopwatch, // frame time (dont care) unused_stopwatch, // engine time (dont care) unused_texture_registry, // texture registry (not supported) diff --git a/flow/layers/performance_overlay_layer_unittests.cc b/flow/layers/performance_overlay_layer_unittests.cc index 6f9ba14610d99..a1a3234dc49e8 100644 --- a/flow/layers/performance_overlay_layer_unittests.cc +++ b/flow/layers/performance_overlay_layer_unittests.cc @@ -48,7 +48,7 @@ TEST(PerformanceOverlayLayer, Gold) { flutter::TextureRegistry unused_texture_registry; flutter::Layer::PaintContext paintContext = { - nullptr, surface->getCanvas(), nullptr, nullptr, mock_stopwatch, + nullptr, surface->getCanvas(), nullptr, nullptr, nullptr, mock_stopwatch, mock_stopwatch, unused_texture_registry, nullptr, false}; // Specify font file to ensure the same font across different operation diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index e2f012df6d88d..421f42cf5ee47 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,7 +34,7 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - params.transformStack = context.view_embedder->transformStack; + params.mutatorsStack = context.mutator_stack; SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index a232090cd856f..f29d9f5f0dc70 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -66,12 +66,12 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pushTransform(transform_); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pushTransform(transform_); } PaintChildren(context); - if (context.view_embedder != nullptr) { - context.view_embedder->transformStack->pop(); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pop(); } } diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 4ad18adf172e4..7247241df7665 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -168,6 +168,7 @@ void RasterCache::Prepare(PrerollContext* context, canvas, context->gr_context, nullptr, + nullptr, context->raster_time, context->ui_time, context->texture_registry, diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 82ff2332c6bfd..062306718dce8 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -197,9 +197,11 @@ ResetAnchor(lastView.layer); // Start loop to apply transforms/clips. - std::vector::reverse_iterator iter = params.transformStack->bottom(); + FML_CHECK(params.mutatorsStack != nullptr); + + std::vector::reverse_iterator iter = params.mutatorsStack->bottom(); int64_t clipCount = 0; - while (iter != params.transformStack->top()) { + while (iter != params.mutatorsStack->top()) { switch (iter->type()) { case transform: { CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); From 4eeb64f0df3ce817c3d959eea55e2dae51f2baf9 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 4 Jun 2019 14:40:02 -0700 Subject: [PATCH 20/56] draft vector with unique_ptr --- flow/embedded_views.cc | 31 +++++++++---------- flow/embedded_views.h | 16 +++++----- .../framework/Source/FlutterPlatformViews.mm | 8 ++--- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index f6749814903cd..e262b8519eeff 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -11,37 +11,36 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { }; void MutatorsStack::pushClipRect(const SkRect& rect) { - Mutator element = Mutator(); - element.setType(clip_rect); - element.setRect(rect); - vector_.push_back(element); + std::unique_ptr element = std::make_unique(); + element->setType(clip_rect); + element->setRect(rect); + vector_.push_back(std::move(element)); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { - Mutator element = Mutator(); - element.setType(clip_rrect); - element.setRRect(rrect); - vector_.push_back(element); + std::unique_ptr element = std::make_unique(); + element->setType(clip_rrect); + element->setRRect(rrect); + vector_.push_back(std::move(element)); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { - Mutator element = Mutator(); - element.setType(transform); - element.setMatrix(matrix); - vector_.push_back(element); + std::unique_ptr element = std::make_unique(); + element->setType(transform); + element->setMatrix(matrix); + vector_.push_back(std::move(element)); }; void MutatorsStack::pop() { vector_.pop_back(); } -std::vector::reverse_iterator -MutatorsStack::top() { +const std::vector>::const_reverse_iterator MutatorsStack::top() { return vector_.rend(); } -std::vector::reverse_iterator -MutatorsStack::bottom() { +const std::vector>::const_reverse_iterator + MutatorsStack::bottom() { return vector_.rbegin(); } diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 1bd44a16f211f..dff1e8a0be105 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -78,16 +78,16 @@ class MutatorsStack { void pop(); // Returns the iterator points to the top of the stack.. - std::vector::reverse_iterator top(); + const std::vector>::const_reverse_iterator top(); // Returns an iterator pointing to the bottom of the stack. - std::vector::reverse_iterator bottom(); + const std::vector>::const_reverse_iterator bottom(); bool operator==(const MutatorsStack& other) const { return vector_ == other.vector_; } private: - std::vector vector_; + std::vector> vector_; }; // MutatorsStack enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; @@ -99,11 +99,11 @@ class Mutator { void setRRect(const SkRRect& rrect) { rrect_ = rrect; } void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } - MutatorType type() { return type_; } - SkRect rect() { return rect_; } - SkRRect rrect() { return rrect_; } - SkPath path() { return path_; } - SkMatrix matrix() { return matrix_; } + MutatorType type() const { return type_; } + SkRect rect() const { return rect_; } + SkRRect rrect() const { return rrect_; } + SkPath path() const { return path_; } + SkMatrix matrix() const { return matrix_; } bool operator==(const Mutator& other) const { if (type_ != other.type_) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 062306718dce8..9818c4f5caa93 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -199,12 +199,12 @@ // Start loop to apply transforms/clips. FML_CHECK(params.mutatorsStack != nullptr); - std::vector::reverse_iterator iter = params.mutatorsStack->bottom(); + auto iter = params.mutatorsStack->bottom(); int64_t clipCount = 0; while (iter != params.mutatorsStack->top()) { - switch (iter->type()) { + switch (iter->get()->type()) { case transform: { - CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); + CATransform3D transform = GetCATransform3DFromSkMatrix(iter->get()->matrix()); lastView.layer.transform = CATransform3DConcat(lastView.layer.transform, transform); break; } @@ -219,7 +219,7 @@ view = [[UIView alloc] initWithFrame:lastView.bounds]; [view addSubview:lastView]; } - PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); + PerformClip(view, iter->get()->type(), iter->get()->rect(), iter->get()->rrect(), iter->get()->path()); ResetAnchor(view.layer); lastView = view; break; From 6d789013789d71d26452b492727a929cd47f3e22 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 4 Jun 2019 15:19:06 -0700 Subject: [PATCH 21/56] more review fixes --- flow/compositor_context.cc | 6 +- flow/embedded_views.cc | 5 +- flow/embedded_views.h | 10 +- .../performance_overlay_layer_unittests.cc | 7 +- .../framework/Source/FlutterPlatformViews.mm | 97 ++++++++++++------- .../Source/FlutterPlatformViews_Internal.h | 8 ++ .../Source/FlutterPlatformViews_Internal.mm | 8 +- 7 files changed, 89 insertions(+), 52 deletions(-) diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index 8c974754d8544..ece208a445552 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -11,9 +11,9 @@ namespace flutter { CompositorContext::CompositorContext() = default; - CompositorContext::~CompositorContext() { - delete mutator_statck_; - } +CompositorContext::~CompositorContext() { + delete mutator_statck_; +} void CompositorContext::BeginFrame(ScopedFrame& frame, bool enable_instrumentation) { diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index e262b8519eeff..e5b64e27d7dc1 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -35,12 +35,13 @@ void MutatorsStack::pop() { vector_.pop_back(); } -const std::vector>::const_reverse_iterator MutatorsStack::top() { +const std::vector>::const_reverse_iterator +MutatorsStack::top() { return vector_.rend(); } const std::vector>::const_reverse_iterator - MutatorsStack::bottom() { +MutatorsStack::bottom() { return vector_.rbegin(); } diff --git a/flow/embedded_views.h b/flow/embedded_views.h index dff1e8a0be105..e3cc6bfc1cdbe 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -60,11 +60,13 @@ class ExternalViewEmbedder { // A stack of mutators that can be applied to an embedded platform view. // -// The stack may include mutators like transforms and clips, each mutator applies to all the mutators that are below it in the stack -// and to the embedded view. +// The stack may include mutators like transforms and clips, each mutator +// applies to all the mutators that are below it in the stack and to the +// embedded view. // -// For example consider the following stack: [T1, T2, T3], where T1 is the top of the stack and T3 is the bottom of the stack. -// Applying this mutators stack to a platform view P1 will result in T1(T2(T2(P1))). +// For example consider the following stack: [T1, T2, T3], where T1 is the top +// of the stack and T3 is the bottom of the stack. Applying this mutators stack +// to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { public: void pushClipRect(const SkRect& rect); diff --git a/flow/layers/performance_overlay_layer_unittests.cc b/flow/layers/performance_overlay_layer_unittests.cc index a1a3234dc49e8..2c7668e9ab9bc 100644 --- a/flow/layers/performance_overlay_layer_unittests.cc +++ b/flow/layers/performance_overlay_layer_unittests.cc @@ -48,8 +48,11 @@ TEST(PerformanceOverlayLayer, Gold) { flutter::TextureRegistry unused_texture_registry; flutter::Layer::PaintContext paintContext = { - nullptr, surface->getCanvas(), nullptr, nullptr, nullptr, mock_stopwatch, - mock_stopwatch, unused_texture_registry, nullptr, false}; + nullptr, surface->getCanvas(), + nullptr, nullptr, + nullptr, mock_stopwatch, + mock_stopwatch, unused_texture_registry, + nullptr, false}; // Specify font file to ensure the same font across different operation // systems. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 9818c4f5caa93..b4e282c870c4b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -183,45 +183,58 @@ return canvases; } -void FlutterPlatformViewsController::CompositeWithParams( - int view_id, - const flutter::EmbeddedViewParams& params) { - UIView* touch_interceptor = touch_interceptors_[view_id].get(); - - CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); - touch_interceptor.frame = frame; - UIView* lastView = touch_interceptor; +// Build a chain of UIViews that applies the mutations described by mutatorsStack. +// +// Clips are applied by adding a super view with the CALayer mask. Transforms are applied to the +// view that's at the head of the chain. For example the following mutators stack [T_1, C_2, T_3, +// T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the following +// UIView tree: +// +// C_2 -> C_5 -> PLATFORM_VIEW +// (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2) +// +// T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW. +// +// UIView instances used for clip mutations are re-used when possible. +// For example if we the mutators stack is updated to [T_1, C_7, T_3, T_4, C_8, T_9], we do not +// remove the previous superviews and re-create new views. Instead, we reuse the superviews that was +// used to perform clips in the previous example and perform the new clips on the same views. +// +// Returns the UIView that's at the top of the generated chain(C_2 for the example above). +UIView* FlutterPlatformViewsController::ApplyMutators(MutatorsStack& mutators_stack, + UIView* embedded_view, + int view_id) { + UIView* head = embedded_view; // Reset everything related to transform. - lastView.layer.transform = CATransform3DIdentity; - ResetAnchor(lastView.layer); + head.layer.transform = CATransform3DIdentity; + ResetAnchor(head.layer); // Start loop to apply transforms/clips. - FML_CHECK(params.mutatorsStack != nullptr); - - auto iter = params.mutatorsStack->bottom(); + auto iter = mutators_stack.bottom(); int64_t clipCount = 0; - while (iter != params.mutatorsStack->top()) { + while (iter != mutators_stack.top()) { switch (iter->get()->type()) { case transform: { CATransform3D transform = GetCATransform3DFromSkMatrix(iter->get()->matrix()); - lastView.layer.transform = CATransform3DConcat(lastView.layer.transform, transform); + head.layer.transform = CATransform3DConcat(head.layer.transform, transform); break; } case clip_rect: case clip_rrect: case clip_path: { - UIView* view = lastView.superview; + UIView* view = head.superview; // if we need more clips operations than last time, create a new view. ++clipCount; if (clipCount > clip_count_[view_id]) { - [lastView removeFromSuperview]; - view = [[UIView alloc] initWithFrame:lastView.bounds]; - [view addSubview:lastView]; + [head removeFromSuperview]; + view = [[UIView alloc] initWithFrame:head.bounds]; + [view addSubview:head]; } - PerformClip(view, iter->get()->type(), iter->get()->rect(), iter->get()->rrect(), iter->get()->path()); + PerformClip(view, iter->get()->type(), iter->get()->rect(), iter->get()->rrect(), + iter->get()->path()); ResetAnchor(view.layer); - lastView = view; + head = view; break; } } @@ -236,27 +249,37 @@ // 500 points in UIKit. And until this point, we did all the calculation based on the flow // resolution. So we need to scale down to match UIKit's logical resolution. CGFloat screenScale = [UIScreen mainScreen].scale; - lastView.layer.transform = CATransform3DConcat( - lastView.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); + head.layer.transform = CATransform3DConcat( + head.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. - int64_t extraClipsFromLastTime = clip_count_[view_id] - clipCount; - if (extraClipsFromLastTime > 0 && lastView.superview) { - [lastView removeFromSuperview]; - UIView* superview = lastView.superview; - while (extraClipsFromLastTime > 0) { - UIView* superSuperView = superview.superview; - [superview removeFromSuperview]; - [superview release]; - superview = superSuperView; - } - [flutter_view_.get() addSubview:lastView]; - } clip_count_[view_id] = clipCount; + bool hasExtraClipViews = clip_count_[view_id] - clipCount > 0; + if (!hasExtraClipViews) { + return head; + } + + [head removeFromSuperview]; + + [root_views_[view_id] removeFromSuperview]; + [root_views_[view_id] release]; + + return head; +} + +void FlutterPlatformViewsController::CompositeWithParams( + int view_id, + const flutter::EmbeddedViewParams& params) { + UIView* touch_interceptor = touch_interceptors_[view_id].get(); + + CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); + touch_interceptor.frame = frame; + FML_CHECK(params.mutatorsStack != nullptr); + UIView* head = ApplyMutators(*params.mutatorsStack, touch_interceptor, view_id); // If we have clips, replace root view with the top parent view. - if (lastView != touch_interceptor) { - root_views_[view_id] = fml::scoped_nsobject([lastView retain]); + if (head != touch_interceptor) { + root_views_[view_id] = fml::scoped_nsobject([head retain]); } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 376faf0b77c6a..c7d1ae33f4e52 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -113,9 +113,16 @@ class FlutterPlatformViewsController { std::map>> factories_; std::map>> views_; std::map> touch_interceptors_; + // Mapping a platform view ID to the top most parent view (root_view) who is a direct child to the + // `flutter_view_`. + // + // The platform view with the view ID is a child of the root view; or in some cases the platform + // view is the root view itself. std::map> root_views_; // Mapping a platform view ID to its latest composition params. std::map current_composition_params_; + // Mapping a platform view ID to the count of the clipping operations that was applied to the + // platform view. std::map clip_count_; std::map> overlays_; // The GrContext that is currently used by all of the overlay surfaces. @@ -149,6 +156,7 @@ class FlutterPlatformViewsController { void EnsureGLOverlayInitialized(int64_t overlay_id, std::shared_ptr gl_context, GrContext* gr_context); + UIView* ApplyMutators(MutatorsStack& mutators_stack, UIView* embedded_view, int view_id); void CompositeWithParams(int view_id, const flutter::EmbeddedViewParams& params); FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index f49333bf3631f..0ac6e9562680f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -105,10 +105,10 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { } void PerformClip(UIView* view, - flutter::MutatorType type, - const SkRect& rect, - const SkRRect& rrect, - const SkPath& path) { + flutter::MutatorType type, + const SkRect& rect, + const SkRRect& rrect, + const SkPath& path) { FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || type == flutter::clip_path); switch (type) { From e494853d7899f2d724f3afb82c830cd40712914d Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 5 Jun 2019 13:52:21 -0700 Subject: [PATCH 22/56] unittests for mutator stack --- flow/BUILD.gn | 1 + flow/embedded_views.h | 84 ++++++++++-------- flow/mutators_stack_unittests.cc | 144 +++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 35 deletions(-) create mode 100644 flow/mutators_stack_unittests.cc diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 82946931baeda..769bb27db00ca 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -116,6 +116,7 @@ executable("flow_unittests") { "layers/performance_overlay_layer_unittests.cc", "matrix_decomposition_unittests.cc", "raster_cache_unittests.cc", + "mutators_stack_unittests.cc" ] deps = [ diff --git a/flow/embedded_views.h b/flow/embedded_views.h index e3cc6bfc1cdbe..d7188d2bc1dbc 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -58,40 +58,6 @@ class ExternalViewEmbedder { }; // ExternalViewEmbedder -// A stack of mutators that can be applied to an embedded platform view. -// -// The stack may include mutators like transforms and clips, each mutator -// applies to all the mutators that are below it in the stack and to the -// embedded view. -// -// For example consider the following stack: [T1, T2, T3], where T1 is the top -// of the stack and T3 is the bottom of the stack. Applying this mutators stack -// to a platform view P1 will result in T1(T2(T2(P1))). -class MutatorsStack { - public: - void pushClipRect(const SkRect& rect); - void pushClipRRect(const SkRRect& rrect); - void pushClipPath(const SkPath& path); - - void pushTransform(const SkMatrix& matrix); - - // Removes the `Mutator` on the top of the stack - // and destroys it. - void pop(); - - // Returns the iterator points to the top of the stack.. - const std::vector>::const_reverse_iterator top(); - // Returns an iterator pointing to the bottom of the stack. - const std::vector>::const_reverse_iterator bottom(); - - bool operator==(const MutatorsStack& other) const { - return vector_ == other.vector_; - } - - private: - std::vector> vector_; -}; // MutatorsStack - enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { @@ -114,7 +80,7 @@ class Mutator { if (type_ == clip_rect && rect_ == other.rect_) { return true; } - if (type_ == clip_rect && rrect_ == other.rrect_) { + if (type_ == clip_rrect && rrect_ == other.rrect_) { return true; } if (type_ == clip_path && path_ == other.path_) { @@ -126,6 +92,8 @@ class Mutator { return false; } + bool operator!=(const Mutator& other) const { return !operator==(other); } + bool isClipType() { return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; } @@ -138,6 +106,52 @@ class Mutator { SkMatrix matrix_; }; // Mutator +// A stack of mutators that can be applied to an embedded platform view. +// +// The stack may include mutators like transforms and clips, each mutator +// applies to all the mutators that are below it in the stack and to the +// embedded view. +// +// For example consider the following stack: [T1, T2, T3], where T1 is the top +// of the stack and T3 is the bottom of the stack. Applying this mutators stack +// to a platform view P1 will result in T1(T2(T2(P1))). +class MutatorsStack { + public: + void pushClipRect(const SkRect& rect); + void pushClipRRect(const SkRRect& rrect); + void pushClipPath(const SkPath& path); + + void pushTransform(const SkMatrix& matrix); + + // Removes the `Mutator` on the top of the stack + // and destroys it. + void pop(); + + // Returns the iterator points to the top of the stack.. + const std::vector>::const_reverse_iterator top(); + // Returns an iterator pointing to the bottom of the stack. + const std::vector>::const_reverse_iterator bottom(); + + bool operator==(const MutatorsStack& other) const { + if (vector_.size() != other.vector_.size()) { + return false; + } + for (size_t i = 0; i < vector_.size(); i++) { + if (*(vector_[i]) != *(other.vector_[i])) { + return false; + } + } + return true; + } + + bool operator!=(const MutatorsStack& other) const { + return !operator==(other); + } + + private: + std::vector> vector_; +}; // MutatorsStack + } // namespace flutter #endif // FLUTTER_FLOW_EMBEDDED_VIEWS_H_ diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc new file mode 100644 index 0000000000000..5e0b16065b125 --- /dev/null +++ b/flow/mutators_stack_unittests.cc @@ -0,0 +1,144 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/flow/embedded_views.h" +#include "gtest/gtest.h" + +TEST(MutatorsStack, Initialization) { + flutter::MutatorsStack stack; + ASSERT_TRUE(true); +} + +TEST(MutatorsStack, PushClipRect) { + flutter::MutatorsStack stack; + SkRect rect; + stack.pushClipRect(rect); + auto iter = stack.bottom(); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->get()->rect() == rect); + +} + +TEST(MutatorsStack, PushClipRRect) { + flutter::MutatorsStack stack; + SkRRect rrect; + stack.pushClipRRect(rrect); + auto iter = stack.bottom(); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->get()->rrect() == rrect); +} + +TEST(MutatorsStack, PushTransform) { + flutter::MutatorsStack stack; + SkMatrix matrix; + stack.pushTransform(matrix); + auto iter = stack.bottom(); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->get()->matrix() == matrix); +} + +TEST(MutatorsStack, Pop) { + flutter::MutatorsStack stack; + SkMatrix matrix; + stack.pushTransform(matrix); + stack.pop(); + auto iter = stack.bottom(); + ASSERT_TRUE(iter == stack.top()); +} + +TEST(MutatorsStack, Traversal) { + flutter::MutatorsStack stack; + SkMatrix matrix; + stack.pushTransform(matrix); + SkRect rect; + stack.pushClipRect(rect); + SkRRect rrect; + stack.pushClipRRect(rrect); + auto iter = stack.bottom(); + int index = 0; + while(iter != stack.top()) { + switch (index) { + case 0: + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->get()->rrect() == rrect); + break; + case 1: + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->get()->rect() == rect); + break; + case 2: + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->get()->matrix() == matrix); + break; + default: + break; + } + ++iter; + ++index; + } +} + +TEST(MutatorsStack, Equality) { + flutter::MutatorsStack stack; + SkMatrix matrix = SkMatrix::MakeScale(1,1); + stack.pushTransform(matrix); + SkRect rect = SkRect::MakeEmpty(); + stack.pushClipRect(rect); + SkRRect rrect = SkRRect::MakeEmpty(); + stack.pushClipRRect(rrect); + + flutter::MutatorsStack stackOther; + SkMatrix matrixOther = SkMatrix::MakeScale(1,1); + stackOther.pushTransform(matrixOther); + SkRect rectOther = SkRect::MakeEmpty(); + stackOther.pushClipRect(rectOther); + SkRRect rrectOther = SkRRect::MakeEmpty(); + stackOther.pushClipRRect(rrectOther); + + ASSERT_TRUE(stack == stackOther); +} + +TEST(Mutator, Equality) { + flutter::Mutator mutator; + flutter::Mutator otherMutator; + mutator.setType(flutter::MutatorType::transform); + otherMutator.setType(flutter::MutatorType::transform); + SkMatrix matrix; + mutator.setMatrix(matrix); + otherMutator.setMatrix(matrix); + ASSERT_TRUE(mutator == otherMutator); + + mutator.setType(flutter::MutatorType::clip_rect); + otherMutator.setType(flutter::MutatorType::clip_rect); + SkRect rect; + mutator.setRect(rect); + otherMutator.setRect(rect); + ASSERT_TRUE(mutator == otherMutator); + + mutator.setType(flutter::MutatorType::clip_rrect); + otherMutator.setType(flutter::MutatorType::clip_rrect); + SkRRect rrect; + mutator.setRRect(rrect); + otherMutator.setRRect(rrect); + ASSERT_TRUE(mutator == otherMutator); + + flutter::Mutator notEqualMutator; + notEqualMutator.setType(flutter::MutatorType::transform); + notEqualMutator.setMatrix(matrix); + ASSERT_FALSE(notEqualMutator == mutator); +} + +TEST(Mutator, UnEquality) { + flutter::Mutator mutator; + mutator.setType(flutter::MutatorType::clip_rect); + SkRect rect; + mutator.setRect(rect); + + SkMatrix matrix; + flutter::Mutator notEqualMutator; + notEqualMutator.setType(flutter::MutatorType::transform); + notEqualMutator.setMatrix(matrix); + ASSERT_TRUE(notEqualMutator != mutator); +} + From 81e5c196f394ec3ee20c808d094cded6361532a0 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 5 Jun 2019 14:59:01 -0700 Subject: [PATCH 23/56] move stack to paint context complete --- flow/compositor_context.cc | 4 +--- flow/compositor_context.h | 11 ----------- flow/layers/layer_tree.cc | 6 +++++- .../ios/framework/Source/FlutterPlatformViews.mm | 3 ++- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index ece208a445552..bf38894b10813 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -11,9 +11,7 @@ namespace flutter { CompositorContext::CompositorContext() = default; -CompositorContext::~CompositorContext() { - delete mutator_statck_; -} +CompositorContext::~CompositorContext() = default; void CompositorContext::BeginFrame(ScopedFrame& frame, bool enable_instrumentation) { diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 58f5ef6d687f6..4266c943d107e 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -37,16 +37,6 @@ class CompositorContext { ExternalViewEmbedder* view_embedder() { return view_embedder_; } - MutatorsStack* mutator_statck() { - if (view_embedder_ == nullptr) { - return nullptr; - } - if (context_.mutator_statck_ == nullptr) { - context_.mutator_statck_ = new MutatorsStack(); - } - return context_.mutator_statck_; - } - CompositorContext& context() const { return context_; } const SkMatrix& root_surface_transformation() const { @@ -99,7 +89,6 @@ class CompositorContext { Counter frame_count_; Stopwatch raster_time_; Stopwatch ui_time_; - MutatorsStack* mutator_statck_; void BeginFrame(ScopedFrame& frame, bool enable_instrumentation); diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 44e5438d61bb2..db82193bc838f 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -78,12 +78,14 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, } } + MutatorsStack* stack = new MutatorsStack(); + Layer::PaintContext context = { (SkCanvas*)&internal_nodes_canvas, frame.canvas(), frame.gr_context(), frame.view_embedder(), - frame.mutator_statck(), + stack, frame.context().raster_time(), frame.context().ui_time(), frame.context().texture_registry(), @@ -92,6 +94,8 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, if (root_layer_->needs_painting()) root_layer_->Paint(context); + + delete stack; } sk_sp LayerTree::Flatten(const SkRect& bounds) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index b4e282c870c4b..ae2bbf87ece10 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -205,6 +205,7 @@ UIView* embedded_view, int view_id) { UIView* head = embedded_view; + head.clipsToBounds = YES; // Reset everything related to transform. head.layer.transform = CATransform3DIdentity; @@ -228,7 +229,7 @@ ++clipCount; if (clipCount > clip_count_[view_id]) { [head removeFromSuperview]; - view = [[UIView alloc] initWithFrame:head.bounds]; + view = [[UIView alloc] initWithFrame:flutter_view_.get().bounds]; [view addSubview:head]; } PerformClip(view, iter->get()->type(), iter->get()->rect(), iter->get()->rrect(), From ea11fad292ca7d2d84cb4e21b57ab9092f9eb931 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 5 Jun 2019 15:09:33 -0700 Subject: [PATCH 24/56] formatting --- flow/mutators_stack_unittests.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 5e0b16065b125..362afad8b7327 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -17,7 +17,6 @@ TEST(MutatorsStack, PushClipRect) { auto iter = stack.bottom(); ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); ASSERT_TRUE(iter->get()->rect() == rect); - } TEST(MutatorsStack, PushClipRRect) { @@ -57,7 +56,7 @@ TEST(MutatorsStack, Traversal) { stack.pushClipRRect(rrect); auto iter = stack.bottom(); int index = 0; - while(iter != stack.top()) { + while (iter != stack.top()) { switch (index) { case 0: ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); @@ -81,7 +80,7 @@ TEST(MutatorsStack, Traversal) { TEST(MutatorsStack, Equality) { flutter::MutatorsStack stack; - SkMatrix matrix = SkMatrix::MakeScale(1,1); + SkMatrix matrix = SkMatrix::MakeScale(1, 1); stack.pushTransform(matrix); SkRect rect = SkRect::MakeEmpty(); stack.pushClipRect(rect); @@ -89,7 +88,7 @@ TEST(MutatorsStack, Equality) { stack.pushClipRRect(rrect); flutter::MutatorsStack stackOther; - SkMatrix matrixOther = SkMatrix::MakeScale(1,1); + SkMatrix matrixOther = SkMatrix::MakeScale(1, 1); stackOther.pushTransform(matrixOther); SkRect rectOther = SkRect::MakeEmpty(); stackOther.pushClipRect(rectOther); @@ -141,4 +140,3 @@ TEST(Mutator, UnEquality) { notEqualMutator.setMatrix(matrix); ASSERT_TRUE(notEqualMutator != mutator); } - From 5deaaeb12790efe9b3e4fd2ca6ff891fb58c4203 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 10:48:57 -0700 Subject: [PATCH 25/56] draft --- flow/embedded_views.cc | 8 +++ flow/embedded_views.h | 11 ++++ flow/layers/clip_path_layer.cc | 6 ++ flow/mutators_stack_unittests.cc | 20 ++++++ .../framework/Source/FlutterPlatformViews.mm | 2 + .../Source/FlutterPlatformViews_Internal.h | 3 + .../Source/FlutterPlatformViews_Internal.mm | 66 ++++++++++++++++++- 7 files changed, 115 insertions(+), 1 deletion(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index e5b64e27d7dc1..7436aefff95d3 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -24,6 +24,14 @@ void MutatorsStack::pushClipRRect(const SkRRect& rrect) { vector_.push_back(std::move(element)); }; + void MutatorsStack::pushClipPath(const SkPath& path) { + std::unique_ptr element = std::make_unique(); + element->setType(clip_path); + element->setPath(path); + vector_.push_back(std::move(element)); + }; + + void MutatorsStack::pushTransform(const SkMatrix& matrix) { std::unique_ptr element = std::make_unique(); element->setType(transform); diff --git a/flow/embedded_views.h b/flow/embedded_views.h index d7188d2bc1dbc..915c3f4c8a8e9 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -27,6 +27,11 @@ class EmbeddedViewParams { MutatorsStack* mutatorsStack; bool operator==(const EmbeddedViewParams& other) const { + FML_LOG(ERROR)<< "param equal"; + FML_LOG(ERROR)<< "offset equal" << (offsetPixels == other.offsetPixels); + FML_LOG(ERROR)<< "sizePoints equal" << (sizePoints == other.sizePoints); + FML_LOG(ERROR)<< "mutatorsStack equal" << (mutatorsStack == other.mutatorsStack); + return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && mutatorsStack == other.mutatorsStack; @@ -65,6 +70,7 @@ class Mutator { void setType(const MutatorType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } void setRRect(const SkRRect& rrect) { rrect_ = rrect; } + void setPath(const SkPath& path) { path_ = path; } void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } MutatorType type() const { return type_; } @@ -74,6 +80,9 @@ class Mutator { SkMatrix matrix() const { return matrix_; } bool operator==(const Mutator& other) const { + if (type_ == clip_path) { + FML_LOG(ERROR)<< "path equal" << (path_ == other.path_); + } if (type_ != other.type_) { return false; } @@ -133,6 +142,8 @@ class MutatorsStack { const std::vector>::const_reverse_iterator bottom(); bool operator==(const MutatorsStack& other) const { + FML_LOG(ERROR)<< "stack equal"; + if (vector_.size() != other.vector_.size()) { return false; } diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index cdca4619a3707..d88aafcccfa88 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -60,6 +60,9 @@ void ClipPathLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipPath(clip_path_, clip_behavior_ != Clip::hardEdge); + if (context.mutator_stack != nullptr) { + context.mutator_stack->pushClipPath(clip_path_); + } if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } @@ -67,6 +70,9 @@ void ClipPathLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } + if (context.mutator_stack != nullptr) { + context.mutator_stack->pop(); + } } } // namespace flutter diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 362afad8b7327..a3f04b168c9bf 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -28,6 +28,15 @@ TEST(MutatorsStack, PushClipRRect) { ASSERT_TRUE(iter->get()->rrect() == rrect); } +TEST(MutatorsStack, PushClipPath) { + flutter::MutatorsStack stack; + SkPath path; + stack.pushClipPath(path); + auto iter = stack.bottom(); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_path); + ASSERT_TRUE(iter->get()->path() == path); +} + TEST(MutatorsStack, PushTransform) { flutter::MutatorsStack stack; SkMatrix matrix; @@ -86,6 +95,8 @@ TEST(MutatorsStack, Equality) { stack.pushClipRect(rect); SkRRect rrect = SkRRect::MakeEmpty(); stack.pushClipRRect(rrect); + SkPath path; + stack.pushClipPath(path); flutter::MutatorsStack stackOther; SkMatrix matrixOther = SkMatrix::MakeScale(1, 1); @@ -94,6 +105,8 @@ TEST(MutatorsStack, Equality) { stackOther.pushClipRect(rectOther); SkRRect rrectOther = SkRRect::MakeEmpty(); stackOther.pushClipRRect(rrectOther); + SkPath otherPath; + stackOther.pushClipPath(otherPath); ASSERT_TRUE(stack == stackOther); } @@ -122,6 +135,13 @@ TEST(Mutator, Equality) { otherMutator.setRRect(rrect); ASSERT_TRUE(mutator == otherMutator); + mutator.setType(flutter::MutatorType::clip_path); + otherMutator.setType(flutter::MutatorType::clip_path); + SkPath path; + mutator.setPath(path); + otherMutator.setPath(path); + ASSERT_TRUE(mutator == otherMutator); + flutter::Mutator notEqualMutator; notEqualMutator.setType(flutter::MutatorType::transform); notEqualMutator.setMatrix(matrix); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index ae2bbf87ece10..b10f523b9c2d6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -293,8 +293,10 @@ // Do nothing if the params didn't change. if (current_composition_params_.count(view_id) == 1 && current_composition_params_[view_id] == params) { + NSLog(@"not changed"); return picture_recorders_[view_id]->getRecordingCanvas(); } + NSLog(@"changed"); current_composition_params_[view_id] = params; CompositeWithParams(view_id, params); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index c7d1ae33f4e52..6572453fc93a7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -39,6 +39,9 @@ void ClipRect(UIView* view, const SkRect& clipSkRect); // Perform clip rounded rect on the `view` using `clipSkRRect`. void ClipRRect(UIView* view, const SkRRect& clipSkRRect); +// Perform clip path on the `view` using `path`. +void ClipPath(UIView *view, const SkPath &path); + // Perform a clip operation on the `view`. // Uses either `rect`, `rrect` or `path` to perform the clip based on the `type`. void PerformClip(UIView* view, diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 0ac6e9562680f..6ed893e8538c2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -104,6 +104,70 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { CGPathRelease(pathRef); } +void ClipPath(UIView *view, const SkPath &path) { + CGMutablePathRef pathRef = CGPathCreateMutable(); + if (!path.isValid()) { + return; + } + if (path.isEmpty()) { + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; + clip.path = pathRef; + view.layer.mask = clip; + CGPathRelease(pathRef); + return; + } + + // Loop through all verbs and translate them into CGPath + + SkPath::Iter iter(path, true); + SkPoint pts[4]; + SkPath::Verb verb = iter.next(pts); + while(verb != SkPath::kDone_Verb) { + switch (verb) { + case SkPath::kMove_Verb: { + NSLog(@"verb move"); + CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y()); + break; + } + case SkPath::kLine_Verb: { + NSLog(@"verb line"); + CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y()); + break; + } + case SkPath::kQuad_Verb: { + NSLog(@"verb quad"); + CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); + break; + } + case SkPath::kConic_Verb: { + NSLog(@"verb conic"); + break; + } + case SkPath::kCubic_Verb: { + NSLog(@"verb cubic"); + CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y()); + break; + } + case SkPath::kClose_Verb: { + NSLog(@"verb close"); + CGPathCloseSubpath(pathRef); + break; + } + case SkPath::kDone_Verb: { + NSLog(@"verb done"); + break; + } + } + verb = iter.next(pts); + } + + NSLog(@"final path %@", pathRef); + CAShapeLayer* clip = [[CAShapeLayer alloc] init]; + clip.path = pathRef; + view.layer.mask = clip; + CGPathRelease(pathRef); +} + void PerformClip(UIView* view, flutter::MutatorType type, const SkRect& rect, @@ -119,7 +183,7 @@ void PerformClip(UIView* view, ClipRRect(view, rrect); break; case flutter::clip_path: - // TODO(cyanglaz): Add clip path + ClipPath(view, path); break; default: break; From 0f70a447f021800d9f5ea8048fcdae0579d0e4fd Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 12:46:55 -0700 Subject: [PATCH 26/56] mutator stack compare fixes --- flow/embedded_views.h | 93 ++++++++++++++++++++------------------- flow/layers/layer_tree.cc | 2 +- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index d7188d2bc1dbc..3c2cef37fce77 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -17,51 +17,10 @@ namespace flutter { -class MutatorsStack; -class Mutator; - -class EmbeddedViewParams { - public: - SkPoint offsetPixels; - SkSize sizePoints; - MutatorsStack* mutatorsStack; - - bool operator==(const EmbeddedViewParams& other) const { - return offsetPixels == other.offsetPixels && - sizePoints == other.sizePoints && - mutatorsStack == other.mutatorsStack; - } -}; - -// This is only used on iOS when running in a non headless mode, -// in this case ExternalViewEmbedder is a reference to the -// FlutterPlatformViewsController which is owned by FlutterViewController. -class ExternalViewEmbedder { - public: - ExternalViewEmbedder() = default; - - virtual void BeginFrame(SkISize frame_size) = 0; - - virtual void PrerollCompositeEmbeddedView(int view_id) = 0; - - virtual std::vector GetCurrentCanvases() = 0; - - // Must be called on the UI thread. - virtual SkCanvas* CompositeEmbeddedView(int view_id, - const EmbeddedViewParams& params) = 0; - - virtual bool SubmitFrame(GrContext* context); - - virtual ~ExternalViewEmbedder() = default; - - FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); - -}; // ExternalViewEmbedder - enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { - public: +public: void setType(const MutatorType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } void setRRect(const SkRRect& rrect) { rrect_ = rrect; } @@ -74,6 +33,7 @@ class Mutator { SkMatrix matrix() const { return matrix_; } bool operator==(const Mutator& other) const { + if (type_ != other.type_) { return false; } @@ -89,6 +49,7 @@ class Mutator { if (type_ == transform && matrix_ == other.matrix_) { return true; } + return false; } @@ -98,7 +59,7 @@ class Mutator { return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; } - private: +private: MutatorType type_; SkRect rect_; SkRRect rrect_; @@ -116,7 +77,7 @@ class Mutator { // of the stack and T3 is the bottom of the stack. Applying this mutators stack // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { - public: +public: void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); @@ -133,11 +94,13 @@ class MutatorsStack { const std::vector>::const_reverse_iterator bottom(); bool operator==(const MutatorsStack& other) const { + if (vector_.size() != other.vector_.size()) { return false; } + for (size_t i = 0; i < vector_.size(); i++) { - if (*(vector_[i]) != *(other.vector_[i])) { + if (*(vector_[i].get()) != *(other.vector_[i].get())) { return false; } } @@ -148,10 +111,48 @@ class MutatorsStack { return !operator==(other); } - private: +private: std::vector> vector_; }; // MutatorsStack +class EmbeddedViewParams { + public: + SkPoint offsetPixels; + SkSize sizePoints; + MutatorsStack* mutatorsStack; + + bool operator==(const EmbeddedViewParams& other) const { + return offsetPixels == other.offsetPixels && + sizePoints == other.sizePoints && + *mutatorsStack == *(other.mutatorsStack); + } +}; + +// This is only used on iOS when running in a non headless mode, +// in this case ExternalViewEmbedder is a reference to the +// FlutterPlatformViewsController which is owned by FlutterViewController. +class ExternalViewEmbedder { + public: + ExternalViewEmbedder() = default; + + virtual void BeginFrame(SkISize frame_size) = 0; + + virtual void PrerollCompositeEmbeddedView(int view_id) = 0; + + virtual std::vector GetCurrentCanvases() = 0; + + // Must be called on the UI thread. + virtual SkCanvas* CompositeEmbeddedView(int view_id, + const EmbeddedViewParams& params) = 0; + + virtual bool SubmitFrame(GrContext* context); + + virtual ~ExternalViewEmbedder() = default; + + FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); + +}; // ExternalViewEmbedder + } // namespace flutter #endif // FLUTTER_FLOW_EMBEDDED_VIEWS_H_ diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index db82193bc838f..470e8cb1ed77f 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -77,7 +77,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, internal_nodes_canvas.addCanvas(overlay_canvases[i]); } } - + MutatorsStack* stack = new MutatorsStack(); Layer::PaintContext context = { From 32d2681e8e112072fead8050d082b4ccf393e374 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 12:47:02 -0700 Subject: [PATCH 27/56] mutator stack compare fixes --- flow/embedded_views.h | 14 ++++++-------- flow/layers/layer_tree.cc | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 3c2cef37fce77..df08c29f9ba9e 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -20,7 +20,7 @@ namespace flutter { enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { -public: + public: void setType(const MutatorType type) { type_ = type; } void setRect(const SkRect& rect) { rect_ = rect; } void setRRect(const SkRRect& rrect) { rrect_ = rrect; } @@ -33,7 +33,6 @@ class Mutator { SkMatrix matrix() const { return matrix_; } bool operator==(const Mutator& other) const { - if (type_ != other.type_) { return false; } @@ -59,7 +58,7 @@ class Mutator { return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; } -private: + private: MutatorType type_; SkRect rect_; SkRRect rrect_; @@ -77,7 +76,7 @@ class Mutator { // of the stack and T3 is the bottom of the stack. Applying this mutators stack // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { -public: + public: void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); @@ -94,7 +93,6 @@ class MutatorsStack { const std::vector>::const_reverse_iterator bottom(); bool operator==(const MutatorsStack& other) const { - if (vector_.size() != other.vector_.size()) { return false; } @@ -111,7 +109,7 @@ class MutatorsStack { return !operator==(other); } -private: + private: std::vector> vector_; }; // MutatorsStack @@ -123,8 +121,8 @@ class EmbeddedViewParams { bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && - sizePoints == other.sizePoints && - *mutatorsStack == *(other.mutatorsStack); + sizePoints == other.sizePoints && + *mutatorsStack == *(other.mutatorsStack); } }; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 470e8cb1ed77f..db82193bc838f 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -77,7 +77,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, internal_nodes_canvas.addCanvas(overlay_canvases[i]); } } - + MutatorsStack* stack = new MutatorsStack(); Layer::PaintContext context = { From b8744202f811630f286373bba92328e5d7b1c004 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 14:48:47 -0700 Subject: [PATCH 28/56] revert the change that made the vector containing unique_ptr --- flow/embedded_views.cc | 32 +++++++++---------- flow/embedded_views.h | 22 ++++--------- flow/layers/platform_view_layer.cc | 2 +- flow/mutators_stack_unittests.cc | 24 +++++++------- .../framework/Source/FlutterPlatformViews.mm | 13 ++++---- .../Source/FlutterPlatformViews_Internal.h | 2 +- 6 files changed, 43 insertions(+), 52 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index e5b64e27d7dc1..1c8494439c2ba 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -11,38 +11,38 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { }; void MutatorsStack::pushClipRect(const SkRect& rect) { - std::unique_ptr element = std::make_unique(); - element->setType(clip_rect); - element->setRect(rect); + Mutator element; + element.setType(clip_rect); + element.setRect(rect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { - std::unique_ptr element = std::make_unique(); - element->setType(clip_rrect); - element->setRRect(rrect); + Mutator element; + element.setType(clip_rrect); + element.setRRect(rrect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { - std::unique_ptr element = std::make_unique(); - element->setType(transform); - element->setMatrix(matrix); + Mutator element; + element.setType(transform); + element.setMatrix(matrix); vector_.push_back(std::move(element)); }; void MutatorsStack::pop() { vector_.pop_back(); -} +}; -const std::vector>::const_reverse_iterator -MutatorsStack::top() { +const std::vector::const_reverse_iterator +MutatorsStack::top() const { return vector_.rend(); -} +}; -const std::vector>::const_reverse_iterator -MutatorsStack::bottom() { +const std::vector::const_reverse_iterator +MutatorsStack::bottom() const { return vector_.rbegin(); -} +}; } // namespace flutter diff --git a/flow/embedded_views.h b/flow/embedded_views.h index df08c29f9ba9e..5ee4c5f91a787 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -77,6 +77,7 @@ class Mutator { // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { public: + void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); @@ -88,21 +89,12 @@ class MutatorsStack { void pop(); // Returns the iterator points to the top of the stack.. - const std::vector>::const_reverse_iterator top(); + const std::vector::const_reverse_iterator top() const; // Returns an iterator pointing to the bottom of the stack. - const std::vector>::const_reverse_iterator bottom(); + const std::vector::const_reverse_iterator bottom() const; bool operator==(const MutatorsStack& other) const { - if (vector_.size() != other.vector_.size()) { - return false; - } - - for (size_t i = 0; i < vector_.size(); i++) { - if (*(vector_[i].get()) != *(other.vector_[i].get())) { - return false; - } - } - return true; + return vector_ == other.vector_; } bool operator!=(const MutatorsStack& other) const { @@ -110,19 +102,19 @@ class MutatorsStack { } private: - std::vector> vector_; + std::vector vector_; }; // MutatorsStack class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - MutatorsStack* mutatorsStack; + MutatorsStack mutatorsStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && - *mutatorsStack == *(other.mutatorsStack); + mutatorsStack == other.mutatorsStack; } }; diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 421f42cf5ee47..bcef3cf924d3f 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,7 +34,7 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - params.mutatorsStack = context.mutator_stack; + params.mutatorsStack = *context.mutator_stack; SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 362afad8b7327..9c3b35fc82c10 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -15,8 +15,8 @@ TEST(MutatorsStack, PushClipRect) { SkRect rect; stack.pushClipRect(rect); auto iter = stack.bottom(); - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); - ASSERT_TRUE(iter->get()->rect() == rect); + ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->rect() == rect); } TEST(MutatorsStack, PushClipRRect) { @@ -24,8 +24,8 @@ TEST(MutatorsStack, PushClipRRect) { SkRRect rrect; stack.pushClipRRect(rrect); auto iter = stack.bottom(); - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); - ASSERT_TRUE(iter->get()->rrect() == rrect); + ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->rrect() == rrect); } TEST(MutatorsStack, PushTransform) { @@ -33,8 +33,8 @@ TEST(MutatorsStack, PushTransform) { SkMatrix matrix; stack.pushTransform(matrix); auto iter = stack.bottom(); - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); - ASSERT_TRUE(iter->get()->matrix() == matrix); + ASSERT_TRUE(iter->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->matrix() == matrix); } TEST(MutatorsStack, Pop) { @@ -59,16 +59,16 @@ TEST(MutatorsStack, Traversal) { while (iter != stack.top()) { switch (index) { case 0: - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); - ASSERT_TRUE(iter->get()->rrect() == rrect); + ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->rrect() == rrect); break; case 1: - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); - ASSERT_TRUE(iter->get()->rect() == rect); + ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->rect() == rect); break; case 2: - ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); - ASSERT_TRUE(iter->get()->matrix() == matrix); + ASSERT_TRUE(iter->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->matrix() == matrix); break; default: break; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index ae2bbf87ece10..4eb3d51f105d8 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -201,7 +201,7 @@ // used to perform clips in the previous example and perform the new clips on the same views. // // Returns the UIView that's at the top of the generated chain(C_2 for the example above). -UIView* FlutterPlatformViewsController::ApplyMutators(MutatorsStack& mutators_stack, +UIView* FlutterPlatformViewsController::ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view, int view_id) { UIView* head = embedded_view; @@ -215,9 +215,9 @@ auto iter = mutators_stack.bottom(); int64_t clipCount = 0; while (iter != mutators_stack.top()) { - switch (iter->get()->type()) { + switch (iter->type()) { case transform: { - CATransform3D transform = GetCATransform3DFromSkMatrix(iter->get()->matrix()); + CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); head.layer.transform = CATransform3DConcat(head.layer.transform, transform); break; } @@ -232,8 +232,8 @@ view = [[UIView alloc] initWithFrame:flutter_view_.get().bounds]; [view addSubview:head]; } - PerformClip(view, iter->get()->type(), iter->get()->rect(), iter->get()->rrect(), - iter->get()->path()); + PerformClip(view, iter->type(), iter->rect(), iter->rrect(), + iter->path()); ResetAnchor(view.layer); head = view; break; @@ -276,8 +276,7 @@ CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); touch_interceptor.frame = frame; - FML_CHECK(params.mutatorsStack != nullptr); - UIView* head = ApplyMutators(*params.mutatorsStack, touch_interceptor, view_id); + UIView* head = ApplyMutators(params.mutatorsStack, touch_interceptor, view_id); // If we have clips, replace root view with the top parent view. if (head != touch_interceptor) { root_views_[view_id] = fml::scoped_nsobject([head retain]); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index c7d1ae33f4e52..85b88d64cc002 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -156,7 +156,7 @@ class FlutterPlatformViewsController { void EnsureGLOverlayInitialized(int64_t overlay_id, std::shared_ptr gl_context, GrContext* gr_context); - UIView* ApplyMutators(MutatorsStack& mutators_stack, UIView* embedded_view, int view_id); + UIView* ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view, int view_id); void CompositeWithParams(int view_id, const flutter::EmbeddedViewParams& params); FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); From a1794dea8fab7162282c167ed03d46189ab414e2 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 14:54:46 -0700 Subject: [PATCH 29/56] formatting --- flow/embedded_views.cc | 7 +++---- flow/embedded_views.h | 1 - .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 1c8494439c2ba..c7e9e0b535de2 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -35,13 +35,12 @@ void MutatorsStack::pop() { vector_.pop_back(); }; -const std::vector::const_reverse_iterator -MutatorsStack::top() const { +const std::vector::const_reverse_iterator MutatorsStack::top() const { return vector_.rend(); }; -const std::vector::const_reverse_iterator -MutatorsStack::bottom() const { +const std::vector::const_reverse_iterator MutatorsStack::bottom() + const { return vector_.rbegin(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 5ee4c5f91a787..4c804504189c4 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -77,7 +77,6 @@ class Mutator { // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { public: - void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 4eb3d51f105d8..0f8b152dd5380 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -232,8 +232,7 @@ view = [[UIView alloc] initWithFrame:flutter_view_.get().bounds]; [view addSubview:head]; } - PerformClip(view, iter->type(), iter->rect(), iter->rrect(), - iter->path()); + PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); ResetAnchor(view.layer); head = view; break; From 2f0125c0690b4327e26331a0e98a3a7359413e4c Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 6 Jun 2019 15:02:49 -0700 Subject: [PATCH 30/56] add TODO --- flow/embedded_views.h | 1 + 1 file changed, 1 insertion(+) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 4c804504189c4..9c68f956c57e2 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -101,6 +101,7 @@ class MutatorsStack { } private: + // TODO(cyanglaz): Make it a vector of unique_ptr to save some copies. std::vector vector_; }; // MutatorsStack From d22acbd4886779698fba3149935db5c59b60aa25 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 10 Jun 2019 09:31:53 -0700 Subject: [PATCH 31/56] fix a bug where the reused clip view doesn't reset transform --- .../platform/darwin/ios/framework/Source/FlutterPlatformViews.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 0f8b152dd5380..5e835b4300c8f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -235,6 +235,7 @@ PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); ResetAnchor(view.layer); head = view; + head.layer.transform = CATransform3DIdentity; break; } } From 2b08642e7ba9ae063d246fc467c04c2606902f1d Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 10 Jun 2019 09:34:24 -0700 Subject: [PATCH 32/56] addition to last fix --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 5e835b4300c8f..4d373c9a6d9b3 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -232,10 +232,10 @@ view = [[UIView alloc] initWithFrame:flutter_view_.get().bounds]; [view addSubview:head]; } + view.layer.transform = CATransform3DIdentity; PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); ResetAnchor(view.layer); head = view; - head.layer.transform = CATransform3DIdentity; break; } } From 1599067ba3b187e41c1b7a3982a19d4b054f537b Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 10 Jun 2019 09:51:29 -0700 Subject: [PATCH 33/56] adding touch transparent view --- .../ios/framework/Source/FlutterPlatformViews.mm | 15 ++++++++++++++- .../Source/FlutterPlatformViews_Internal.h | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 4d373c9a6d9b3..3a4276d949949 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -229,7 +229,8 @@ ++clipCount; if (clipCount > clip_count_[view_id]) { [head removeFromSuperview]; - view = [[UIView alloc] initWithFrame:flutter_view_.get().bounds]; + view = [[TouchTransparentView alloc] initWithFrame:flutter_view_.get().bounds]; + [view addSubview:head]; } view.layer.transform = CATransform3DIdentity; @@ -612,3 +613,15 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer return YES; } @end + +@implementation TouchTransparentView + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event { + for (UIView* view in self.subviews) { + if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) + return YES; + } + return NO; +} + +@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 85b88d64cc002..9d6282de2cc58 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -28,6 +28,12 @@ - (void)blockGesture; @end +// A view that only acknowlege touches are inside if the touches are acknowlege inside by any of its +// subviews. +@interface TouchTransparentView : UIView + +@end + namespace flutter { // Converts a SkRect to CGRect. From b8e4111d5e764a90b1e6eee7d4604db32ed535cd Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 10 Jun 2019 09:58:29 -0700 Subject: [PATCH 34/56] adding approximate for conic and remove debugging logs --- flow/embedded_views.cc | 13 ++++++------- .../Source/FlutterPlatformViews_Internal.h | 2 +- .../Source/FlutterPlatformViews_Internal.mm | 18 ++++++------------ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 74d29cd6585db..f77eaa6cda37f 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -24,13 +24,12 @@ void MutatorsStack::pushClipRRect(const SkRRect& rrect) { vector_.push_back(element); }; - void MutatorsStack::pushClipPath(const SkPath& path) { - Mutator element; - element.setType(clip_path); - element.setPath(path); - vector_.push_back(element); - }; - +void MutatorsStack::pushClipPath(const SkPath& path) { + Mutator element; + element.setType(clip_path); + element.setPath(path); + vector_.push_back(element); +}; void MutatorsStack::pushTransform(const SkMatrix& matrix) { Mutator element; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 28f825cd34f07..47a862b069114 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -46,7 +46,7 @@ void ClipRect(UIView* view, const SkRect& clipSkRect); void ClipRRect(UIView* view, const SkRRect& clipSkRRect); // Perform clip path on the `view` using `path`. -void ClipPath(UIView *view, const SkPath &path); +void ClipPath(UIView* view, const SkPath& path); // Perform a clip operation on the `view`. // Uses either `rect`, `rrect` or `path` to perform the clip based on the `type`. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 6ed893e8538c2..c4b09dff17c90 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -104,7 +104,7 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { CGPathRelease(pathRef); } -void ClipPath(UIView *view, const SkPath &path) { +void ClipPath(UIView* view, const SkPath& path) { CGMutablePathRef pathRef = CGPathCreateMutable(); if (!path.isValid()) { return; @@ -118,50 +118,44 @@ void ClipPath(UIView *view, const SkPath &path) { } // Loop through all verbs and translate them into CGPath - SkPath::Iter iter(path, true); SkPoint pts[4]; SkPath::Verb verb = iter.next(pts); - while(verb != SkPath::kDone_Verb) { + while (verb != SkPath::kDone_Verb) { switch (verb) { case SkPath::kMove_Verb: { - NSLog(@"verb move"); CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y()); break; } case SkPath::kLine_Verb: { - NSLog(@"verb line"); CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y()); break; } case SkPath::kQuad_Verb: { - NSLog(@"verb quad"); CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); break; } case SkPath::kConic_Verb: { - NSLog(@"verb conic"); + // Conic is not available in quartz, we use quad to approximate. + CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); break; } case SkPath::kCubic_Verb: { - NSLog(@"verb cubic"); - CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y()); + CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), + pts[3].x(), pts[3].y()); break; } case SkPath::kClose_Verb: { - NSLog(@"verb close"); CGPathCloseSubpath(pathRef); break; } case SkPath::kDone_Verb: { - NSLog(@"verb done"); break; } } verb = iter.next(pts); } - NSLog(@"final path %@", pathRef); CAShapeLayer* clip = [[CAShapeLayer alloc] init]; clip.path = pathRef; view.layer.mask = clip; From a027fa0d9ff45a0907ab2d945dacf2e254f5d885 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 15:36:55 -0700 Subject: [PATCH 35/56] some review fixes --- flow/embedded_views.cc | 12 +-- flow/embedded_views.h | 21 +++-- flow/mutators_stack_unittests.cc | 38 +++------ .../framework/Source/FlutterPlatformViews.mm | 18 +---- .../Source/FlutterPlatformViews_Internal.h | 10 ++- .../Source/FlutterPlatformViews_Internal.mm | 80 +++++++++++-------- 6 files changed, 82 insertions(+), 97 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index c7e9e0b535de2..5360d72771ae7 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -11,23 +11,17 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { }; void MutatorsStack::pushClipRect(const SkRect& rect) { - Mutator element; - element.setType(clip_rect); - element.setRect(rect); + Mutator element = Mutator(rect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { - Mutator element; - element.setType(clip_rrect); - element.setRRect(rrect); + Mutator element = Mutator(rrect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { - Mutator element; - element.setType(transform); - element.setMatrix(matrix); + Mutator element = Mutator(matrix); vector_.push_back(std::move(element)); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 9c68f956c57e2..333c40222f99d 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -21,10 +21,11 @@ enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { public: - void setType(const MutatorType type) { type_ = type; } - void setRect(const SkRect& rect) { rect_ = rect; } - void setRRect(const SkRRect& rrect) { rrect_ = rrect; } - void setMatrix(const SkMatrix& matrix) { matrix_ = matrix; } + + explicit Mutator(const SkRect& rect):type_(clip_rect), rect_(rect){} + explicit Mutator(const SkRRect& rrect):type_(clip_rrect), rrect_(rrect){} + explicit Mutator(const SkPath& path):type_(clip_path), path_(path){} + explicit Mutator(const SkMatrix& matrix):type_(transform), matrix_(matrix){} MutatorType type() const { return type_; } SkRect rect() const { return rect_; } @@ -60,10 +61,14 @@ class Mutator { private: MutatorType type_; - SkRect rect_; - SkRRect rrect_; - SkPath path_; - SkMatrix matrix_; + + union{ + SkRect rect_; + SkRRect rrect_; + SkPath path_; + SkMatrix matrix_; + }; + }; // Mutator // A stack of mutators that can be applied to an embedded platform view. diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 9c3b35fc82c10..634f9cef641ee 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -99,44 +99,28 @@ TEST(MutatorsStack, Equality) { } TEST(Mutator, Equality) { - flutter::Mutator mutator; - flutter::Mutator otherMutator; - mutator.setType(flutter::MutatorType::transform); - otherMutator.setType(flutter::MutatorType::transform); SkMatrix matrix; - mutator.setMatrix(matrix); - otherMutator.setMatrix(matrix); + flutter::Mutator mutator = flutter::Mutator(matrix); + flutter::Mutator otherMutator = flutter::Mutator(matrix); ASSERT_TRUE(mutator == otherMutator); - mutator.setType(flutter::MutatorType::clip_rect); - otherMutator.setType(flutter::MutatorType::clip_rect); SkRect rect; - mutator.setRect(rect); - otherMutator.setRect(rect); - ASSERT_TRUE(mutator == otherMutator); + flutter::Mutator mutator2 = flutter::Mutator(rect); + flutter::Mutator otherMutator2 = flutter::Mutator(rect); + ASSERT_TRUE(mutator2 == otherMutator2); - mutator.setType(flutter::MutatorType::clip_rrect); - otherMutator.setType(flutter::MutatorType::clip_rrect); SkRRect rrect; - mutator.setRRect(rrect); - otherMutator.setRRect(rrect); - ASSERT_TRUE(mutator == otherMutator); + flutter::Mutator mutator3 = flutter::Mutator(rrect); + flutter::Mutator otherMutator3 =flutter::Mutator(rrect); + ASSERT_TRUE(mutator3 == otherMutator3); - flutter::Mutator notEqualMutator; - notEqualMutator.setType(flutter::MutatorType::transform); - notEqualMutator.setMatrix(matrix); - ASSERT_FALSE(notEqualMutator == mutator); + ASSERT_FALSE(mutator2 == mutator); } TEST(Mutator, UnEquality) { - flutter::Mutator mutator; - mutator.setType(flutter::MutatorType::clip_rect); SkRect rect; - mutator.setRect(rect); - + flutter::Mutator mutator = flutter::Mutator(rect); SkMatrix matrix; - flutter::Mutator notEqualMutator; - notEqualMutator.setType(flutter::MutatorType::transform); - notEqualMutator.setMatrix(matrix); + flutter::Mutator notEqualMutator = flutter::Mutator(matrix); ASSERT_TRUE(notEqualMutator != mutator); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3a4276d949949..906d32b71b205 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -229,12 +229,12 @@ ++clipCount; if (clipCount > clip_count_[view_id]) { [head removeFromSuperview]; - view = [[TouchTransparentView alloc] initWithFrame:flutter_view_.get().bounds]; - + view = [[ChildClippingView alloc] initWithFrame:flutter_view_.get().bounds]; [view addSubview:head]; } view.layer.transform = CATransform3DIdentity; - PerformClip(view, iter->type(), iter->rect(), iter->rrect(), iter->path()); + ChildClippingView *clippingView = (ChildClippingView *)view; + [clippingView performClip:iter->type() rect:iter->rect() rrect:iter->rrect() path:iter->path()]; ResetAnchor(view.layer); head = view; break; @@ -613,15 +613,3 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer return YES; } @end - -@implementation TouchTransparentView - -- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event { - for (UIView* view in self.subviews) { - if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) - return YES; - } - return NO; -} - -@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 9d6282de2cc58..2eeae84bab59e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -28,9 +28,13 @@ - (void)blockGesture; @end -// A view that only acknowlege touches are inside if the touches are acknowlege inside by any of its -// subviews. -@interface TouchTransparentView : UIView +// The parent view handles clipping to its subviews. +@interface ChildClippingView : UIView + +// Performs the clipping based on the type. +// +// The `type` must be one of the 3: clip_rect, clip_rrect, clip_path. +-(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(const SkRRect&)rrect path:(const SkPath&)path; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 0ac6e9562680f..3e9e090da1ad4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -21,33 +21,58 @@ FlutterPlatformViewsController::~FlutterPlatformViewsController() = default; -CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) { +CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { + // Skia only supports 2D transform so we don't map z. + CATransform3D transform = CATransform3DIdentity; + transform.m11 = matrix.getScaleX(); + transform.m21 = matrix.getSkewX(); + transform.m41 = matrix.getTranslateX(); + transform.m14 = matrix.getPerspX(); + + transform.m12 = matrix.getSkewY(); + transform.m22 = matrix.getScaleY(); + transform.m42 = matrix.getTranslateY(); + transform.m24 = matrix.getPerspY(); + return transform; +} + +void ResetAnchor(CALayer* layer) { + // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. + layer.anchorPoint = CGPointZero; + layer.position = CGPointZero; +} + +} // namespace flutter + +@implementation ChildClippingView + ++ (CGRect)getCGRectFromSkRect:(const SkRect&) clipSkRect { return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, clipSkRect.fBottom - clipSkRect.fTop); } -void ClipRect(UIView* view, const SkRect& clipSkRect) { - CGRect clipRect = GetCGRectFromSkRect(clipSkRect); +- (void)clipRect:(const SkRect&)clipSkRect { + CGRect clipRect = [ChildClippingView getCGRectFromSkRect:clipSkRect]; CGPathRef pathRef = CGPathCreateWithRect(clipRect, nil); CAShapeLayer* clip = [[CAShapeLayer alloc] init]; clip.path = pathRef; - view.layer.mask = clip; + self.layer.mask = clip; CGPathRelease(pathRef); } -void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { +-(void)clipRRect:(const SkRRect&)clipSkRRect { CGPathRef pathRef = nullptr; switch (clipSkRRect.getType()) { case SkRRect::kEmpty_Type: { break; } case SkRRect::kRect_Type: { - ClipRect(view, clipSkRRect.rect()); + [self clipRect:clipSkRRect.rect()]; return; } case SkRRect::kOval_Type: case SkRRect::kSimple_Type: { - CGRect clipRect = GetCGRectFromSkRect(clipSkRRect.rect()); + CGRect clipRect = [ChildClippingView getCGRectFromSkRect:clipSkRRect.rect()]; pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(), clipSkRRect.getSimpleRadii().y(), nil); break; @@ -100,23 +125,19 @@ void ClipRRect(UIView* view, const SkRRect& clipSkRRect) { // clipping on iOS. CAShapeLayer* clip = [[CAShapeLayer alloc] init]; clip.path = pathRef; - view.layer.mask = clip; + self.layer.mask = clip; CGPathRelease(pathRef); } -void PerformClip(UIView* view, - flutter::MutatorType type, - const SkRect& rect, - const SkRRect& rrect, - const SkPath& path) { +-(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(const SkRRect&) rrect path:(const SkPath&)path { FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || type == flutter::clip_path); switch (type) { case flutter::clip_rect: - ClipRect(view, rect); + [self clipRect:rect]; break; case flutter::clip_rrect: - ClipRRect(view, rrect); + [self clipRRect:rrect]; break; case flutter::clip_path: // TODO(cyanglaz): Add clip path @@ -126,25 +147,14 @@ void PerformClip(UIView* view, } } -CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) { - // Skia only supports 2D transform so we don't map z. - CATransform3D transform = CATransform3DIdentity; - transform.m11 = matrix.getScaleX(); - transform.m21 = matrix.getSkewX(); - transform.m41 = matrix.getTranslateX(); - transform.m14 = matrix.getPerspX(); - - transform.m12 = matrix.getSkewY(); - transform.m22 = matrix.getScaleY(); - transform.m42 = matrix.getTranslateY(); - transform.m24 = matrix.getPerspY(); - return transform; -} - -void ResetAnchor(CALayer* layer) { - // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz. - layer.anchorPoint = CGPointZero; - layer.position = CGPointZero; +// Only acknowlege touches are inside if the touches are acknowlege inside by any of its +// subviews. +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent* )event { + for (UIView* view in self.subviews) { + if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) + return YES; + } + return NO; } -} // namespace flutter +@end From 12ff43a6a1cde1beb6cb9e36216aec7fa9a4459f Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 16:20:10 -0700 Subject: [PATCH 36/56] union done --- flow/embedded_views.h | 22 ++++++++++++------- .../Source/FlutterPlatformViews_Internal.mm | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 333c40222f99d..4c0e1c628c7fc 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -24,14 +24,14 @@ class Mutator { explicit Mutator(const SkRect& rect):type_(clip_rect), rect_(rect){} explicit Mutator(const SkRRect& rrect):type_(clip_rrect), rrect_(rrect){} - explicit Mutator(const SkPath& path):type_(clip_path), path_(path){} + explicit Mutator(const SkPath& path):type_(clip_path), path_(new SkPath(path)){} explicit Mutator(const SkMatrix& matrix):type_(transform), matrix_(matrix){} - MutatorType type() const { return type_; } - SkRect rect() const { return rect_; } - SkRRect rrect() const { return rrect_; } - SkPath path() const { return path_; } - SkMatrix matrix() const { return matrix_; } + const MutatorType& type() const { return type_; } + const SkRect& rect() const { return rect_; } + const SkRRect& rrect() const { return rrect_; } + const SkPath& path() const { return *path_; } + const SkMatrix& matrix() const { return matrix_; } bool operator==(const Mutator& other) const { if (type_ != other.type_) { @@ -43,7 +43,7 @@ class Mutator { if (type_ == clip_rrect && rrect_ == other.rrect_) { return true; } - if (type_ == clip_path && path_ == other.path_) { + if (type_ == clip_path && *path_ == *other.path_) { return true; } if (type_ == transform && matrix_ == other.matrix_) { @@ -59,14 +59,20 @@ class Mutator { return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; } + ~Mutator(){ + if (type_ == clip_path) { + delete path_; + } + }; + private: MutatorType type_; union{ SkRect rect_; SkRRect rrect_; - SkPath path_; SkMatrix matrix_; + SkPath* path_; }; }; // Mutator diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 3e9e090da1ad4..77cc2dd2bdb81 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -151,8 +151,9 @@ -(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(co // subviews. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent* )event { for (UIView* view in self.subviews) { - if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) + if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) { return YES; + } } return NO; } From a9a660f4abe3054a9d8578998dfd55681562fab4 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 16:47:17 -0700 Subject: [PATCH 37/56] draft --- flow/embedded_views.h | 2 +- flow/layers/clip_rect_layer.cc | 10 ++++------ flow/layers/clip_rrect_layer.cc | 9 +++------ flow/layers/layer.h | 2 +- flow/layers/layer_tree.cc | 7 +++---- flow/layers/performance_overlay_layer_unittests.cc | 4 ++-- flow/layers/platform_view_layer.cc | 6 +++++- flow/layers/transform_layer.cc | 9 +++------ flow/raster_cache.cc | 3 ++- 9 files changed, 24 insertions(+), 28 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 4c0e1c628c7fc..c1f305f084c0f 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -120,7 +120,7 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; - MutatorsStack mutatorsStack; + MutatorsStack& mutatorsStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index c42df8aeb447d..734674ef0e5ea 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,9 +50,8 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); - if (context.mutator_stack != nullptr) { - context.mutator_stack->pushClipRect(clip_rect_); - } + context.mutator_stack.pushClipRect(clip_rect_); + if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); } @@ -60,9 +59,8 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - if (context.mutator_stack != nullptr) { - context.mutator_stack->pop(); - } + context.mutator_stack.pop(); + } } // namespace flutter diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index e15e12d198ea2..9548fa1d126dd 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -58,9 +58,8 @@ void ClipRRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); - if (context.mutator_stack != nullptr) { - context.mutator_stack->pushClipRRect(clip_rrect_); - } + context.mutator_stack.pushClipRRect(clip_rrect_); + if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); } @@ -68,9 +67,7 @@ void ClipRRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - if (context.mutator_stack != nullptr) { - context.mutator_stack->pop(); - } + context.mutator_stack.pop(); } } // namespace flutter diff --git a/flow/layers/layer.h b/flow/layers/layer.h index efe238f6c3cf7..d64d6bef33a06 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -83,7 +83,7 @@ class Layer { SkCanvas* leaf_nodes_canvas; GrContext* gr_context; ExternalViewEmbedder* view_embedder; - MutatorsStack* mutator_stack; + MutatorsStack& mutator_stack; const Stopwatch& raster_time; const Stopwatch& ui_time; TextureRegistry& texture_registry; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index db82193bc838f..86cab4041eefd 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -78,8 +78,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, } } - MutatorsStack* stack = new MutatorsStack(); - + MutatorsStack stack; Layer::PaintContext context = { (SkCanvas*)&internal_nodes_canvas, frame.canvas(), @@ -95,7 +94,6 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, if (root_layer_->needs_painting()) root_layer_->Paint(context); - delete stack; } sk_sp LayerTree::Flatten(const SkRect& bounds) { @@ -108,6 +106,7 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { return nullptr; } + MutatorsStack unused_stack; const Stopwatch unused_stopwatch; TextureRegistry unused_texture_registry; SkMatrix root_surface_transformation; @@ -135,7 +134,7 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { canvas, // canvas nullptr, nullptr, - nullptr, + unused_stack, unused_stopwatch, // frame time (dont care) unused_stopwatch, // engine time (dont care) unused_texture_registry, // texture registry (not supported) diff --git a/flow/layers/performance_overlay_layer_unittests.cc b/flow/layers/performance_overlay_layer_unittests.cc index d2470148cd368..a6ea29f7a3d41 100644 --- a/flow/layers/performance_overlay_layer_unittests.cc +++ b/flow/layers/performance_overlay_layer_unittests.cc @@ -47,11 +47,11 @@ TEST(PerformanceOverlayLayer, Gold) { ASSERT_TRUE(surface != nullptr); flutter::TextureRegistry unused_texture_registry; - + flutter::MutatorsStack unused_stack; flutter::Layer::PaintContext paintContext = { nullptr, surface->getCanvas(), nullptr, nullptr, - nullptr, mock_stopwatch, + unused_stack, mock_stopwatch, mock_stopwatch, unused_texture_registry, nullptr, false}; diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index bcef3cf924d3f..95941822fd85e 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,7 +34,11 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - params.mutatorsStack = *context.mutator_stack; + params.mutatorsStack = context.mutator_stack; + + FML_DLOG(ERROR) << "address:"; + FML_DLOG(ERROR) << ¶ms.mutatorsStack; + FML_DLOG(ERROR) << &context.mutator_stack; SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index f29d9f5f0dc70..ea6bded59f9be 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -66,13 +66,10 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); - if (context.mutator_stack != nullptr) { - context.mutator_stack->pushTransform(transform_); - } + context.mutator_stack.pushTransform(transform_); + PaintChildren(context); - if (context.mutator_stack != nullptr) { - context.mutator_stack->pop(); - } + context.mutator_stack.pop(); } } // namespace flutter diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 7247241df7665..be0c88d5cc7e8 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -159,6 +159,7 @@ void RasterCache::Prepare(PrerollContext* context, entry.image = Rasterize(context->gr_context, ctm, context->dst_color_space, checkerboard_images_, layer->paint_bounds(), [layer, context](SkCanvas* canvas) { + MutatorsStack stack; SkISize canvas_size = canvas->getBaseLayerSize(); SkNWayCanvas internal_nodes_canvas( canvas_size.width(), canvas_size.height()); @@ -168,7 +169,7 @@ void RasterCache::Prepare(PrerollContext* context, canvas, context->gr_context, nullptr, - nullptr, + stack, context->raster_time, context->ui_time, context->texture_registry, From f4b9503d399d4357d4c442ebf56cce812cfaa881 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 19:02:20 -0700 Subject: [PATCH 38/56] review fixes --- flow/embedded_views.h | 29 +++++-- flow/layers/clip_rect_layer.cc | 5 +- flow/layers/clip_rrect_layer.cc | 4 +- flow/layers/layer.h | 2 +- flow/layers/layer_tree.cc | 1 - .../performance_overlay_layer_unittests.cc | 2 +- flow/layers/platform_view_layer.cc | 4 +- flow/layers/transform_layer.cc | 4 +- flow/mutators_stack_unittests.cc | 2 +- .../framework/Source/FlutterPlatformViews.mm | 84 ++++++++++--------- .../Source/FlutterPlatformViews_Internal.h | 5 +- .../Source/FlutterPlatformViews_Internal.mm | 11 ++- 12 files changed, 88 insertions(+), 65 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index c1f305f084c0f..1b771c714950a 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -21,11 +21,12 @@ enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { public: - - explicit Mutator(const SkRect& rect):type_(clip_rect), rect_(rect){} - explicit Mutator(const SkRRect& rrect):type_(clip_rrect), rrect_(rrect){} - explicit Mutator(const SkPath& path):type_(clip_path), path_(new SkPath(path)){} - explicit Mutator(const SkMatrix& matrix):type_(transform), matrix_(matrix){} + explicit Mutator(const SkRect& rect) : type_(clip_rect), rect_(rect) {} + explicit Mutator(const SkRRect& rrect) : type_(clip_rrect), rrect_(rrect) {} + explicit Mutator(const SkPath& path) + : type_(clip_path), path_(new SkPath(path)) {} + explicit Mutator(const SkMatrix& matrix) + : type_(transform), matrix_(matrix) {} const MutatorType& type() const { return type_; } const SkRect& rect() const { return rect_; } @@ -59,7 +60,7 @@ class Mutator { return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; } - ~Mutator(){ + ~Mutator() { if (type_ == clip_path) { delete path_; } @@ -68,7 +69,7 @@ class Mutator { private: MutatorType type_; - union{ + union { SkRect rect_; SkRRect rrect_; SkMatrix matrix_; @@ -118,15 +119,25 @@ class MutatorsStack { class EmbeddedViewParams { public: + EmbeddedViewParams() = default; + + EmbeddedViewParams(const EmbeddedViewParams& other) { + offsetPixels = other.offsetPixels; + sizePoints = other.sizePoints; + mutatorsStack = new MutatorsStack(*other.mutatorsStack); + }; + SkPoint offsetPixels; SkSize sizePoints; - MutatorsStack& mutatorsStack; + MutatorsStack* mutatorsStack; bool operator==(const EmbeddedViewParams& other) const { return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints && - mutatorsStack == other.mutatorsStack; + *mutatorsStack == *other.mutatorsStack; } + + ~EmbeddedViewParams() { delete mutatorsStack; } }; // This is only used on iOS when running in a non headless mode, diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 734674ef0e5ea..0460711f3aeb6 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -50,7 +50,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, clip_behavior_ != Clip::hardEdge); - context.mutator_stack.pushClipRect(clip_rect_); + context.mutators_stack.pushClipRect(clip_rect_); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); @@ -59,8 +59,7 @@ void ClipRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - context.mutator_stack.pop(); - + context.mutators_stack.pop(); } } // namespace flutter diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 9548fa1d126dd..ca17c11429545 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -58,7 +58,7 @@ void ClipRRectLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); - context.mutator_stack.pushClipRRect(clip_rrect_); + context.mutators_stack.pushClipRRect(clip_rrect_); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr); @@ -67,7 +67,7 @@ void ClipRRectLayer::Paint(PaintContext& context) const { if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { context.internal_nodes_canvas->restore(); } - context.mutator_stack.pop(); + context.mutators_stack.pop(); } } // namespace flutter diff --git a/flow/layers/layer.h b/flow/layers/layer.h index d64d6bef33a06..5e30a50c907f9 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -83,7 +83,7 @@ class Layer { SkCanvas* leaf_nodes_canvas; GrContext* gr_context; ExternalViewEmbedder* view_embedder; - MutatorsStack& mutator_stack; + MutatorsStack& mutators_stack; const Stopwatch& raster_time; const Stopwatch& ui_time; TextureRegistry& texture_registry; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 86cab4041eefd..a99aa16f1b7ea 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -93,7 +93,6 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, if (root_layer_->needs_painting()) root_layer_->Paint(context); - } sk_sp LayerTree::Flatten(const SkRect& bounds) { diff --git a/flow/layers/performance_overlay_layer_unittests.cc b/flow/layers/performance_overlay_layer_unittests.cc index a6ea29f7a3d41..f82b0e2963869 100644 --- a/flow/layers/performance_overlay_layer_unittests.cc +++ b/flow/layers/performance_overlay_layer_unittests.cc @@ -51,7 +51,7 @@ TEST(PerformanceOverlayLayer, Gold) { flutter::Layer::PaintContext paintContext = { nullptr, surface->getCanvas(), nullptr, nullptr, - unused_stack, mock_stopwatch, + unused_stack, mock_stopwatch, mock_stopwatch, unused_texture_registry, nullptr, false}; diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 95941822fd85e..784574837e638 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -34,11 +34,11 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; - params.mutatorsStack = context.mutator_stack; + params.mutatorsStack = &context.mutators_stack; FML_DLOG(ERROR) << "address:"; FML_DLOG(ERROR) << ¶ms.mutatorsStack; - FML_DLOG(ERROR) << &context.mutator_stack; + FML_DLOG(ERROR) << &context.mutators_stack; SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index ea6bded59f9be..e88b743bd4f0a 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -66,10 +66,10 @@ void TransformLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); - context.mutator_stack.pushTransform(transform_); + context.mutators_stack.pushTransform(transform_); PaintChildren(context); - context.mutator_stack.pop(); + context.mutators_stack.pop(); } } // namespace flutter diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 634f9cef641ee..bf65bbe96874b 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -111,7 +111,7 @@ TEST(Mutator, Equality) { SkRRect rrect; flutter::Mutator mutator3 = flutter::Mutator(rrect); - flutter::Mutator otherMutator3 =flutter::Mutator(rrect); + flutter::Mutator otherMutator3 = flutter::Mutator(rrect); ASSERT_TRUE(mutator3 == otherMutator3); ASSERT_FALSE(mutator2 == mutator); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 906d32b71b205..e0395eb8cc1f7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -183,9 +183,9 @@ return canvases; } -// Build a chain of UIViews that applies the mutations described by mutatorsStack. +// Builds a chain of UIViews that applies the mutations described by mutatorsStack. // -// Clips are applied by adding a super view with the CALayer mask. Transforms are applied to the +// Clips are applied by adding a super view with a CALayer mask. Transforms are applied to the // view that's at the head of the chain. For example the following mutators stack [T_1, C_2, T_3, // T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the following // UIView tree: @@ -196,9 +196,9 @@ // T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW. // // UIView instances used for clip mutations are re-used when possible. -// For example if we the mutators stack is updated to [T_1, C_7, T_3, T_4, C_8, T_9], we do not -// remove the previous superviews and re-create new views. Instead, we reuse the superviews that was -// used to perform clips in the previous example and perform the new clips on the same views. +// For example if the mutators stack above is updated to [T_1, C_7, T_3, T_4, C_8, T_9], we do not +// remove the previous superviews and re-create new views. Instead, we reuse the superviews that +// were used to perform clips in the previous example and perform the new clips on the same views. // // Returns the UIView that's at the top of the generated chain(C_2 for the example above). UIView* FlutterPlatformViewsController::ApplyMutators(const MutatorsStack& mutators_stack, @@ -211,7 +211,7 @@ head.layer.transform = CATransform3DIdentity; ResetAnchor(head.layer); - // Start loop to apply transforms/clips. + // Apply transforms/clips. auto iter = mutators_stack.bottom(); int64_t clipCount = 0; while (iter != mutators_stack.top()) { @@ -224,36 +224,31 @@ case clip_rect: case clip_rrect: case clip_path: { - UIView* view = head.superview; + UIView* clipView = head.superview; // if we need more clips operations than last time, create a new view. ++clipCount; if (clipCount > clip_count_[view_id]) { [head removeFromSuperview]; - view = [[ChildClippingView alloc] initWithFrame:flutter_view_.get().bounds]; - [view addSubview:head]; + clipView = [[ChildClippingView alloc] initWithFrame:flutter_view_.get().bounds]; + [clipView addSubview:head]; } - view.layer.transform = CATransform3DIdentity; - ChildClippingView *clippingView = (ChildClippingView *)view; - [clippingView performClip:iter->type() rect:iter->rect() rrect:iter->rrect() path:iter->path()]; - ResetAnchor(view.layer); - head = view; + clipView.layer.transform = CATransform3DIdentity; + [(ChildClippingView*)clipView performClip:iter->type() + rect:iter->rect() + rrect:iter->rrect() + path:iter->path()]; + ResetAnchor(clipView.layer); + head = clipView; break; } } ++iter; } - // Reverse scale based on screen scale. - // - // The UIKit frame is set based on the logical resolution instead of physical. - // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). - // However, flow is based on the physical resolution. For eaxmple, 1000 pixels in flow equals - // 500 points in UIKit. And until this point, we did all the calculation based on the flow - // resolution. So we need to scale down to match UIKit's logical resolution. - CGFloat screenScale = [UIScreen mainScreen].scale; - head.layer.transform = CATransform3DConcat( - head.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); - + // If we have clips, replace root view with the top parent view. + if (head != embedded_view) { + root_views_[view_id] = fml::scoped_nsobject([head retain]); + } // If we have less cilp operations this time, remove unnecessary views. // We skip this process if we have more clip operations this time. clip_count_[view_id] = clipCount; @@ -277,11 +272,18 @@ CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height()); touch_interceptor.frame = frame; - UIView* head = ApplyMutators(params.mutatorsStack, touch_interceptor, view_id); - // If we have clips, replace root view with the top parent view. - if (head != touch_interceptor) { - root_views_[view_id] = fml::scoped_nsobject([head retain]); - } + UIView* head = ApplyMutators(*params.mutatorsStack, touch_interceptor, view_id); + + // Reverse scale based on screen scale. + // + // The UIKit frame is set based on the logical resolution instead of physical. + // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). + // However, flow is based on the physical resolution. For eaxmple, 1000 pixels in flow equals + // 500 points in UIKit. And until this point, we did all the calculation based on the flow + // resolution. So we need to scale down to match UIKit's logical resolution. + CGFloat screenScale = [UIScreen mainScreen].scale; + head.layer.transform = CATransform3DConcat( + head.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); } SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView( @@ -295,7 +297,7 @@ current_composition_params_[view_id] == params) { return picture_recorders_[view_id]->getRecordingCanvas(); } - current_composition_params_[view_id] = params; + current_composition_params_[view_id] = EmbeddedViewParams(params); CompositeWithParams(view_id, params); return picture_recorders_[view_id]->getRecordingCanvas(); @@ -345,14 +347,17 @@ for (size_t i = 0; i < composition_order_.size(); i++) { int view_id = composition_order_[i]; - UIView* root = root_views_[view_id].get(); + // We added a chain of super views to the platform view to handle clipping. + // The `platform_view_root` is the view at the top of the chain which is a direct subview of the + // `FlutterView`. + UIView* platform_view_root = root_views_[view_id].get(); UIView* overlay = overlays_[view_id]->overlay_view; - FML_CHECK(root.superview == overlay.superview); - if (root.superview == flutter_view) { - [flutter_view bringSubviewToFront:root]; + FML_CHECK(platform_view_root.superview == overlay.superview); + if (platform_view_root.superview == flutter_view) { + [flutter_view bringSubviewToFront:platform_view_root]; [flutter_view bringSubviewToFront:overlay]; } else { - [flutter_view addSubview:root]; + [flutter_view addSubview:platform_view_root]; [flutter_view addSubview:overlay]; } @@ -374,8 +379,11 @@ if (root_views_.find(view_id) == root_views_.end()) { continue; } - UIView* root = root_views_[view_id].get(); - [root removeFromSuperview]; + // We added a chain of super views to the platform view to handle clipping. + // The `platform_view_root` is the view at the top of the chain which is a direct subview of + // the `FlutterView`. + UIView* platform_view_root = root_views_[view_id].get(); + [platform_view_root removeFromSuperview]; [overlays_[view_id]->overlay_view.get() removeFromSuperview]; } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 2eeae84bab59e..f702ded5b7f07 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -34,7 +34,10 @@ // Performs the clipping based on the type. // // The `type` must be one of the 3: clip_rect, clip_rrect, clip_path. --(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(const SkRRect&)rrect path:(const SkPath&)path; +- (void)performClip:(flutter::MutatorType)type + rect:(const SkRect&)rect + rrect:(const SkRRect&)rrect + path:(const SkPath&)path; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 77cc2dd2bdb81..7bedd2b34b7ef 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -46,7 +46,7 @@ void ResetAnchor(CALayer* layer) { @implementation ChildClippingView -+ (CGRect)getCGRectFromSkRect:(const SkRect&) clipSkRect { ++ (CGRect)getCGRectFromSkRect:(const SkRect&)clipSkRect { return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft, clipSkRect.fBottom - clipSkRect.fTop); } @@ -60,7 +60,7 @@ - (void)clipRect:(const SkRect&)clipSkRect { CGPathRelease(pathRef); } --(void)clipRRect:(const SkRRect&)clipSkRRect { +- (void)clipRRect:(const SkRRect&)clipSkRRect { CGPathRef pathRef = nullptr; switch (clipSkRRect.getType()) { case SkRRect::kEmpty_Type: { @@ -129,7 +129,10 @@ -(void)clipRRect:(const SkRRect&)clipSkRRect { CGPathRelease(pathRef); } --(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(const SkRRect&) rrect path:(const SkPath&)path { +- (void)performClip:(flutter::MutatorType)type + rect:(const SkRect&)rect + rrect:(const SkRRect&)rrect + path:(const SkPath&)path { FML_CHECK(type == flutter::clip_rect || type == flutter::clip_rrect || type == flutter::clip_path); switch (type) { @@ -149,7 +152,7 @@ -(void)performClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(co // Only acknowlege touches are inside if the touches are acknowlege inside by any of its // subviews. -- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent* )event { +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event { for (UIView* view in self.subviews) { if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) { return YES; From 7c0fa63fb831120b2bc75881b401917867e7e3db Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 22:58:28 -0700 Subject: [PATCH 39/56] draft --- flow/embedded_views.cc | 10 +-- flow/embedded_views.h | 46 ++++++++++++-- flow/layers/platform_view_layer.cc | 4 -- flow/mutators_stack_unittests.cc | 63 +++++++++++++++---- .../framework/Source/FlutterPlatformViews.mm | 4 +- 5 files changed, 99 insertions(+), 28 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 5360d72771ae7..a37cb7a797094 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -11,17 +11,17 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { }; void MutatorsStack::pushClipRect(const SkRect& rect) { - Mutator element = Mutator(rect); + std::unique_ptr element = std::make_unique(rect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { - Mutator element = Mutator(rrect); + std::unique_ptr element = std::make_unique(rrect); vector_.push_back(std::move(element)); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { - Mutator element = Mutator(matrix); + std::unique_ptr element = std::make_unique(matrix); vector_.push_back(std::move(element)); }; @@ -29,11 +29,11 @@ void MutatorsStack::pop() { vector_.pop_back(); }; -const std::vector::const_reverse_iterator MutatorsStack::top() const { +const std::vector>::const_reverse_iterator MutatorsStack::top() const { return vector_.rend(); }; -const std::vector::const_reverse_iterator MutatorsStack::bottom() +const std::vector>::const_reverse_iterator MutatorsStack::bottom() const { return vector_.rbegin(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 1b771c714950a..3373657e685b4 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -21,6 +21,26 @@ enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { public: + + Mutator(const Mutator& other) { + switch (other.type_) { + case clip_rect: + rect_ = other.rect_; + break; + case clip_rrect: + rrect_ = other.rrect_; + break; + case clip_path: + path_ = new SkPath(*other.path_); + break; + case transform: + matrix_ = other.matrix_; + break; + default: + break; + } + } + explicit Mutator(const SkRect& rect) : type_(clip_rect), rect_(rect) {} explicit Mutator(const SkRRect& rrect) : type_(clip_rrect), rrect_(rrect) {} explicit Mutator(const SkPath& path) @@ -89,6 +109,15 @@ class Mutator { // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { public: + + MutatorsStack() = default; + + MutatorsStack(const MutatorsStack& other) { + for (size_t i = 0; i < other.vector_.size(); i++) { + vector_[i] = std::make_unique(*other.vector_[i].get()); + } + } + void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); @@ -100,12 +129,20 @@ class MutatorsStack { void pop(); // Returns the iterator points to the top of the stack.. - const std::vector::const_reverse_iterator top() const; + const std::vector>::const_reverse_iterator top() const; // Returns an iterator pointing to the bottom of the stack. - const std::vector::const_reverse_iterator bottom() const; + const std::vector>::const_reverse_iterator bottom() const; bool operator==(const MutatorsStack& other) const { - return vector_ == other.vector_; + if (vector_.size() != other.vector_.size()) { + return false; + } + for (size_t i = 0; i < vector_.size(); i ++) { + if (*vector_[i] != *other.vector_[i]) { + return false; + } + } + return true; } bool operator!=(const MutatorsStack& other) const { @@ -113,8 +150,7 @@ class MutatorsStack { } private: - // TODO(cyanglaz): Make it a vector of unique_ptr to save some copies. - std::vector vector_; + std::vector> vector_; }; // MutatorsStack class EmbeddedViewParams { diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 784574837e638..d685c385ac7e9 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -36,10 +36,6 @@ void PlatformViewLayer::Paint(PaintContext& context) const { params.sizePoints = size_; params.mutatorsStack = &context.mutators_stack; - FML_DLOG(ERROR) << "address:"; - FML_DLOG(ERROR) << ¶ms.mutatorsStack; - FML_DLOG(ERROR) << &context.mutators_stack; - SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_, params); context.leaf_nodes_canvas = canvas; diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index bf65bbe96874b..51b5e510736d3 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -10,13 +10,23 @@ TEST(MutatorsStack, Initialization) { ASSERT_TRUE(true); } +TEST(MutatorsStack, CopyConstructor) { + flutter::MutatorsStack stack; + SkRRect rrect; + SkRect rect; + stack.pushClipRect(rect); + stack.pushClipRRect(rrect); + flutter::MutatorsStack copy = flutter::MutatorsStack(stack); + ASSERT_TRUE(copy == stack); +} + TEST(MutatorsStack, PushClipRect) { flutter::MutatorsStack stack; SkRect rect; stack.pushClipRect(rect); auto iter = stack.bottom(); - ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rect); - ASSERT_TRUE(iter->rect() == rect); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->get()->rect() == rect); } TEST(MutatorsStack, PushClipRRect) { @@ -24,8 +34,8 @@ TEST(MutatorsStack, PushClipRRect) { SkRRect rrect; stack.pushClipRRect(rrect); auto iter = stack.bottom(); - ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rrect); - ASSERT_TRUE(iter->rrect() == rrect); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->get()->rrect() == rrect); } TEST(MutatorsStack, PushTransform) { @@ -33,8 +43,8 @@ TEST(MutatorsStack, PushTransform) { SkMatrix matrix; stack.pushTransform(matrix); auto iter = stack.bottom(); - ASSERT_TRUE(iter->type() == flutter::MutatorType::transform); - ASSERT_TRUE(iter->matrix() == matrix); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->get()->matrix() == matrix); } TEST(MutatorsStack, Pop) { @@ -59,16 +69,16 @@ TEST(MutatorsStack, Traversal) { while (iter != stack.top()) { switch (index) { case 0: - ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rrect); - ASSERT_TRUE(iter->rrect() == rrect); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(iter->get()->rrect() == rrect); break; case 1: - ASSERT_TRUE(iter->type() == flutter::MutatorType::clip_rect); - ASSERT_TRUE(iter->rect() == rect); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(iter->get()->rect() == rect); break; case 2: - ASSERT_TRUE(iter->type() == flutter::MutatorType::transform); - ASSERT_TRUE(iter->matrix() == matrix); + ASSERT_TRUE(iter->get()->type() == flutter::MutatorType::transform); + ASSERT_TRUE(iter->get()->matrix() == matrix); break; default: break; @@ -98,6 +108,35 @@ TEST(MutatorsStack, Equality) { ASSERT_TRUE(stack == stackOther); } +TEST(Mutator, Initialization) { + SkRect rect; + flutter::Mutator mutator = flutter::Mutator(rect); + ASSERT_TRUE(mutator.type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(mutator.rect() == rect); + + SkRRect rrect; + flutter::Mutator mutator2 = flutter::Mutator(rrect); + ASSERT_TRUE(mutator2.type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(mutator2.rrect() == rrect); + + SkPath path; + flutter::Mutator mutator3 = flutter::Mutator(path); + ASSERT_TRUE(mutator3.type() == flutter::MutatorType::clip_path); + ASSERT_TRUE(mutator3.path() == path); + + SkMatrix matrix; + flutter::Mutator mutator4 = flutter::Mutator(matrix); + ASSERT_TRUE(mutator4.type() == flutter::MutatorType::transform); + ASSERT_TRUE(mutator4.matrix() == matrix); +} + +TEST(Mutator, CopyConstructor) { + SkRect rect; + flutter::Mutator mutator = flutter::Mutator(rect); + flutter::Mutator copy = flutter::Mutator(mutator); + ASSERT_TRUE(mutator == copy); +} + TEST(Mutator, Equality) { SkMatrix matrix; flutter::Mutator mutator = flutter::Mutator(matrix); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index e0395eb8cc1f7..2ed46ea0eca8d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -212,9 +212,9 @@ ResetAnchor(head.layer); // Apply transforms/clips. - auto iter = mutators_stack.bottom(); + auto iter = mutators_stack.bottom()->get(); int64_t clipCount = 0; - while (iter != mutators_stack.top()) { + while (iter != mutators_stack.top()->get()) { switch (iter->type()) { case transform: { CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); From 2eb40d64883bc4095d0c31f90a327eb6cf9d749b Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 11 Jun 2019 23:09:17 -0700 Subject: [PATCH 40/56] embeded param does not delete stack when destructed --- flow/embedded_views.h | 1 - 1 file changed, 1 deletion(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 1b771c714950a..6101674d42c10 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -137,7 +137,6 @@ class EmbeddedViewParams { *mutatorsStack == *other.mutatorsStack; } - ~EmbeddedViewParams() { delete mutatorsStack; } }; // This is only used on iOS when running in a non headless mode, From 7d1d0e5842eb480f297847165a6be356f4e29969 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 09:10:17 -0700 Subject: [PATCH 41/56] copy constructor for Mutator --- flow/embedded_views.h | 20 ++++++++++++++++++++ flow/mutators_stack_unittests.cc | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 6101674d42c10..5d5d8e917279b 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -21,6 +21,26 @@ enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { public: + + Mutator(const Mutator& other) { + switch (other.type_) { + case clip_rect: + rect_ = other.rect_; + break; + case clip_rrect: + rrect_ = other.rrect_; + break; + case clip_path: + path_ = new SkPath(*other.path_); + break; + case transform: + matrix_ = other.matrix_; + break; + default: + break; + } + } + explicit Mutator(const SkRect& rect) : type_(clip_rect), rect_(rect) {} explicit Mutator(const SkRRect& rrect) : type_(clip_rrect), rrect_(rrect) {} explicit Mutator(const SkPath& path) diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index bf65bbe96874b..499a8515c163f 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -78,6 +78,35 @@ TEST(MutatorsStack, Traversal) { } } +TEST(Mutator, Initialization) { + SkRect rect; + flutter::Mutator mutator = flutter::Mutator(rect); + ASSERT_TRUE(mutator.type() == flutter::MutatorType::clip_rect); + ASSERT_TRUE(mutator.rect() == rect); + + SkRRect rrect; + flutter::Mutator mutator2 = flutter::Mutator(rrect); + ASSERT_TRUE(mutator2.type() == flutter::MutatorType::clip_rrect); + ASSERT_TRUE(mutator2.rrect() == rrect); + + SkPath path; + flutter::Mutator mutator3 = flutter::Mutator(path); + ASSERT_TRUE(mutator3.type() == flutter::MutatorType::clip_path); + ASSERT_TRUE(mutator3.path() == path); + + SkMatrix matrix; + flutter::Mutator mutator4 = flutter::Mutator(matrix); + ASSERT_TRUE(mutator4.type() == flutter::MutatorType::transform); + ASSERT_TRUE(mutator4.matrix() == matrix); +} + +TEST(Mutator, CopyConstructor) { + SkRect rect; + flutter::Mutator mutator = flutter::Mutator(rect); + flutter::Mutator copy = flutter::Mutator(mutator); + ASSERT_TRUE(mutator == copy); +} + TEST(MutatorsStack, Equality) { flutter::MutatorsStack stack; SkMatrix matrix = SkMatrix::MakeScale(1, 1); From 46098a4c9fa4669a1ad35cc004ab39f984c3ca84 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 09:20:36 -0700 Subject: [PATCH 42/56] more tests --- flow/embedded_views.h | 3 ++- flow/mutators_stack_unittests.cc | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 5d5d8e917279b..a3579205a3b55 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -23,6 +23,7 @@ class Mutator { public: Mutator(const Mutator& other) { + type_ = other.type_; switch (other.type_) { case clip_rect: rect_ = other.rect_; @@ -40,7 +41,7 @@ class Mutator { break; } } - + explicit Mutator(const SkRect& rect) : type_(clip_rect), rect_(rect) {} explicit Mutator(const SkRRect& rrect) : type_(clip_rrect), rrect_(rrect) {} explicit Mutator(const SkPath& path) diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 499a8515c163f..4c6948d529dbb 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -105,6 +105,21 @@ TEST(Mutator, CopyConstructor) { flutter::Mutator mutator = flutter::Mutator(rect); flutter::Mutator copy = flutter::Mutator(mutator); ASSERT_TRUE(mutator == copy); + + SkRRect rrect; + flutter::Mutator mutator2 = flutter::Mutator(rrect); + flutter::Mutator copy2 = flutter::Mutator(mutator2); + ASSERT_TRUE(mutator2 == copy2); + + SkPath path; + flutter::Mutator mutator3 = flutter::Mutator(path); + flutter::Mutator copy3 = flutter::Mutator(mutator3); + ASSERT_TRUE(mutator3 == copy3); + + SkMatrix matrix; + flutter::Mutator mutator4 = flutter::Mutator(matrix); + flutter::Mutator copy4 = flutter::Mutator(mutator4); + ASSERT_TRUE(mutator4 == copy4); } TEST(MutatorsStack, Equality) { From fa1248a9a1f66f5710f387ffa4b548037b6a9713 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 09:52:43 -0700 Subject: [PATCH 43/56] remove the move to --- flow/embedded_views.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 5360d72771ae7..a487bdc762910 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -12,17 +12,17 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { void MutatorsStack::pushClipRect(const SkRect& rect) { Mutator element = Mutator(rect); - vector_.push_back(std::move(element)); + vector_.push_back(element); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { Mutator element = Mutator(rrect); - vector_.push_back(std::move(element)); + vector_.push_back(element); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { Mutator element = Mutator(matrix); - vector_.push_back(std::move(element)); + vector_.push_back(element); }; void MutatorsStack::pop() { From 50843a0ac2af253fc542d313eb06bafeaaaa17c9 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 10:35:12 -0700 Subject: [PATCH 44/56] share ptr for vector_ --- flow/embedded_views.cc | 16 ++--- flow/embedded_views.h | 12 +--- flow/mutators_stack_unittests.cc | 59 +++++-------------- .../framework/Source/FlutterPlatformViews.mm | 16 ++--- 4 files changed, 34 insertions(+), 69 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 3949d360f216c..63f4524b50b62 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -11,18 +11,18 @@ bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { }; void MutatorsStack::pushClipRect(const SkRect& rect) { - std::unique_ptr element = std::make_unique(rect); - vector_.push_back(std::move(element)); + std::shared_ptr element = std::make_shared(rect); + vector_.push_back(element); }; void MutatorsStack::pushClipRRect(const SkRRect& rrect) { - std::unique_ptr element = std::make_unique(rrect); - vector_.push_back(std::move(element)); + std::shared_ptr element = std::make_shared(rrect); + vector_.push_back(element); }; void MutatorsStack::pushTransform(const SkMatrix& matrix) { - std::unique_ptr element = std::make_unique(matrix); - vector_.push_back(std::move(element)); + std::shared_ptr element = std::make_shared(matrix); + vector_.push_back(element); }; @@ -30,11 +30,11 @@ void MutatorsStack::pop() { vector_.pop_back(); }; -const std::vector>::const_reverse_iterator MutatorsStack::top() const { +const std::vector>::const_reverse_iterator MutatorsStack::top() const { return vector_.rend(); }; -const std::vector>::const_reverse_iterator MutatorsStack::bottom() +const std::vector>::const_reverse_iterator MutatorsStack::bottom() const { return vector_.rbegin(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 526b4488fc1b0..c3e0cae7942e7 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -113,12 +113,6 @@ class MutatorsStack { MutatorsStack() = default; - MutatorsStack(const MutatorsStack& other) { - for (size_t i = 0; i < other.vector_.size(); i++) { - vector_[i] = std::make_unique(*other.vector_[i].get()); - } - } - void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); @@ -130,9 +124,9 @@ class MutatorsStack { void pop(); // Returns the iterator points to the top of the stack.. - const std::vector>::const_reverse_iterator top() const; + const std::vector>::const_reverse_iterator top() const; // Returns an iterator pointing to the bottom of the stack. - const std::vector>::const_reverse_iterator bottom() const; + const std::vector>::const_reverse_iterator bottom() const; bool operator==(const MutatorsStack& other) const { if (vector_.size() != other.vector_.size()) { @@ -151,7 +145,7 @@ class MutatorsStack { } private: - std::vector> vector_; + std::vector> vector_; }; // MutatorsStack class EmbeddedViewParams { diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index 60499e87040ef..e31f0c1fcbef4 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -88,50 +88,6 @@ TEST(MutatorsStack, Traversal) { } } -TEST(Mutator, Initialization) { - SkRect rect; - flutter::Mutator mutator = flutter::Mutator(rect); - ASSERT_TRUE(mutator.type() == flutter::MutatorType::clip_rect); - ASSERT_TRUE(mutator.rect() == rect); - - SkRRect rrect; - flutter::Mutator mutator2 = flutter::Mutator(rrect); - ASSERT_TRUE(mutator2.type() == flutter::MutatorType::clip_rrect); - ASSERT_TRUE(mutator2.rrect() == rrect); - - SkPath path; - flutter::Mutator mutator3 = flutter::Mutator(path); - ASSERT_TRUE(mutator3.type() == flutter::MutatorType::clip_path); - ASSERT_TRUE(mutator3.path() == path); - - SkMatrix matrix; - flutter::Mutator mutator4 = flutter::Mutator(matrix); - ASSERT_TRUE(mutator4.type() == flutter::MutatorType::transform); - ASSERT_TRUE(mutator4.matrix() == matrix); -} - -TEST(Mutator, CopyConstructor) { - SkRect rect; - flutter::Mutator mutator = flutter::Mutator(rect); - flutter::Mutator copy = flutter::Mutator(mutator); - ASSERT_TRUE(mutator == copy); - - SkRRect rrect; - flutter::Mutator mutator2 = flutter::Mutator(rrect); - flutter::Mutator copy2 = flutter::Mutator(mutator2); - ASSERT_TRUE(mutator2 == copy2); - - SkPath path; - flutter::Mutator mutator3 = flutter::Mutator(path); - flutter::Mutator copy3 = flutter::Mutator(mutator3); - ASSERT_TRUE(mutator3 == copy3); - - SkMatrix matrix; - flutter::Mutator mutator4 = flutter::Mutator(matrix); - flutter::Mutator copy4 = flutter::Mutator(mutator4); - ASSERT_TRUE(mutator4 == copy4); -} - TEST(MutatorsStack, Equality) { flutter::MutatorsStack stack; SkMatrix matrix = SkMatrix::MakeScale(1, 1); @@ -179,6 +135,21 @@ TEST(Mutator, CopyConstructor) { flutter::Mutator mutator = flutter::Mutator(rect); flutter::Mutator copy = flutter::Mutator(mutator); ASSERT_TRUE(mutator == copy); + + SkRRect rrect; + flutter::Mutator mutator2 = flutter::Mutator(rrect); + flutter::Mutator copy2 = flutter::Mutator(mutator2); + ASSERT_TRUE(mutator2 == copy2); + + SkPath path; + flutter::Mutator mutator3 = flutter::Mutator(path); + flutter::Mutator copy3 = flutter::Mutator(mutator3); + ASSERT_TRUE(mutator3 == copy3); + + SkMatrix matrix; + flutter::Mutator mutator4 = flutter::Mutator(matrix); + flutter::Mutator copy4 = flutter::Mutator(mutator4); + ASSERT_TRUE(mutator4 == copy4); } TEST(Mutator, Equality) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 2ed46ea0eca8d..eccf86912dc5d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -212,12 +212,12 @@ ResetAnchor(head.layer); // Apply transforms/clips. - auto iter = mutators_stack.bottom()->get(); + std::vector>::const_reverse_iterator iter = mutators_stack.bottom(); int64_t clipCount = 0; - while (iter != mutators_stack.top()->get()) { - switch (iter->type()) { + while (iter != mutators_stack.top()) { + switch ((*iter)->type()) { case transform: { - CATransform3D transform = GetCATransform3DFromSkMatrix(iter->matrix()); + CATransform3D transform = GetCATransform3DFromSkMatrix((*iter)->matrix()); head.layer.transform = CATransform3DConcat(head.layer.transform, transform); break; } @@ -233,10 +233,10 @@ [clipView addSubview:head]; } clipView.layer.transform = CATransform3DIdentity; - [(ChildClippingView*)clipView performClip:iter->type() - rect:iter->rect() - rrect:iter->rrect() - path:iter->path()]; + [(ChildClippingView*)clipView performClip:(*iter)->type() + rect:(*iter)->rect() + rrect:(*iter)->rrect() + path:(*iter)->path()]; ResetAnchor(clipView.layer); head = clipView; break; From 3b6b3b074806623034071cb5caa2700ae6b9d615 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 10:56:40 -0700 Subject: [PATCH 45/56] formatting --- flow/embedded_views.cc | 8 ++++---- flow/embedded_views.h | 11 +++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index 63f4524b50b62..9bbd913748079 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -25,17 +25,17 @@ void MutatorsStack::pushTransform(const SkMatrix& matrix) { vector_.push_back(element); }; - void MutatorsStack::pop() { vector_.pop_back(); }; -const std::vector>::const_reverse_iterator MutatorsStack::top() const { +const std::vector>::const_reverse_iterator +MutatorsStack::top() const { return vector_.rend(); }; -const std::vector>::const_reverse_iterator MutatorsStack::bottom() - const { +const std::vector>::const_reverse_iterator +MutatorsStack::bottom() const { return vector_.rbegin(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index c3e0cae7942e7..a47cabcf50c55 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -21,7 +21,6 @@ enum MutatorType { clip_rect, clip_rrect, clip_path, transform }; class Mutator { public: - Mutator(const Mutator& other) { type_ = other.type_; switch (other.type_) { @@ -110,7 +109,6 @@ class Mutator { // to a platform view P1 will result in T1(T2(T2(P1))). class MutatorsStack { public: - MutatorsStack() = default; void pushClipRect(const SkRect& rect); @@ -124,15 +122,17 @@ class MutatorsStack { void pop(); // Returns the iterator points to the top of the stack.. - const std::vector>::const_reverse_iterator top() const; + const std::vector>::const_reverse_iterator top() + const; // Returns an iterator pointing to the bottom of the stack. - const std::vector>::const_reverse_iterator bottom() const; + const std::vector>::const_reverse_iterator bottom() + const; bool operator==(const MutatorsStack& other) const { if (vector_.size() != other.vector_.size()) { return false; } - for (size_t i = 0; i < vector_.size(); i ++) { + for (size_t i = 0; i < vector_.size(); i++) { if (*vector_[i] != *other.vector_[i]) { return false; } @@ -167,7 +167,6 @@ class EmbeddedViewParams { sizePoints == other.sizePoints && *mutatorsStack == *other.mutatorsStack; } - }; // This is only used on iOS when running in a non headless mode, From b4b59ca227806597a827e05bf3c46076fa73379c Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 11:29:50 -0700 Subject: [PATCH 46/56] fixes unittest --- flow/mutators_stack_unittests.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flow/mutators_stack_unittests.cc b/flow/mutators_stack_unittests.cc index e31f0c1fcbef4..16d4b3d5a8ba0 100644 --- a/flow/mutators_stack_unittests.cc +++ b/flow/mutators_stack_unittests.cc @@ -109,7 +109,7 @@ TEST(MutatorsStack, Equality) { } TEST(Mutator, Initialization) { - SkRect rect; + SkRect rect = SkRect::MakeEmpty(); flutter::Mutator mutator = flutter::Mutator(rect); ASSERT_TRUE(mutator.type() == flutter::MutatorType::clip_rect); ASSERT_TRUE(mutator.rect() == rect); @@ -131,7 +131,7 @@ TEST(Mutator, Initialization) { } TEST(Mutator, CopyConstructor) { - SkRect rect; + SkRect rect = SkRect::MakeEmpty(); flutter::Mutator mutator = flutter::Mutator(rect); flutter::Mutator copy = flutter::Mutator(mutator); ASSERT_TRUE(mutator == copy); @@ -158,7 +158,7 @@ TEST(Mutator, Equality) { flutter::Mutator otherMutator = flutter::Mutator(matrix); ASSERT_TRUE(mutator == otherMutator); - SkRect rect; + SkRect rect = SkRect::MakeEmpty(); flutter::Mutator mutator2 = flutter::Mutator(rect); flutter::Mutator otherMutator2 = flutter::Mutator(rect); ASSERT_TRUE(mutator2 == otherMutator2); @@ -172,7 +172,7 @@ TEST(Mutator, Equality) { } TEST(Mutator, UnEquality) { - SkRect rect; + SkRect rect = SkRect::MakeEmpty(); flutter::Mutator mutator = flutter::Mutator(rect); SkMatrix matrix; flutter::Mutator notEqualMutator = flutter::Mutator(matrix); From ee57e42c9331d214b4a6b22c3c5212875e991e49 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Wed, 12 Jun 2019 11:31:08 -0700 Subject: [PATCH 47/56] Update BUILD.gn --- flow/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 71bb8538b8ef2..0e6dabb52b8f7 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -116,8 +116,8 @@ executable("flow_unittests") { "layers/performance_overlay_layer_unittests.cc", "layers/physical_shape_layer_unittests.cc", "matrix_decomposition_unittests.cc", + "mutators_stack_unittests.cc", "raster_cache_unittests.cc", - "mutators_stack_unittests.cc" ] deps = [ From 979d25136e0fa85a5e9326b1d3ef465856f43ab3 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 12:30:35 -0700 Subject: [PATCH 48/56] license file fix --- ci/licenses_golden/licenses_flutter | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e69dd41f3f3d2..c438a52daf986 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -73,6 +73,7 @@ FILE: ../../../flutter/flow/layers/transform_layer.h FILE: ../../../flutter/flow/matrix_decomposition.cc FILE: ../../../flutter/flow/matrix_decomposition.h FILE: ../../../flutter/flow/matrix_decomposition_unittests.cc +FILE: ../../../flutter/flow/mutators_stack_unittests.cc FILE: ../../../flutter/flow/paint_utils.cc FILE: ../../../flutter/flow/paint_utils.h FILE: ../../../flutter/flow/raster_cache.cc From a297a9f05c2b3f33d3ea0ac90fd47236dd7495b6 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 12 Jun 2019 13:58:55 -0700 Subject: [PATCH 49/56] remove testing logs --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 4545bc30643b0..eccf86912dc5d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -295,10 +295,8 @@ // Do nothing if the params didn't change. if (current_composition_params_.count(view_id) == 1 && current_composition_params_[view_id] == params) { - NSLog(@"not changed"); return picture_recorders_[view_id]->getRecordingCanvas(); } - NSLog(@"changed"); current_composition_params_[view_id] = EmbeddedViewParams(params); CompositeWithParams(view_id, params); From 6c7d75571752f4b1cf5ca3151c59b462f9f8bb57 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jun 2019 09:48:50 -0700 Subject: [PATCH 50/56] fix --- .../ios/framework/Source/FlutterPlatformViews_Internal.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index b81c6c48e7b80..36bf762a0ba20 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -37,10 +37,11 @@ - (void)setClip:(flutter::MutatorType)type rect:(const SkRect&)rect rrect:(const SkRRect&)rrect + path:(const SkPath&)path; - @end +@end - namespace flutter { +namespace flutter { // Converts a SkMatrix to CATransform3D. // Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix); From 13f515ce60f09dd7680a9546305dd4a092663fee Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jun 2019 10:00:35 -0700 Subject: [PATCH 51/56] mark --- flow/embedded_views.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 88cfac45d28b2..61804cc12ca59 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -113,14 +113,13 @@ class Mutator { // For example consider the following stack: [T1, T2, T3], where T1 is the top // of the stack and T3 is the bottom of the stack. Applying this mutators stack // to a platform view P1 will result in T1(T2(T2(P1))). -class MutatorsStack { +class MutatorsStack {//clip path public: MutatorsStack() = default; void pushClipRect(const SkRect& rect); void pushClipRRect(const SkRRect& rrect); void pushClipPath(const SkPath& path); - void pushTransform(const SkMatrix& matrix); // Removes the `Mutator` on the top of the stack From 467ac6593b5666d4926c32c9dd4ee40ae022525e Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jun 2019 10:04:28 -0700 Subject: [PATCH 52/56] revert mark --- flow/embedded_views.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 61804cc12ca59..337ebb4a567a9 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -113,7 +113,7 @@ class Mutator { // For example consider the following stack: [T1, T2, T3], where T1 is the top // of the stack and T3 is the bottom of the stack. Applying this mutators stack // to a platform view P1 will result in T1(T2(T2(P1))). -class MutatorsStack {//clip path +class MutatorsStack { public: MutatorsStack() = default; From ac72abfa406f5f7301e41f21f5b6efef2d77bc2a Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jun 2019 10:06:07 -0700 Subject: [PATCH 53/56] formatting --- .../Source/FlutterPlatformViews_Internal.h | 292 +++++++++--------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 36bf762a0ba20..61ecc4637ca34 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -42,152 +42,152 @@ @end namespace flutter { - // Converts a SkMatrix to CATransform3D. - // Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. - CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix); - - // Reset the anchor of `layer` to match the tranform operation from flow. - // The position of the `layer` should be unchanged after resetting the anchor. - void ResetAnchor(CALayer * layer); - - class IOSGLContext; - class IOSSurface; - - struct FlutterPlatformViewLayer { - FlutterPlatformViewLayer(fml::scoped_nsobject overlay_view, - std::unique_ptr ios_surface, - std::unique_ptr surface); - - ~FlutterPlatformViewLayer(); - - fml::scoped_nsobject overlay_view; - std::unique_ptr ios_surface; - std::unique_ptr surface; - }; - - class FlutterPlatformViewsController { - public: - FlutterPlatformViewsController(); - - ~FlutterPlatformViewsController(); - - void SetFlutterView(UIView* flutter_view); - - void SetFlutterViewController(UIViewController* flutter_view_controller); - - void RegisterViewFactory(NSObject* factory, NSString* factoryId); - - void SetFrameSize(SkISize frame_size); - - void PrerollCompositeEmbeddedView(int view_id); - - // Returns the `FlutterPlatformView` object associated with the view_id. - // - // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or - // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method - // returns nil. - NSObject* GetPlatformViewByID(int view_id); - - std::vector GetCurrentCanvases(); - - SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); - - // Discards all platform views instances and auxiliary resources. - void Reset(); - - bool SubmitFrame(bool gl_rendering, - GrContext* gr_context, - std::shared_ptr gl_context); - - void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); - - private: - fml::scoped_nsobject channel_; - fml::scoped_nsobject flutter_view_; - fml::scoped_nsobject flutter_view_controller_; - std::map>> factories_; - std::map>> views_; - std::map> touch_interceptors_; - // Mapping a platform view ID to the top most parent view (root_view) who is a direct child to - // the `flutter_view_`. - // - // The platform view with the view ID is a child of the root view; If the platform view is not - // clipped, and no clipping view is added, the root view will be the intercepting view. - std::map> root_views_; - // Mapping a platform view ID to its latest composition params. - std::map current_composition_params_; - // Mapping a platform view ID to the count of the clipping operations that were applied to the - // platform view last time it was composited. - std::map clip_count_; - std::map> overlays_; - // The GrContext that is currently used by all of the overlay surfaces. - // We track this to know when the GrContext for the Flutter app has changed - // so we can update the overlays with the new context. - GrContext* overlays_gr_context_; - SkISize frame_size_; - - // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on - // the next frame. - std::unordered_set views_to_dispose_; - - // A vector of embedded view IDs according to their composition order. - // The last ID in this vector belond to the that is composited on top of all others. - std::vector composition_order_; - - // The latest composition order that was presented in Present(). - std::vector active_composition_order_; - - std::map> picture_recorders_; - - void OnCreate(FlutterMethodCall* call, FlutterResult& result); - void OnDispose(FlutterMethodCall* call, FlutterResult& result); - void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result); - void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result); - - void DetachUnusedLayers(); - // Dispose the views in `views_to_dispose_`. - void DisposeViews(); - void EnsureOverlayInitialized(int64_t overlay_id); - void EnsureGLOverlayInitialized(int64_t overlay_id, - std::shared_ptr gl_context, - GrContext* gr_context); - - // Traverse the `mutators_stack` and return the number of clip operations. - int CountClips(const MutatorsStack& mutators_stack); - - // Make sure that platform_view has exactly clip_count ChildClippingView ancestors. - // - // Existing ChildClippingViews are re-used. If there are currently more ChildClippingView - // ancestors than needed, the extra views are detached. If there are less ChildClippingView - // ancestors than needed, new ChildClippingViews will be added. - // - // If head_clip_view was attached as a subview to FlutterView, the head of the newly constructed - // ChildClippingViews chain is attached to FlutterView in the same position. - // - // Returns the new head of the clip views chain. - UIView* ReconstructClipViewsChain(int number_of_clips, - UIView* platform_view, - UIView* head_clip_view); - - // Applies the mutators in the mutators_stack to the UIView chain that was constructed by - // `ReconstructClipViewsChain` - // - // Clips are applied to the super view with a CALayer mask. Transforms are applied to the - // current view that's at the head of the chain. For example the following mutators stack [T_1, - // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the - // following UIView tree: - // - // C_2 -> C_5 -> PLATFORM_VIEW - // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2) - // - // T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW. - // - // After each clip operation, we update the head to the super view of the current head. - void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view); - void CompositeWithParams(int view_id, const flutter::EmbeddedViewParams& params); - - FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); - }; +// Converts a SkMatrix to CATransform3D. +// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4. +CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix); + +// Reset the anchor of `layer` to match the tranform operation from flow. +// The position of the `layer` should be unchanged after resetting the anchor. +void ResetAnchor(CALayer* layer); + +class IOSGLContext; +class IOSSurface; + +struct FlutterPlatformViewLayer { + FlutterPlatformViewLayer(fml::scoped_nsobject overlay_view, + std::unique_ptr ios_surface, + std::unique_ptr surface); + + ~FlutterPlatformViewLayer(); + + fml::scoped_nsobject overlay_view; + std::unique_ptr ios_surface; + std::unique_ptr surface; +}; + +class FlutterPlatformViewsController { + public: + FlutterPlatformViewsController(); + + ~FlutterPlatformViewsController(); + + void SetFlutterView(UIView* flutter_view); + + void SetFlutterViewController(UIViewController* flutter_view_controller); + + void RegisterViewFactory(NSObject* factory, NSString* factoryId); + + void SetFrameSize(SkISize frame_size); + + void PrerollCompositeEmbeddedView(int view_id); + + // Returns the `FlutterPlatformView` object associated with the view_id. + // + // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or + // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method + // returns nil. + NSObject* GetPlatformViewByID(int view_id); + + std::vector GetCurrentCanvases(); + + SkCanvas* CompositeEmbeddedView(int view_id, const flutter::EmbeddedViewParams& params); + + // Discards all platform views instances and auxiliary resources. + void Reset(); + + bool SubmitFrame(bool gl_rendering, + GrContext* gr_context, + std::shared_ptr gl_context); + + void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); + + private: + fml::scoped_nsobject channel_; + fml::scoped_nsobject flutter_view_; + fml::scoped_nsobject flutter_view_controller_; + std::map>> factories_; + std::map>> views_; + std::map> touch_interceptors_; + // Mapping a platform view ID to the top most parent view (root_view) who is a direct child to + // the `flutter_view_`. + // + // The platform view with the view ID is a child of the root view; If the platform view is not + // clipped, and no clipping view is added, the root view will be the intercepting view. + std::map> root_views_; + // Mapping a platform view ID to its latest composition params. + std::map current_composition_params_; + // Mapping a platform view ID to the count of the clipping operations that were applied to the + // platform view last time it was composited. + std::map clip_count_; + std::map> overlays_; + // The GrContext that is currently used by all of the overlay surfaces. + // We track this to know when the GrContext for the Flutter app has changed + // so we can update the overlays with the new context. + GrContext* overlays_gr_context_; + SkISize frame_size_; + + // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on + // the next frame. + std::unordered_set views_to_dispose_; + + // A vector of embedded view IDs according to their composition order. + // The last ID in this vector belond to the that is composited on top of all others. + std::vector composition_order_; + + // The latest composition order that was presented in Present(). + std::vector active_composition_order_; + + std::map> picture_recorders_; + + void OnCreate(FlutterMethodCall* call, FlutterResult& result); + void OnDispose(FlutterMethodCall* call, FlutterResult& result); + void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result); + void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result); + + void DetachUnusedLayers(); + // Dispose the views in `views_to_dispose_`. + void DisposeViews(); + void EnsureOverlayInitialized(int64_t overlay_id); + void EnsureGLOverlayInitialized(int64_t overlay_id, + std::shared_ptr gl_context, + GrContext* gr_context); + + // Traverse the `mutators_stack` and return the number of clip operations. + int CountClips(const MutatorsStack& mutators_stack); + + // Make sure that platform_view has exactly clip_count ChildClippingView ancestors. + // + // Existing ChildClippingViews are re-used. If there are currently more ChildClippingView + // ancestors than needed, the extra views are detached. If there are less ChildClippingView + // ancestors than needed, new ChildClippingViews will be added. + // + // If head_clip_view was attached as a subview to FlutterView, the head of the newly constructed + // ChildClippingViews chain is attached to FlutterView in the same position. + // + // Returns the new head of the clip views chain. + UIView* ReconstructClipViewsChain(int number_of_clips, + UIView* platform_view, + UIView* head_clip_view); + + // Applies the mutators in the mutators_stack to the UIView chain that was constructed by + // `ReconstructClipViewsChain` + // + // Clips are applied to the super view with a CALayer mask. Transforms are applied to the + // current view that's at the head of the chain. For example the following mutators stack [T_1, + // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the + // following UIView tree: + // + // C_2 -> C_5 -> PLATFORM_VIEW + // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2) + // + // T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW. + // + // After each clip operation, we update the head to the super view of the current head. + void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view); + void CompositeWithParams(int view_id, const flutter::EmbeddedViewParams& params); + + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); +}; } // namespace flutter From e64360c654ab62b12afa5b83a8ac45cb12ef3634 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jun 2019 10:17:03 -0700 Subject: [PATCH 54/56] use constant --- .../ios/framework/Source/FlutterPlatformViews_Internal.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 90bdeb85c1541..04129351350f7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -6,6 +6,8 @@ #include "flutter/shell/platform/darwin/ios/ios_surface.h" +static int kMaxPointsInVerb = 4; + namespace flutter { FlutterPlatformViewLayer::FlutterPlatformViewLayer(fml::scoped_nsobject overlay_view, @@ -144,7 +146,7 @@ - (void)clipPath:(const SkPath&)path { // Loop through all verbs and translate them into CGPath SkPath::Iter iter(path, true); - SkPoint pts[4]; + SkPoint pts[kMaxPointsInVerb]; SkPath::Verb verb = iter.next(pts); while (verb != SkPath::kDone_Verb) { switch (verb) { From 9b2f55f6c37b45579b16b7c8d3cd41a7fc2bc51f Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 1 Jul 2019 14:12:20 -0700 Subject: [PATCH 55/56] review fixes --- .../ios/framework/Source/FlutterPlatformViews.mm | 7 +++++++ .../framework/Source/FlutterPlatformViews_Internal.mm | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 449839a507537..e4bba5fe5720c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -260,6 +260,13 @@ } ++iter; } + // Reverse scale based on screen scale. + // + // The UIKit frame is set based on the logical resolution instead of physical. + // (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html). + // However, flow is based on the physical resolution. For eaxmple, 1000 pixels in flow equals + // 500 points in UIKit. And until this point, we did all the calculation based on the flow + // resolution. So we need to scale down to match UIKit's logical resolution. CGFloat screenScale = [UIScreen mainScreen].scale; head.layer.transform = CATransform3DConcat( head.layer.transform, CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1)); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 04129351350f7..11013c6cc6af4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -148,28 +148,38 @@ - (void)clipPath:(const SkPath&)path { SkPath::Iter iter(path, true); SkPoint pts[kMaxPointsInVerb]; SkPath::Verb verb = iter.next(pts); + SkPoint last_pt_from_last_verb; while (verb != SkPath::kDone_Verb) { + if (verb == SkPath::kLine_Verb || verb == SkPath::kQuad_Verb || verb == SkPath::kConic_Verb || + verb == SkPath::kCubic_Verb) { + FML_DCHECK(last_pt_from_last_verb == pts[0]); + } switch (verb) { case SkPath::kMove_Verb: { CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y()); + last_pt_from_last_verb = pts[0]; break; } case SkPath::kLine_Verb: { CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y()); + last_pt_from_last_verb = pts[1]; break; } case SkPath::kQuad_Verb: { CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); + last_pt_from_last_verb = pts[2]; break; } case SkPath::kConic_Verb: { // Conic is not available in quartz, we use quad to approximate. CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); + last_pt_from_last_verb = pts[2]; break; } case SkPath::kCubic_Verb: { CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y()); + last_pt_from_last_verb = pts[3]; break; } case SkPath::kClose_Verb: { From ad6f4006a539157d4ba65e83b9bcbdfe9bc2093f Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 1 Jul 2019 14:36:25 -0700 Subject: [PATCH 56/56] add todo --- .../ios/framework/Source/FlutterPlatformViews_Internal.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 11013c6cc6af4..dc91dde315463 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -172,6 +172,8 @@ - (void)clipPath:(const SkPath&)path { } case SkPath::kConic_Verb: { // Conic is not available in quartz, we use quad to approximate. + // TODO(cyanglaz): Better approximate the conic path. + // https://github.com/flutter/flutter/issues/35062 CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); last_pt_from_last_verb = pts[2]; break;