mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland "Add GetBoundingRectAfterMutations to EmbeddedViewParams to calculate the final bounding rect for platform view #19170" (#19212)
This commit is contained in:
parent
2a5053f299
commit
5b1b59a34d
@ -26,6 +26,7 @@ FILE: ../../../flutter/common/task_runners.cc
|
||||
FILE: ../../../flutter/common/task_runners.h
|
||||
FILE: ../../../flutter/flow/compositor_context.cc
|
||||
FILE: ../../../flutter/flow/compositor_context.h
|
||||
FILE: ../../../flutter/flow/embedded_view_params_unittests.cc
|
||||
FILE: ../../../flutter/flow/embedded_views.cc
|
||||
FILE: ../../../flutter/flow/embedded_views.h
|
||||
FILE: ../../../flutter/flow/gl_context_switch.cc
|
||||
|
||||
@ -130,6 +130,7 @@ executable("flow_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"embedded_view_params_unittests.cc",
|
||||
"flow_run_all_unittests.cc",
|
||||
"flow_test_utils.cc",
|
||||
"flow_test_utils.h",
|
||||
|
||||
98
flow/embedded_view_params_unittests.cc
Normal file
98
flow/embedded_view_params_unittests.cc
Normal file
@ -0,0 +1,98 @@
|
||||
// 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 "flutter/fml/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations) {
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix;
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
|
||||
}
|
||||
|
||||
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix = SkMatrix::Scale(2, 2);
|
||||
stack.PushTransform(matrix);
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 2));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 2));
|
||||
}
|
||||
|
||||
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix = SkMatrix::MakeTrans(1, 1);
|
||||
stack.PushTransform(matrix);
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
|
||||
}
|
||||
|
||||
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix;
|
||||
matrix.setRotate(90);
|
||||
stack.PushTransform(matrix);
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
|
||||
FML_DLOG(ERROR) << rect.x();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
|
||||
}
|
||||
|
||||
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix;
|
||||
matrix.setRotate(45);
|
||||
stack.PushTransform(matrix);
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), sqrt(2)));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), sqrt(2)));
|
||||
}
|
||||
|
||||
TEST(EmbeddedViewParams,
|
||||
GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) {
|
||||
SkMatrix matrix = SkMatrix::MakeTrans(2, 2);
|
||||
matrix.preScale(3, 3);
|
||||
matrix.preRotate(90);
|
||||
|
||||
MutatorsStack stack;
|
||||
stack.PushTransform(matrix);
|
||||
|
||||
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
|
||||
const SkRect& rect = params.finalBoundingRect();
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 3));
|
||||
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 3));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -186,21 +186,49 @@ class EmbeddedViewParams {
|
||||
public:
|
||||
EmbeddedViewParams() = default;
|
||||
|
||||
EmbeddedViewParams(SkMatrix matrix,
|
||||
SkSize size_points,
|
||||
MutatorsStack mutators_stack)
|
||||
: matrix_(matrix),
|
||||
size_points_(size_points),
|
||||
mutators_stack_(mutators_stack) {
|
||||
SkPath path;
|
||||
SkRect starting_rect = SkRect::MakeSize(size_points);
|
||||
path.addRect(starting_rect);
|
||||
path.transform(matrix);
|
||||
final_bounding_rect_ = path.computeTightBounds();
|
||||
}
|
||||
|
||||
EmbeddedViewParams(const EmbeddedViewParams& other) {
|
||||
offsetPixels = other.offsetPixels;
|
||||
sizePoints = other.sizePoints;
|
||||
mutatorsStack = other.mutatorsStack;
|
||||
size_points_ = other.size_points_;
|
||||
mutators_stack_ = other.mutators_stack_;
|
||||
matrix_ = other.matrix_;
|
||||
final_bounding_rect_ = other.final_bounding_rect_;
|
||||
};
|
||||
|
||||
SkPoint offsetPixels;
|
||||
SkSize sizePoints;
|
||||
MutatorsStack mutatorsStack;
|
||||
// The original size of the platform view before any mutation matrix is
|
||||
// applied.
|
||||
const SkSize& sizePoints() const { return size_points_; };
|
||||
// The mutators stack contains the detailed step by step mutations for this
|
||||
// platform view.
|
||||
const MutatorsStack& mutatorsStack() const { return mutators_stack_; };
|
||||
// The bounding rect of the platform view after applying all the mutations.
|
||||
//
|
||||
// Clippings are ignored.
|
||||
const SkRect& finalBoundingRect() const { return final_bounding_rect_; }
|
||||
|
||||
bool operator==(const EmbeddedViewParams& other) const {
|
||||
return offsetPixels == other.offsetPixels &&
|
||||
sizePoints == other.sizePoints &&
|
||||
mutatorsStack == other.mutatorsStack;
|
||||
return size_points_ == other.size_points_ &&
|
||||
mutators_stack_ == other.mutators_stack_ &&
|
||||
final_bounding_rect_ == other.final_bounding_rect_ &&
|
||||
matrix_ == other.matrix_;
|
||||
}
|
||||
|
||||
private:
|
||||
SkMatrix matrix_;
|
||||
SkSize size_points_;
|
||||
MutatorsStack mutators_stack_;
|
||||
SkRect final_bounding_rect_;
|
||||
};
|
||||
|
||||
enum class PostPrerollResult { kResubmitFrame, kSuccess };
|
||||
|
||||
@ -27,11 +27,8 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
|
||||
}
|
||||
context->has_platform_view = true;
|
||||
std::unique_ptr<EmbeddedViewParams> params =
|
||||
std::make_unique<EmbeddedViewParams>();
|
||||
params->offsetPixels =
|
||||
SkPoint::Make(matrix.getTranslateX(), matrix.getTranslateY());
|
||||
params->sizePoints = size_;
|
||||
params->mutatorsStack = context->mutators_stack;
|
||||
std::make_unique<EmbeddedViewParams>(matrix, size_,
|
||||
context->mutators_stack);
|
||||
context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
|
||||
std::move(params));
|
||||
}
|
||||
|
||||
@ -63,10 +63,10 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int view_id) const {
|
||||
const EmbeddedViewParams& params = view_params_.at(view_id);
|
||||
// TODO(egarciad): The rect should be computed from the mutator stack.
|
||||
// https://github.com/flutter/flutter/issues/59821
|
||||
return SkRect::MakeXYWH(params.offsetPixels.x(), //
|
||||
params.offsetPixels.y(), //
|
||||
params.sizePoints.width() * device_pixel_ratio_, //
|
||||
params.sizePoints.height() * device_pixel_ratio_ //
|
||||
return SkRect::MakeXYWH(params.finalBoundingRect().x(), //
|
||||
params.finalBoundingRect().y(), //
|
||||
params.sizePoints().width() * device_pixel_ratio_, //
|
||||
params.sizePoints().height() * device_pixel_ratio_ //
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -198,9 +198,11 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect) {
|
||||
embedder->BeginFrame(SkISize::Make(100, 100), nullptr, 1.5,
|
||||
raster_thread_merger);
|
||||
|
||||
auto view_params = std::make_unique<EmbeddedViewParams>();
|
||||
view_params->offsetPixels = SkPoint::Make(10, 20);
|
||||
view_params->sizePoints = SkSize::Make(30, 40);
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix = SkMatrix::MakeTrans(10, 20);
|
||||
stack.PushTransform(matrix);
|
||||
auto view_params =
|
||||
std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(30, 40), stack);
|
||||
|
||||
auto view_id = 0;
|
||||
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params));
|
||||
@ -219,14 +221,21 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect__ChangedParams) {
|
||||
raster_thread_merger);
|
||||
|
||||
auto view_id = 0;
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
|
||||
view_params_1->offsetPixels = SkPoint::Make(10, 20);
|
||||
view_params_1->sizePoints = SkSize::Make(30, 40);
|
||||
|
||||
MutatorsStack stack1;
|
||||
SkMatrix matrix1 = SkMatrix::MakeTrans(10, 20);
|
||||
stack1.PushTransform(matrix1);
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
|
||||
matrix1, SkSize::Make(30, 40), stack1);
|
||||
|
||||
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_1));
|
||||
|
||||
auto view_params_2 = std::make_unique<EmbeddedViewParams>();
|
||||
view_params_2->offsetPixels = SkPoint::Make(50, 60);
|
||||
view_params_2->sizePoints = SkSize::Make(70, 80);
|
||||
MutatorsStack stack2;
|
||||
SkMatrix matrix2 = SkMatrix::MakeTrans(50, 60);
|
||||
stack2.PushTransform(matrix2);
|
||||
auto view_params_2 = std::make_unique<EmbeddedViewParams>(
|
||||
matrix2, SkSize::Make(70, 80), stack2);
|
||||
|
||||
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_2));
|
||||
|
||||
ASSERT_EQ(SkRect::MakeXYWH(50, 60, 105, 120), embedder->GetViewRect(view_id));
|
||||
@ -281,11 +290,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
|
||||
// Add an Android view.
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
|
||||
view_params_1->offsetPixels = SkPoint::Make(100, 100);
|
||||
MutatorsStack stack1;
|
||||
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
|
||||
stack1.PushTransform(matrix1);
|
||||
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
|
||||
// the offsetPixels, but not the sizePoints.
|
||||
view_params_1->sizePoints = SkSize::Make(200, 200);
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
|
||||
matrix1, SkSize::Make(200, 200), stack1);
|
||||
|
||||
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
|
||||
// This is the recording canvas flow writes to.
|
||||
auto canvas_1 = embedder->CompositeEmbeddedView(0);
|
||||
@ -329,11 +341,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
|
||||
// Add an Android view.
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
|
||||
view_params_1->offsetPixels = SkPoint::Make(100, 100);
|
||||
MutatorsStack stack1;
|
||||
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
|
||||
stack1.PushTransform(matrix1);
|
||||
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
|
||||
// the offsetPixels, but not the sizePoints.
|
||||
view_params_1->sizePoints = SkSize::Make(200, 200);
|
||||
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
|
||||
matrix1, SkSize::Make(200, 200), stack1);
|
||||
|
||||
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
|
||||
// This is the recording canvas flow writes to.
|
||||
auto canvas_1 = embedder->CompositeEmbeddedView(0);
|
||||
|
||||
@ -407,13 +407,14 @@ void FlutterPlatformViewsController::ApplyMutators(const MutatorsStack& mutators
|
||||
|
||||
void FlutterPlatformViewsController::CompositeWithParams(int view_id,
|
||||
const EmbeddedViewParams& params) {
|
||||
CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height());
|
||||
CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
|
||||
UIView* touchInterceptor = touch_interceptors_[view_id].get();
|
||||
touchInterceptor.layer.transform = CATransform3DIdentity;
|
||||
touchInterceptor.frame = frame;
|
||||
touchInterceptor.alpha = 1;
|
||||
|
||||
int currentClippingCount = CountClips(params.mutatorsStack);
|
||||
const MutatorsStack& mutatorStack = params.mutatorsStack();
|
||||
int currentClippingCount = CountClips(mutatorStack);
|
||||
int previousClippingCount = clip_count_[view_id];
|
||||
if (currentClippingCount != previousClippingCount) {
|
||||
clip_count_[view_id] = currentClippingCount;
|
||||
@ -424,7 +425,7 @@ void FlutterPlatformViewsController::CompositeWithParams(int view_id,
|
||||
ReconstructClipViewsChain(currentClippingCount, touchInterceptor, oldPlatformViewRoot);
|
||||
root_views_[view_id] = fml::scoped_nsobject<UIView>([newPlatformViewRoot retain]);
|
||||
}
|
||||
ApplyMutators(params.mutatorsStack, touchInterceptor);
|
||||
ApplyMutators(mutatorStack, touchInterceptor);
|
||||
}
|
||||
|
||||
SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(int view_id) {
|
||||
|
||||
@ -108,7 +108,7 @@ void EmbedderLayers::PushPlatformViewLayer(
|
||||
view.struct_size = sizeof(FlutterPlatformView);
|
||||
view.identifier = identifier;
|
||||
|
||||
const auto& mutators = params.mutatorsStack;
|
||||
const auto& mutators = params.mutatorsStack();
|
||||
|
||||
std::vector<const FlutterPlatformViewMutation*> mutations_array;
|
||||
|
||||
@ -180,10 +180,10 @@ void EmbedderLayers::PushPlatformViewLayer(
|
||||
layer.platform_view = platform_views_referenced_.back().get();
|
||||
|
||||
const auto layer_bounds =
|
||||
SkRect::MakeXYWH(params.offsetPixels.x(), //
|
||||
params.offsetPixels.y(), //
|
||||
params.sizePoints.width() * device_pixel_ratio_, //
|
||||
params.sizePoints.height() * device_pixel_ratio_ //
|
||||
SkRect::MakeXYWH(params.finalBoundingRect().x(), //
|
||||
params.finalBoundingRect().y(), //
|
||||
params.sizePoints().width() * device_pixel_ratio_, //
|
||||
params.sizePoints().height() * device_pixel_ratio_ //
|
||||
);
|
||||
|
||||
const auto transformed_layer_bounds =
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user