Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5710a41

Browse files
author
Chris Yang
committed
Revert "Revert "PlatformView partial blur" (#37085)"
This reverts commit 8fcf413.
1 parent e7696f4 commit 5710a41

14 files changed

+669
-344
lines changed

flow/embedded_views.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ void MutatorsStack::PushOpacity(const int& alpha) {
100100
};
101101

102102
void MutatorsStack::PushBackdropFilter(
103-
const std::shared_ptr<const DlImageFilter>& filter) {
104-
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(filter);
103+
const std::shared_ptr<const DlImageFilter>& filter,
104+
const SkRect& filter_rect) {
105+
std::shared_ptr<Mutator> element =
106+
std::make_shared<Mutator>(filter, filter_rect);
105107
vector_.push_back(element);
106108
};
107109

flow/embedded_views.h

+45-11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,33 @@ enum MutatorType {
3232
kBackdropFilter
3333
};
3434

35+
// Represents an image filter mutation.
36+
//
37+
// Should be used for image_filter_layer and backdrop_filter_layer.
38+
// TODO(cyanglaz): Refactor this into a ImageFilterMutator class.
39+
// https://github.com/flutter/flutter/issues/108470
40+
class ImageFilterMutation {
41+
public:
42+
ImageFilterMutation(std::shared_ptr<const DlImageFilter> filter,
43+
const SkRect& filter_rect)
44+
: filter_(filter), filter_rect_(filter_rect) {}
45+
46+
const DlImageFilter& GetFilter() const { return *filter_; }
47+
const SkRect& GetFilterRect() const { return filter_rect_; }
48+
49+
bool operator==(const ImageFilterMutation& other) const {
50+
return *filter_ == *other.filter_ && filter_rect_ == other.filter_rect_;
51+
}
52+
53+
bool operator!=(const ImageFilterMutation& other) const {
54+
return !operator==(other);
55+
}
56+
57+
private:
58+
std::shared_ptr<const DlImageFilter> filter_;
59+
const SkRect filter_rect_;
60+
};
61+
3562
// Stores mutation information like clipping or kTransform.
3663
//
3764
// The `type` indicates the type of the mutation: kClipRect, kTransform and etc.
@@ -59,7 +86,7 @@ class Mutator {
5986
alpha_ = other.alpha_;
6087
break;
6188
case kBackdropFilter:
62-
filter_ = other.filter_;
89+
filter_mutation_ = other.filter_mutation_;
6390
break;
6491
default:
6592
break;
@@ -73,15 +100,20 @@ class Mutator {
73100
explicit Mutator(const SkMatrix& matrix)
74101
: type_(kTransform), matrix_(matrix) {}
75102
explicit Mutator(const int& alpha) : type_(kOpacity), alpha_(alpha) {}
76-
explicit Mutator(std::shared_ptr<const DlImageFilter> filter)
77-
: type_(kBackdropFilter), filter_(filter) {}
103+
explicit Mutator(std::shared_ptr<const DlImageFilter> filter,
104+
const SkRect& filter_rect)
105+
: type_(kBackdropFilter),
106+
filter_mutation_(
107+
std::make_shared<ImageFilterMutation>(filter, filter_rect)) {}
78108

79109
const MutatorType& GetType() const { return type_; }
80110
const SkRect& GetRect() const { return rect_; }
81111
const SkRRect& GetRRect() const { return rrect_; }
82112
const SkPath& GetPath() const { return *path_; }
83113
const SkMatrix& GetMatrix() const { return matrix_; }
84-
const DlImageFilter& GetFilter() const { return *filter_; }
114+
const ImageFilterMutation& GetFilterMutation() const {
115+
return *filter_mutation_;
116+
}
85117
const int& GetAlpha() const { return alpha_; }
86118
float GetAlphaFloat() const { return (alpha_ / 255.0); }
87119

@@ -101,7 +133,7 @@ class Mutator {
101133
case kOpacity:
102134
return alpha_ == other.alpha_;
103135
case kBackdropFilter:
104-
return *filter_ == *other.filter_;
136+
return *filter_mutation_ == *other.filter_mutation_;
105137
}
106138

107139
return false;
@@ -132,8 +164,7 @@ class Mutator {
132164
int alpha_;
133165
};
134166

135-
std::shared_ptr<const DlImageFilter> filter_;
136-
167+
std::shared_ptr<ImageFilterMutation> filter_mutation_;
137168
}; // Mutator
138169

139170
// A stack of mutators that can be applied to an embedded platform view.
@@ -154,7 +185,8 @@ class MutatorsStack {
154185
void PushClipPath(const SkPath& path);
155186
void PushTransform(const SkMatrix& matrix);
156187
void PushOpacity(const int& alpha);
157-
void PushBackdropFilter(const std::shared_ptr<const DlImageFilter>& filter);
188+
void PushBackdropFilter(const std::shared_ptr<const DlImageFilter>& filter,
189+
const SkRect& filter_rect);
158190

159191
// Removes the `Mutator` on the top of the stack
160192
// and destroys it.
@@ -249,8 +281,9 @@ class EmbeddedViewParams {
249281
const SkRect& finalBoundingRect() const { return final_bounding_rect_; }
250282

251283
// Pushes the stored DlImageFilter object to the mutators stack.
252-
void PushImageFilter(std::shared_ptr<const DlImageFilter> filter) {
253-
mutators_stack_.PushBackdropFilter(filter);
284+
void PushImageFilter(std::shared_ptr<const DlImageFilter> filter,
285+
const SkRect& filter_rect) {
286+
mutators_stack_.PushBackdropFilter(filter, filter_rect);
254287
}
255288

256289
// Whether the embedder should construct DisplayList objects to hold the
@@ -454,7 +487,8 @@ class ExternalViewEmbedder {
454487
// See also: |PushVisitedPlatformView| for pushing platform view ids to the
455488
// visited platform views list.
456489
virtual void PushFilterToVisitedPlatformViews(
457-
std::shared_ptr<const DlImageFilter> filter) {}
490+
std::shared_ptr<const DlImageFilter> filter,
491+
const SkRect& filter_rect) {}
458492

459493
private:
460494
bool used_this_frame_ = false;

flow/layers/backdrop_filter_layer.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ void BackdropFilterLayer::Preroll(PrerollContext* context,
4444
Layer::AutoPrerollSaveLayerState save =
4545
Layer::AutoPrerollSaveLayerState::Create(context, true, bool(filter_));
4646
if (context->view_embedder != nullptr) {
47-
context->view_embedder->PushFilterToVisitedPlatformViews(filter_);
47+
context->view_embedder->PushFilterToVisitedPlatformViews(
48+
filter_, context->cull_rect);
4849
}
4950
SkRect child_paint_bounds = SkRect::MakeEmpty();
5051
PrerollChildren(context, matrix, &child_paint_bounds);

flow/mutators_stack_unittests.cc

+18-12
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,19 @@ TEST(MutatorsStack, PushBackdropFilter) {
9494
const int num_of_mutators = 10;
9595
for (int i = 0; i < num_of_mutators; i++) {
9696
auto filter = std::make_shared<DlBlurImageFilter>(i, 5, DlTileMode::kClamp);
97-
stack.PushBackdropFilter(filter);
97+
stack.PushBackdropFilter(filter, SkRect::MakeXYWH(i, i, i, i));
9898
}
9999

100100
auto iter = stack.Begin();
101101
int i = 0;
102102
while (iter != stack.End()) {
103103
ASSERT_EQ(iter->get()->GetType(), MutatorType::kBackdropFilter);
104-
ASSERT_EQ(iter->get()->GetFilter().asBlur()->sigma_x(), i);
104+
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilter().asBlur()->sigma_x(),
105+
i);
106+
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i);
107+
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().x(), i);
108+
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().width(), i);
109+
ASSERT_EQ(iter->get()->GetFilterMutation().GetFilterRect().height(), i);
105110
++iter;
106111
++i;
107112
}
@@ -164,7 +169,7 @@ TEST(MutatorsStack, Equality) {
164169
int alpha = 240;
165170
stack.PushOpacity(alpha);
166171
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
167-
stack.PushBackdropFilter(filter);
172+
stack.PushBackdropFilter(filter, SkRect::MakeEmpty());
168173

169174
MutatorsStack stack_other;
170175
SkMatrix matrix_other = SkMatrix::Scale(1, 1);
@@ -179,7 +184,7 @@ TEST(MutatorsStack, Equality) {
179184
stack_other.PushOpacity(other_alpha);
180185
auto other_filter =
181186
std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
182-
stack_other.PushBackdropFilter(other_filter);
187+
stack_other.PushBackdropFilter(other_filter, SkRect::MakeEmpty());
183188

184189
ASSERT_TRUE(stack == stack_other);
185190
}
@@ -211,9 +216,9 @@ TEST(Mutator, Initialization) {
211216
ASSERT_TRUE(mutator5.GetType() == MutatorType::kOpacity);
212217

213218
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
214-
Mutator mutator6 = Mutator(filter);
219+
Mutator mutator6 = Mutator(filter, SkRect::MakeEmpty());
215220
ASSERT_TRUE(mutator6.GetType() == MutatorType::kBackdropFilter);
216-
ASSERT_TRUE(mutator6.GetFilter() == *filter);
221+
ASSERT_TRUE(mutator6.GetFilterMutation().GetFilter() == *filter);
217222
}
218223

219224
TEST(Mutator, CopyConstructor) {
@@ -244,7 +249,7 @@ TEST(Mutator, CopyConstructor) {
244249
ASSERT_TRUE(mutator5 == copy5);
245250

246251
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
247-
Mutator mutator6 = Mutator(filter);
252+
Mutator mutator6 = Mutator(filter, SkRect::MakeEmpty());
248253
Mutator copy6 = Mutator(mutator6);
249254
ASSERT_TRUE(mutator6 == copy6);
250255
}
@@ -276,9 +281,10 @@ TEST(Mutator, Equality) {
276281
Mutator other_mutator5 = Mutator(alpha);
277282
ASSERT_TRUE(mutator5 == other_mutator5);
278283

279-
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
280-
Mutator mutator6 = Mutator(filter);
281-
Mutator other_mutator6 = Mutator(filter);
284+
auto filter1 = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
285+
auto filter2 = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
286+
Mutator mutator6 = Mutator(filter1, SkRect::MakeEmpty());
287+
Mutator other_mutator6 = Mutator(filter2, SkRect::MakeEmpty());
282288
ASSERT_TRUE(mutator6 == other_mutator6);
283289
}
284290

@@ -299,8 +305,8 @@ TEST(Mutator, UnEquality) {
299305
auto filter = std::make_shared<DlBlurImageFilter>(5, 5, DlTileMode::kClamp);
300306
auto filter2 =
301307
std::make_shared<DlBlurImageFilter>(10, 10, DlTileMode::kClamp);
302-
Mutator mutator3 = Mutator(filter);
303-
Mutator other_mutator3 = Mutator(filter2);
308+
Mutator mutator3 = Mutator(filter, SkRect::MakeEmpty());
309+
Mutator other_mutator3 = Mutator(filter2, SkRect::MakeEmpty());
304310
ASSERT_TRUE(mutator3 != other_mutator3);
305311
}
306312

shell/common/shell_test_external_view_embedder.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ void ShellTestExternalViewEmbedder::PushVisitedPlatformView(int64_t view_id) {
8989

9090
// |ExternalViewEmbedder|
9191
void ShellTestExternalViewEmbedder::PushFilterToVisitedPlatformViews(
92-
std::shared_ptr<const DlImageFilter> filter) {
92+
std::shared_ptr<const DlImageFilter> filter,
93+
const SkRect& filter_rect) {
9394
for (int64_t id : visited_platform_views_) {
9495
EmbeddedViewParams params = current_composition_params_[id];
95-
params.PushImageFilter(filter);
96+
params.PushImageFilter(filter, filter_rect);
9697
current_composition_params_[id] = params;
9798
mutators_stacks_[id] = params.mutatorsStack();
9899
}

shell/common/shell_test_external_view_embedder.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
7676

7777
// |ExternalViewEmbedder|
7878
void PushFilterToVisitedPlatformViews(
79-
std::shared_ptr<const DlImageFilter> filter) override;
79+
std::shared_ptr<const DlImageFilter> filter,
80+
const SkRect& filter_rect) override;
8081

8182
// |ExternalViewEmbedder|
8283
void SubmitFrame(GrDirectContext* context,

shell/common/shell_unittests.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ TEST_F(ShellTest, PushBackdropFilterToVisitedPlatformViews) {
845845
auto filter = DlBlurImageFilter(5, 5, DlTileMode::kClamp);
846846
auto mutator = *external_view_embedder->GetStack(50).Begin();
847847
ASSERT_EQ(mutator->GetType(), MutatorType::kBackdropFilter);
848-
ASSERT_EQ(mutator->GetFilter(), filter);
848+
ASSERT_EQ(mutator->GetFilterMutation().GetFilter(), filter);
849849

850850
DestroyShell(std::move(shell));
851851
}

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

+38-14
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,11 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
321321
}
322322

323323
void FlutterPlatformViewsController::PushFilterToVisitedPlatformViews(
324-
std::shared_ptr<const DlImageFilter> filter) {
324+
std::shared_ptr<const DlImageFilter> filter,
325+
const SkRect& filter_rect) {
325326
for (int64_t id : visited_platform_views_) {
326327
EmbeddedViewParams params = current_composition_params_[id];
327-
params.PushImageFilter(filter);
328+
params.PushImageFilter(filter, filter_rect);
328329
current_composition_params_[id] = params;
329330
}
330331
}
@@ -425,7 +426,7 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
425426
CGRectGetWidth(flutter_view.bounds),
426427
CGRectGetHeight(flutter_view.bounds))] autorelease];
427428

428-
NSMutableArray* blurRadii = [[[NSMutableArray alloc] init] autorelease];
429+
NSMutableArray* blurFilters = [[[NSMutableArray alloc] init] autorelease];
429430

430431
auto iter = mutators_stack.Begin();
431432
while (iter != mutators_stack.End()) {
@@ -448,13 +449,35 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
448449
embedded_view.alpha = (*iter)->GetAlphaFloat() * embedded_view.alpha;
449450
break;
450451
case kBackdropFilter: {
451-
// We only support DlBlurImageFilter for BackdropFilter.
452-
if ((*iter)->GetFilter().asBlur() && canApplyBlurBackdrop) {
453-
// sigma_x is arbitrarily chosen as the radius value because Quartz sets
454-
// sigma_x and sigma_y equal to each other. DlBlurImageFilter's Tile Mode
455-
// is not supported in Quartz's gaussianBlur CAFilter, so it is not used
456-
// to blur the PlatformView.
457-
[blurRadii addObject:@((*iter)->GetFilter().asBlur()->sigma_x())];
452+
// Only support DlBlurImageFilter for BackdropFilter.
453+
if (!(*iter)->GetFilterMutation().GetFilter().asBlur() || !canApplyBlurBackdrop) {
454+
break;
455+
}
456+
CGRect filterRect =
457+
flutter::GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect());
458+
// `filterRect` reprents the rect that should be filtered inside the `flutter_view_`.
459+
// The `PlatformViewFilter` needs the frame inside the `clipView` that needs to be
460+
// filtered.
461+
if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
462+
break;
463+
}
464+
CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
465+
CGRect frameInClipView = [flutter_view_.get() convertRect:intersection toView:clipView];
466+
// sigma_x is arbitrarily chosen as the radius value because Quartz sets
467+
// sigma_x and sigma_y equal to each other. DlBlurImageFilter's Tile Mode
468+
// is not supported in Quartz's gaussianBlur CAFilter, so it is not used
469+
// to blur the PlatformView.
470+
CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
471+
UIVisualEffectView* visualEffectView = [[[UIVisualEffectView alloc]
472+
initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]] autorelease];
473+
PlatformViewFilter* filter =
474+
[[[PlatformViewFilter alloc] initWithFrame:frameInClipView
475+
blurRadius:blurRadius
476+
visualEffectView:visualEffectView] autorelease];
477+
if (!filter) {
478+
canApplyBlurBackdrop = NO;
479+
} else {
480+
[blurFilters addObject:filter];
458481
}
459482
break;
460483
}
@@ -463,15 +486,16 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
463486
}
464487

465488
if (canApplyBlurBackdrop) {
466-
canApplyBlurBackdrop = [clipView applyBlurBackdropFilters:blurRadii];
489+
[clipView applyBlurBackdropFilters:blurFilters];
467490
}
468491

469492
// Reverse the offset of the clipView.
470493
// The clipView's frame includes the final translate of the final transform matrix.
471-
// So we need to revese this translate so the platform view can layout at the correct offset.
494+
// Thus, this translate needs to be reversed so the platform view can layout at the correct
495+
// offset.
472496
//
473-
// Note that we don't apply this transform matrix the clippings because clippings happen on the
474-
// mask view, whose origin is always (0,0) to the flutter_view.
497+
// Note that the transforms are not applied to the clipping paths because clipping paths happen on
498+
// the mask view, whose origin is always (0,0) to the flutter_view.
475499
CATransform3D reverseTranslate =
476500
CATransform3DMakeTranslation(-clipView.frame.origin.x, -clipView.frame.origin.y, 0);
477501
embedded_view.layer.transform = CATransform3DConcat(finalTransform, reverseTranslate);

0 commit comments

Comments
 (0)