Skip to content

Commit

Permalink
Reland "IOS Platform view transform/clipping (flutter#9075)" and fix …
Browse files Browse the repository at this point in the history
…the breakage. (flutter#9483)

* Revert "Revert "IOS Platform view transform/clipping (flutter#9075)" (flutter#9480)"

This reverts commit 00d929f.

* fix fuschia buid
  • Loading branch information
Chris Yang authored Jun 25, 2019
1 parent d90573a commit aa9b3a1
Show file tree
Hide file tree
Showing 17 changed files with 730 additions and 23 deletions.
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,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
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ 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",
]

Expand Down
30 changes: 30 additions & 0 deletions flow/embedded_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,34 @@ namespace flutter {
bool ExternalViewEmbedder::SubmitFrame(GrContext* context) {
return false;
};

void MutatorsStack::pushClipRect(const SkRect& rect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect);
vector_.push_back(element);
};

void MutatorsStack::pushClipRRect(const SkRRect& rrect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rrect);
vector_.push_back(element);
};

void MutatorsStack::pushTransform(const SkMatrix& matrix) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(matrix);
vector_.push_back(element);
};

void MutatorsStack::pop() {
vector_.pop_back();
};

const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator
MutatorsStack::top() const {
return vector_.rend();
};

const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator
MutatorsStack::bottom() const {
return vector_.rbegin();
};

} // namespace flutter
158 changes: 156 additions & 2 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,178 @@

#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 {

enum MutatorType { clip_rect, clip_rrect, clip_path, transform };

// Stores mutation information like clipping or transform.
//
// The `type` indicates the type of the mutation: clip_rect, transform and etc.
// Each `type` is paired with an object that supports the mutation. For example,
// if the `type` is clip_rect, `rect()` is used the represent the rect to be
// clipped. One mutation object must only contain one type of mutation.
class Mutator {
public:
Mutator(const Mutator& other) {
type_ = other.type_;
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)
: 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_; }
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_) {
return false;
}
if (type_ == clip_rect && rect_ == other.rect_) {
return true;
}
if (type_ == clip_rrect && 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 operator!=(const Mutator& other) const { return !operator==(other); }

bool isClipType() {
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_;
SkMatrix matrix_;
SkPath* path_;
};

}; // 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:
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
// and destroys it.
void pop();

// Returns an iterator pointing to the top of the stack.
const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator top()
const;
// Returns an iterator pointing to the bottom of the stack.
const std::vector<std::shared_ptr<Mutator>>::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] != *other.vector_[i]) {
return false;
}
}
return true;
}

bool operator!=(const MutatorsStack& other) const {
return !operator==(other);
}

private:
std::vector<std::shared_ptr<Mutator>> vector_;
}; // MutatorsStack

class EmbeddedViewParams {
public:
EmbeddedViewParams() = default;

EmbeddedViewParams(const EmbeddedViewParams& other) {
offsetPixels = other.offsetPixels;
sizePoints = other.sizePoints;
mutatorsStack = other.mutatorsStack;
};

SkPoint offsetPixels;
SkSize sizePoints;
MutatorsStack mutatorsStack;

bool operator==(const EmbeddedViewParams& other) const {
return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints;
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 {
// TODO(cyanglaz): Make embedder own the `EmbeddedViewParams`.

public:
ExternalViewEmbedder() = default;

Expand All @@ -46,7 +199,8 @@ class ExternalViewEmbedder {
virtual ~ExternalViewEmbedder() = default;

FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
};

}; // ExternalViewEmbedder

} // namespace flutter

Expand Down
3 changes: 3 additions & 0 deletions flow/layers/clip_rect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ 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.mutators_stack.pushClipRect(clip_rect_);

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.mutators_stack.pop();
}

} // namespace flutter
3 changes: 3 additions & 0 deletions flow/layers/clip_rrect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ 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.mutators_stack.pushClipRRect(clip_rrect_);

if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr);
}
PaintChildren(context);
if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->restore();
}
context.mutators_stack.pop();
}

} // namespace flutter
1 change: 1 addition & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class Layer {
SkCanvas* leaf_nodes_canvas;
GrContext* gr_context;
ExternalViewEmbedder* view_embedder;
MutatorsStack& mutators_stack;
const Stopwatch& raster_time;
const Stopwatch& ui_time;
TextureRegistry& texture_registry;
Expand Down
4 changes: 4 additions & 0 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
}
}

MutatorsStack stack;
Layer::PaintContext context = {
(SkCanvas*)&internal_nodes_canvas,
frame.canvas(),
frame.gr_context(),
frame.view_embedder(),
stack,
frame.context().raster_time(),
frame.context().ui_time(),
frame.context().texture_registry(),
Expand All @@ -108,6 +110,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
return nullptr;
}

MutatorsStack unused_stack;
const Stopwatch unused_stopwatch;
TextureRegistry unused_texture_registry;
SkMatrix root_surface_transformation;
Expand Down Expand Up @@ -135,6 +138,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
canvas, // canvas
nullptr,
nullptr,
unused_stack,
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
Expand Down
9 changes: 6 additions & 3 deletions flow/layers/performance_overlay_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ 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, mock_stopwatch,
mock_stopwatch, unused_texture_registry, nullptr, false};
nullptr, surface->getCanvas(),
nullptr, nullptr,
unused_stack, mock_stopwatch,
mock_stopwatch, unused_texture_registry,
nullptr, false};

// Specify font file to ensure the same font across different operation
// systems.
Expand Down
1 change: 1 addition & 0 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
params.offsetPixels =
SkPoint::Make(transform.getTranslateX(), transform.getTranslateY());
params.sizePoints = size_;
params.mutatorsStack = context.mutators_stack;

SkCanvas* canvas =
context.view_embedder->CompositeEmbeddedView(view_id_, params);
Expand Down
3 changes: 3 additions & 0 deletions flow/layers/transform_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ void TransformLayer::Paint(PaintContext& context) const {

SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->concat(transform_);
context.mutators_stack.pushTransform(transform_);

PaintChildren(context);
context.mutators_stack.pop();
}

} // namespace flutter
Loading

0 comments on commit aa9b3a1

Please sign in to comment.