Skip to content

Commit 120a32f

Browse files
Chris Yangzhongwuzw
authored andcommitted
Reland "Add GetBoundingRectAfterMutations to EmbeddedViewParams to calculate the final bounding rect for platform view flutter#19170" (flutter#19212)
1 parent 9b49d62 commit 120a32f

9 files changed

Lines changed: 182 additions & 41 deletions

File tree

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ FILE: ../../../flutter/common/task_runners.cc
2626
FILE: ../../../flutter/common/task_runners.h
2727
FILE: ../../../flutter/flow/compositor_context.cc
2828
FILE: ../../../flutter/flow/compositor_context.h
29+
FILE: ../../../flutter/flow/embedded_view_params_unittests.cc
2930
FILE: ../../../flutter/flow/embedded_views.cc
3031
FILE: ../../../flutter/flow/embedded_views.h
3132
FILE: ../../../flutter/flow/gl_context_switch.cc

flow/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ executable("flow_unittests") {
130130
testonly = true
131131

132132
sources = [
133+
"embedded_view_params_unittests.cc",
133134
"flow_run_all_unittests.cc",
134135
"flow_test_utils.cc",
135136
"flow_test_utils.h",
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/flow/embedded_views.h"
6+
#include "flutter/fml/logging.h"
7+
#include "gtest/gtest.h"
8+
9+
namespace flutter {
10+
namespace testing {
11+
12+
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations) {
13+
MutatorsStack stack;
14+
SkMatrix matrix;
15+
16+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
17+
const SkRect& rect = params.finalBoundingRect();
18+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
19+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
20+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
21+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
22+
}
23+
24+
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
25+
MutatorsStack stack;
26+
SkMatrix matrix = SkMatrix::Scale(2, 2);
27+
stack.PushTransform(matrix);
28+
29+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
30+
const SkRect& rect = params.finalBoundingRect();
31+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
32+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
33+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 2));
34+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 2));
35+
}
36+
37+
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
38+
MutatorsStack stack;
39+
SkMatrix matrix = SkMatrix::MakeTrans(1, 1);
40+
stack.PushTransform(matrix);
41+
42+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
43+
const SkRect& rect = params.finalBoundingRect();
44+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1));
45+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1));
46+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
47+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
48+
}
49+
50+
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
51+
MutatorsStack stack;
52+
SkMatrix matrix;
53+
matrix.setRotate(90);
54+
stack.PushTransform(matrix);
55+
56+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
57+
const SkRect& rect = params.finalBoundingRect();
58+
59+
FML_DLOG(ERROR) << rect.x();
60+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
61+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
62+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
63+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
64+
}
65+
66+
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
67+
MutatorsStack stack;
68+
SkMatrix matrix;
69+
matrix.setRotate(45);
70+
stack.PushTransform(matrix);
71+
72+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
73+
const SkRect& rect = params.finalBoundingRect();
74+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2));
75+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
76+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), sqrt(2)));
77+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), sqrt(2)));
78+
}
79+
80+
TEST(EmbeddedViewParams,
81+
GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) {
82+
SkMatrix matrix = SkMatrix::MakeTrans(2, 2);
83+
matrix.preScale(3, 3);
84+
matrix.preRotate(90);
85+
86+
MutatorsStack stack;
87+
stack.PushTransform(matrix);
88+
89+
EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
90+
const SkRect& rect = params.finalBoundingRect();
91+
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
92+
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2));
93+
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 3));
94+
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 3));
95+
}
96+
97+
} // namespace testing
98+
} // namespace flutter

flow/embedded_views.h

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,21 +186,49 @@ class EmbeddedViewParams {
186186
public:
187187
EmbeddedViewParams() = default;
188188

189+
EmbeddedViewParams(SkMatrix matrix,
190+
SkSize size_points,
191+
MutatorsStack mutators_stack)
192+
: matrix_(matrix),
193+
size_points_(size_points),
194+
mutators_stack_(mutators_stack) {
195+
SkPath path;
196+
SkRect starting_rect = SkRect::MakeSize(size_points);
197+
path.addRect(starting_rect);
198+
path.transform(matrix);
199+
final_bounding_rect_ = path.computeTightBounds();
200+
}
201+
189202
EmbeddedViewParams(const EmbeddedViewParams& other) {
190-
offsetPixels = other.offsetPixels;
191-
sizePoints = other.sizePoints;
192-
mutatorsStack = other.mutatorsStack;
203+
size_points_ = other.size_points_;
204+
mutators_stack_ = other.mutators_stack_;
205+
matrix_ = other.matrix_;
206+
final_bounding_rect_ = other.final_bounding_rect_;
193207
};
194208

195-
SkPoint offsetPixels;
196-
SkSize sizePoints;
197-
MutatorsStack mutatorsStack;
209+
// The original size of the platform view before any mutation matrix is
210+
// applied.
211+
const SkSize& sizePoints() const { return size_points_; };
212+
// The mutators stack contains the detailed step by step mutations for this
213+
// platform view.
214+
const MutatorsStack& mutatorsStack() const { return mutators_stack_; };
215+
// The bounding rect of the platform view after applying all the mutations.
216+
//
217+
// Clippings are ignored.
218+
const SkRect& finalBoundingRect() const { return final_bounding_rect_; }
198219

199220
bool operator==(const EmbeddedViewParams& other) const {
200-
return offsetPixels == other.offsetPixels &&
201-
sizePoints == other.sizePoints &&
202-
mutatorsStack == other.mutatorsStack;
221+
return size_points_ == other.size_points_ &&
222+
mutators_stack_ == other.mutators_stack_ &&
223+
final_bounding_rect_ == other.final_bounding_rect_ &&
224+
matrix_ == other.matrix_;
203225
}
226+
227+
private:
228+
SkMatrix matrix_;
229+
SkSize size_points_;
230+
MutatorsStack mutators_stack_;
231+
SkRect final_bounding_rect_;
204232
};
205233

206234
enum class PostPrerollResult { kResubmitFrame, kSuccess };

flow/layers/platform_view_layer.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
2727
}
2828
context->has_platform_view = true;
2929
std::unique_ptr<EmbeddedViewParams> params =
30-
std::make_unique<EmbeddedViewParams>();
31-
params->offsetPixels =
32-
SkPoint::Make(matrix.getTranslateX(), matrix.getTranslateY());
33-
params->sizePoints = size_;
34-
params->mutatorsStack = context->mutators_stack;
30+
std::make_unique<EmbeddedViewParams>(matrix, size_,
31+
context->mutators_stack);
3532
context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
3633
std::move(params));
3734
}

shell/platform/android/external_view_embedder/external_view_embedder.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int view_id) const {
6363
const EmbeddedViewParams& params = view_params_.at(view_id);
6464
// TODO(egarciad): The rect should be computed from the mutator stack.
6565
// https://github.com/flutter/flutter/issues/59821
66-
return SkRect::MakeXYWH(params.offsetPixels.x(), //
67-
params.offsetPixels.y(), //
68-
params.sizePoints.width() * device_pixel_ratio_, //
69-
params.sizePoints.height() * device_pixel_ratio_ //
66+
return SkRect::MakeXYWH(params.finalBoundingRect().x(), //
67+
params.finalBoundingRect().y(), //
68+
params.sizePoints().width() * device_pixel_ratio_, //
69+
params.sizePoints().height() * device_pixel_ratio_ //
7070
);
7171
}
7272

shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,11 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect) {
198198
embedder->BeginFrame(SkISize::Make(100, 100), nullptr, 1.5,
199199
raster_thread_merger);
200200

201-
auto view_params = std::make_unique<EmbeddedViewParams>();
202-
view_params->offsetPixels = SkPoint::Make(10, 20);
203-
view_params->sizePoints = SkSize::Make(30, 40);
201+
MutatorsStack stack;
202+
SkMatrix matrix = SkMatrix::MakeTrans(10, 20);
203+
stack.PushTransform(matrix);
204+
auto view_params =
205+
std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(30, 40), stack);
204206

205207
auto view_id = 0;
206208
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params));
@@ -219,14 +221,21 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect__ChangedParams) {
219221
raster_thread_merger);
220222

221223
auto view_id = 0;
222-
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
223-
view_params_1->offsetPixels = SkPoint::Make(10, 20);
224-
view_params_1->sizePoints = SkSize::Make(30, 40);
224+
225+
MutatorsStack stack1;
226+
SkMatrix matrix1 = SkMatrix::MakeTrans(10, 20);
227+
stack1.PushTransform(matrix1);
228+
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
229+
matrix1, SkSize::Make(30, 40), stack1);
230+
225231
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_1));
226232

227-
auto view_params_2 = std::make_unique<EmbeddedViewParams>();
228-
view_params_2->offsetPixels = SkPoint::Make(50, 60);
229-
view_params_2->sizePoints = SkSize::Make(70, 80);
233+
MutatorsStack stack2;
234+
SkMatrix matrix2 = SkMatrix::MakeTrans(50, 60);
235+
stack2.PushTransform(matrix2);
236+
auto view_params_2 = std::make_unique<EmbeddedViewParams>(
237+
matrix2, SkSize::Make(70, 80), stack2);
238+
230239
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_2));
231240

232241
ASSERT_EQ(SkRect::MakeXYWH(50, 60, 105, 120), embedder->GetViewRect(view_id));
@@ -281,11 +290,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
281290
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
282291

283292
// Add an Android view.
284-
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
285-
view_params_1->offsetPixels = SkPoint::Make(100, 100);
293+
MutatorsStack stack1;
294+
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
295+
stack1.PushTransform(matrix1);
286296
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
287297
// the offsetPixels, but not the sizePoints.
288-
view_params_1->sizePoints = SkSize::Make(200, 200);
298+
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
299+
matrix1, SkSize::Make(200, 200), stack1);
300+
289301
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
290302
// This is the recording canvas flow writes to.
291303
auto canvas_1 = embedder->CompositeEmbeddedView(0);
@@ -329,11 +341,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
329341
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
330342

331343
// Add an Android view.
332-
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
333-
view_params_1->offsetPixels = SkPoint::Make(100, 100);
344+
MutatorsStack stack1;
345+
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
346+
stack1.PushTransform(matrix1);
334347
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
335348
// the offsetPixels, but not the sizePoints.
336-
view_params_1->sizePoints = SkSize::Make(200, 200);
349+
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
350+
matrix1, SkSize::Make(200, 200), stack1);
351+
337352
embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
338353
// This is the recording canvas flow writes to.
339354
auto canvas_1 = embedder->CompositeEmbeddedView(0);

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,13 +407,14 @@
407407

408408
void FlutterPlatformViewsController::CompositeWithParams(int view_id,
409409
const EmbeddedViewParams& params) {
410-
CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height());
410+
CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
411411
UIView* touchInterceptor = touch_interceptors_[view_id].get();
412412
touchInterceptor.layer.transform = CATransform3DIdentity;
413413
touchInterceptor.frame = frame;
414414
touchInterceptor.alpha = 1;
415415

416-
int currentClippingCount = CountClips(params.mutatorsStack);
416+
const MutatorsStack& mutatorStack = params.mutatorsStack();
417+
int currentClippingCount = CountClips(mutatorStack);
417418
int previousClippingCount = clip_count_[view_id];
418419
if (currentClippingCount != previousClippingCount) {
419420
clip_count_[view_id] = currentClippingCount;
@@ -424,7 +425,7 @@
424425
ReconstructClipViewsChain(currentClippingCount, touchInterceptor, oldPlatformViewRoot);
425426
root_views_[view_id] = fml::scoped_nsobject<UIView>([newPlatformViewRoot retain]);
426427
}
427-
ApplyMutators(params.mutatorsStack, touchInterceptor);
428+
ApplyMutators(mutatorStack, touchInterceptor);
428429
}
429430

430431
SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(int view_id) {

shell/platform/embedder/embedder_layers.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void EmbedderLayers::PushPlatformViewLayer(
108108
view.struct_size = sizeof(FlutterPlatformView);
109109
view.identifier = identifier;
110110

111-
const auto& mutators = params.mutatorsStack;
111+
const auto& mutators = params.mutatorsStack();
112112

113113
std::vector<const FlutterPlatformViewMutation*> mutations_array;
114114

@@ -180,10 +180,10 @@ void EmbedderLayers::PushPlatformViewLayer(
180180
layer.platform_view = platform_views_referenced_.back().get();
181181

182182
const auto layer_bounds =
183-
SkRect::MakeXYWH(params.offsetPixels.x(), //
184-
params.offsetPixels.y(), //
185-
params.sizePoints.width() * device_pixel_ratio_, //
186-
params.sizePoints.height() * device_pixel_ratio_ //
183+
SkRect::MakeXYWH(params.finalBoundingRect().x(), //
184+
params.finalBoundingRect().y(), //
185+
params.sizePoints().width() * device_pixel_ratio_, //
186+
params.sizePoints().height() * device_pixel_ratio_ //
187187
);
188188

189189
const auto transformed_layer_bounds =

0 commit comments

Comments
 (0)