-
Notifications
You must be signed in to change notification settings - Fork 6k
IOS Platform view transform/clipping #9075
Changes from 16 commits
853cbd6
72042cf
8489c08
647e66b
f7d7aaa
c0741b2
6e95d26
a3e1d61
4cf9f8a
1daacb0
04d1f40
5b05eb2
9b290cb
52a8252
3a899fa
cabc67a
4496b21
4bdae98
33513b9
e8926a5
3f4c586
d4f88f2
4eeb64f
6d78901
e494853
81e5c19
ea11fad
2c79050
0f70a44
32d2681
b874420
a1794de
2f0125c
d22acbd
2b08642
1599067
a027fa0
12ff43a
a9a660f
f4b9503
7c0fa63
2eb40d6
6d4c82c
7d1d0e5
46098a4
fa1248a
dd0eed8
50843a0
31ec192
3b6b3b0
b4b59ca
ee57e42
979d251
b45ad9a
b40944e
701afe5
551445d
8622d13
d46290e
8f86532
a5b7f8a
b0d3110
ff442ee
5f0a513
455a495
cf36c46
fd498ee
78acc1f
aeb56e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,51 @@ | |
|
|
||
| namespace flutter { | ||
|
|
||
| ExternalViewEmbedder::ExternalViewEmbedder() | ||
| : transformStack(std::make_shared<FlutterEmbededViewTransformStack>()){}; | ||
|
|
||
| bool ExternalViewEmbedder::SubmitFrame(GrContext* context) { | ||
| return false; | ||
| }; | ||
|
|
||
| #pragma mark - FlutterEmbededViewTransformStack | ||
|
|
||
| void FlutterEmbededViewTransformStack::pushClipRect(const SkRect& rect) { | ||
| FlutterEmbededViewTransformElement element = | ||
| FlutterEmbededViewTransformElement(); | ||
| element.setType(clip_rect); | ||
| element.setRect(rect); | ||
| vector_.push_back(element); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: we can save some copies by making it a vector of unique pointers
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried it naively and caused some issue when trying to copy the stack to the params, reverting the change and adding a TODO and will work on it in future. |
||
| }; | ||
|
|
||
| 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(); | ||
| element.setType(transform); | ||
| element.setMatrix(matrix); | ||
| vector_.push_back(element); | ||
| }; | ||
|
|
||
| void FlutterEmbededViewTransformStack::pop() { | ||
| vector_.pop_back(); | ||
| } | ||
|
|
||
| std::vector<FlutterEmbededViewTransformElement>::reverse_iterator | ||
| FlutterEmbededViewTransformStack::rbegin() { | ||
| return vector_.rbegin(); | ||
| } | ||
|
|
||
| std::vector<FlutterEmbededViewTransformElement>::reverse_iterator | ||
| FlutterEmbededViewTransformStack::rend() { | ||
| return vector_.rend(); | ||
| } | ||
|
|
||
| } // namespace flutter | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,23 +9,37 @@ | |
|
|
||
| #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" | ||
|
|
||
| namespace flutter { | ||
|
|
||
| class FlutterEmbededViewTransformStack; | ||
| class FlutterEmbededViewTransformElement; | ||
|
|
||
| class EmbeddedViewParams { | ||
| public: | ||
| SkPoint offsetPixels; | ||
| SkSize sizePoints; | ||
| std::shared_ptr<FlutterEmbededViewTransformStack> transformStack; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why a shared pointer?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both |
||
|
|
||
| friend bool operator==(const EmbeddedViewParams& lhs, | ||
|
cyanglaz marked this conversation as resolved.
Outdated
|
||
| const EmbeddedViewParams& rhs) { | ||
| return lhs.offsetPixels == rhs.offsetPixels && | ||
| lhs.sizePoints == rhs.sizePoints && | ||
| lhs.transformStack == rhs.transformStack; | ||
| } | ||
| }; | ||
|
|
||
| // 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(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. revert
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| virtual void BeginFrame(SkISize frame_size) = 0; | ||
|
|
||
|
|
@@ -42,8 +56,88 @@ class ExternalViewEmbedder { | |
| virtual ~ExternalViewEmbedder() = default; | ||
|
|
||
| FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder); | ||
|
|
||
| #pragma mark - transforms | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we don't do these in our C++ code
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| std::shared_ptr<FlutterEmbededViewTransformStack> transformStack; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the state of an ongoing paint traversal, I do not think it belongs in ExternalViewEmbedder(e.g think of an hypothetical world where we'll be painting multiple parts of the tree in parallel). I'd keep this in PaintContext.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Do you think all the stack related classes belong to the same file of paintContext?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
|
||
| }; // ExternalViewEmbedder | ||
|
|
||
| class FlutterEmbededViewTransformStack { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably omit the "Flutter" prefix from these classes.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our language is a little ambiguous around "transforms", e.g usually we mean the transform matrix when we say transforms. I don't have a good idea though. Update: I asked @chinmaygarde and he suggested to call it mutators, I think it's a much more reasonable name.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add unit tests for this class.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
| public: | ||
| void pushClipRect(const SkRect& rect); | ||
| void pushClipRRect(const SkRRect& rrect); | ||
| void pushClipPath(const SkPath& path); | ||
|
|
||
| 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. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just from reading this comment I'm not sure what's the "bottom of the stack" the mutator that should apply to all other mutators in the stack, or the one that all other mutators applies to? can you make this more clear in the comment ?(for both iterators)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. Updated to Let me know what you think.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: // 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 {
...
// Returns an iterator pointing to the top of the stack.
std::vector<EmbeddedViewMutator>::reverse_iterator top();
// Returns an iterator pointing to the bottom of the stack.
std::vector<EmbeddedViewMutator>::reverse_iterator bottom();
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| std::vector<FlutterEmbededViewTransformElement>::reverse_iterator rbegin(); | ||
| // Returns the iterator points to the top of the stack. | ||
| std::vector<FlutterEmbededViewTransformElement>::reverse_iterator rend(); | ||
|
|
||
| bool operator==(const FlutterEmbededViewTransformStack& other) const { | ||
| return vector_ == other.vector_; | ||
| } | ||
|
|
||
| private: | ||
| std::vector<FlutterEmbededViewTransformElement> vector_; | ||
| }; // FlutterEmbededViewTransformStack | ||
|
|
||
| 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; } | ||
| 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_; } | ||
|
|
||
| bool operator==(const FlutterEmbededViewTransformElement& other) const { | ||
| if (type_ != other.type_) { | ||
| return false; | ||
| } | ||
| if (type_ == clip_rect && rect_ == other.rect_) { | ||
| return true; | ||
| } | ||
| 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; | ||
| } | ||
|
|
||
| bool isClipType() { | ||
| return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path; | ||
| } | ||
|
|
||
| private: | ||
| FlutterEmbededViewTransformType type_; | ||
| SkRect rect_; | ||
| SkRRect rrect_; | ||
| SkPath path_; | ||
| SkMatrix matrix_; | ||
| }; // FlutterEmbededViewTransformElement | ||
|
|
||
| } // namespace flutter | ||
|
|
||
| #endif // FLUTTER_FLOW_EMBEDDED_VIEWS_H_ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,13 +50,15 @@ 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_); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. view_embedder can be null, protect against it in all call sites.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { | ||
| context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr); | ||
| } | ||
| PaintChildren(context); | ||
| if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { | ||
| context.internal_nodes_canvas->restore(); | ||
| } | ||
| context.view_embedder->transformStack->pop(); | ||
| } | ||
|
|
||
| } // namespace flutter | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done