Skip to content

Commit de82380

Browse files
authored
[Impeller] implements blur styles for gradients (flutter#51264)
fixes flutter#144449 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent a1e6c06 commit de82380

File tree

4 files changed

+155
-28
lines changed

4 files changed

+155
-28
lines changed

impeller/aiks/aiks_blur_unittests.cc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,105 @@ TEST_P(AiksTest, GaussianBlurAnimatedBackdrop) {
755755
ASSERT_TRUE(OpenPlaygroundHere(callback));
756756
}
757757

758+
TEST_P(AiksTest, GaussianBlurStyleInnerGradient) {
759+
Canvas canvas;
760+
canvas.Scale(GetContentScale());
761+
762+
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
763+
764+
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
765+
Color{0.7568, 0.2627, 0.2118, 1.0}};
766+
std::vector<Scalar> stops = {0.0, 1.0};
767+
768+
Paint paint;
769+
paint.color_source = ColorSource::MakeLinearGradient(
770+
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
771+
Entity::TileMode::kMirror, {});
772+
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
773+
.style = FilterContents::BlurStyle::kInner,
774+
.sigma = Sigma(30),
775+
};
776+
canvas.DrawPath(PathBuilder()
777+
.MoveTo({200, 200})
778+
.LineTo({300, 400})
779+
.LineTo({100, 400})
780+
.Close()
781+
.TakePath(),
782+
paint);
783+
784+
// Draw another thing to make sure the clip area is reset.
785+
Paint red;
786+
red.color = Color::Red();
787+
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
788+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
789+
}
790+
791+
TEST_P(AiksTest, GaussianBlurStyleSolidGradient) {
792+
Canvas canvas;
793+
canvas.Scale(GetContentScale());
794+
795+
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
796+
797+
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
798+
Color{0.7568, 0.2627, 0.2118, 1.0}};
799+
std::vector<Scalar> stops = {0.0, 1.0};
800+
801+
Paint paint;
802+
paint.color_source = ColorSource::MakeLinearGradient(
803+
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
804+
Entity::TileMode::kMirror, {});
805+
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
806+
.style = FilterContents::BlurStyle::kSolid,
807+
.sigma = Sigma(30),
808+
};
809+
canvas.DrawPath(PathBuilder()
810+
.MoveTo({200, 200})
811+
.LineTo({300, 400})
812+
.LineTo({100, 400})
813+
.Close()
814+
.TakePath(),
815+
paint);
816+
817+
// Draw another thing to make sure the clip area is reset.
818+
Paint red;
819+
red.color = Color::Red();
820+
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
821+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
822+
}
823+
824+
TEST_P(AiksTest, GaussianBlurStyleOuterGradient) {
825+
Canvas canvas;
826+
canvas.Scale(GetContentScale());
827+
828+
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
829+
830+
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
831+
Color{0.7568, 0.2627, 0.2118, 1.0}};
832+
std::vector<Scalar> stops = {0.0, 1.0};
833+
834+
Paint paint;
835+
paint.color_source = ColorSource::MakeLinearGradient(
836+
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
837+
Entity::TileMode::kMirror, {});
838+
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
839+
.style = FilterContents::BlurStyle::kOuter,
840+
.sigma = Sigma(30),
841+
};
842+
canvas.DrawPath(PathBuilder()
843+
.MoveTo({200, 200})
844+
.LineTo({300, 400})
845+
.LineTo({100, 400})
846+
.Close()
847+
.TakePath(),
848+
paint);
849+
850+
// Draw another thing to make sure the clip area is reset.
851+
Paint red;
852+
red.color = Color::Red();
853+
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
854+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
855+
}
856+
758857
TEST_P(AiksTest, GaussianBlurStyleInner) {
759858
Canvas canvas;
760859
canvas.Scale(GetContentScale());

impeller/aiks/paint.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
170170
/// 2. Blur the mask.
171171

172172
auto blurred_mask = FilterContents::MakeGaussianBlur(
173-
FilterInput::Make(mask), sigma, sigma, Entity::TileMode::kDecal, style);
173+
FilterInput::Make(mask), sigma, sigma, Entity::TileMode::kDecal, style,
174+
color_source_contents->GetGeometry());
174175

175176
/// 3. Replace the geometry of the original color source with a rectangle that
176177
/// covers the full region of the blurred mask. Note that geometry is in

impeller/entity/contents/filters/gaussian_blur_filter_contents.cc

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -210,30 +210,39 @@ Entity ApplyClippedBlurStyle(Entity::ClipOperation clip_operation,
210210
const Snapshot& input_snapshot,
211211
Entity blur_entity,
212212
const std::shared_ptr<Geometry>& geometry) {
213-
auto shared_blur_entity = std::make_shared<Entity>(std::move(blur_entity));
214-
shared_blur_entity->SetNewClipDepth(entity.GetNewClipDepth());
215-
auto clipper = std::make_unique<ClipContents>();
216-
clipper->SetClipOperation(clip_operation);
217-
clipper->SetGeometry(geometry);
213+
auto clip_contents = std::make_shared<ClipContents>();
214+
clip_contents->SetClipOperation(clip_operation);
215+
clip_contents->SetGeometry(geometry);
216+
Entity clipper;
217+
clipper.SetContents(clip_contents);
218218
auto restore = std::make_unique<ClipRestoreContents>();
219-
Entity result;
220-
result.SetTransform(entity.GetTransform());
221-
result.SetContents(Contents::MakeAnonymous(
222-
fml::MakeCopyable([shared_blur_entity, clipper = std::move(clipper),
223-
restore = std::move(restore)](
224-
const ContentContext& renderer,
225-
const Entity& entity, RenderPass& pass) mutable {
219+
Matrix entity_transform = entity.GetTransform();
220+
Matrix blur_transform = blur_entity.GetTransform();
221+
auto renderer = fml::MakeCopyable(
222+
[blur_entity = blur_entity.Clone(), clipper = std::move(clipper),
223+
restore = std::move(restore), entity_transform,
224+
blur_transform](const ContentContext& renderer, const Entity& entity,
225+
RenderPass& pass) mutable {
226226
bool result = true;
227-
result = clipper->Render(renderer, entity, pass) && result;
228-
result = shared_blur_entity->Render(renderer, pass) && result;
227+
clipper.SetNewClipDepth(entity.GetNewClipDepth());
228+
clipper.SetTransform(entity.GetTransform() * entity_transform);
229+
result = clipper.Render(renderer, pass) && result;
230+
blur_entity.SetNewClipDepth(entity.GetNewClipDepth());
231+
blur_entity.SetTransform(entity.GetTransform() * blur_transform);
232+
result = blur_entity.Render(renderer, pass) && result;
229233
if constexpr (!ContentContext::kEnableStencilThenCover) {
230234
result = restore->Render(renderer, entity, pass) && result;
231235
}
232236
return result;
233-
}),
234-
[shared_blur_entity](const Entity& entity) {
235-
return shared_blur_entity->GetCoverage();
236-
}));
237+
});
238+
auto coverage =
239+
fml::MakeCopyable([blur_entity = std::move(blur_entity),
240+
blur_transform](const Entity& entity) mutable {
241+
blur_entity.SetTransform(entity.GetTransform() * blur_transform);
242+
return blur_entity.GetCoverage();
243+
});
244+
Entity result;
245+
result.SetContents(Contents::MakeAnonymous(renderer, coverage));
237246
return result;
238247
}
239248

@@ -256,24 +265,33 @@ Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
256265
input, input_snapshot,
257266
std::move(blur_entity), geometry);
258267
case FilterContents::BlurStyle::kSolid: {
259-
Entity blurred = ApplyClippedBlurStyle(Entity::ClipOperation::kIntersect,
260-
entity, input, input_snapshot,
261-
std::move(blur_entity), geometry);
262268
Entity snapshot_entity = Entity::FromSnapshot(
263269
input_snapshot, entity.GetBlendMode(), entity.GetClipDepth());
264270
Entity result;
265-
std::optional<Rect> coverage = blurred.GetCoverage();
271+
Matrix blurred_transform = blur_entity.GetTransform();
272+
Matrix snapshot_transform = snapshot_entity.GetTransform();
266273
result.SetContents(Contents::MakeAnonymous(
267-
fml::MakeCopyable([blurred = std::move(blurred),
274+
fml::MakeCopyable([blur_entity = blur_entity.Clone(),
275+
blurred_transform, snapshot_transform,
268276
snapshot_entity = std::move(snapshot_entity)](
269277
const ContentContext& renderer,
270278
const Entity& entity,
271279
RenderPass& pass) mutable {
272-
return blurred.Render(renderer, pass) &&
273-
snapshot_entity.Render(renderer, pass);
280+
bool result = true;
281+
blur_entity.SetNewClipDepth(entity.GetNewClipDepth());
282+
blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
283+
result = result && blur_entity.Render(renderer, pass);
284+
snapshot_entity.SetTransform(entity.GetTransform() *
285+
snapshot_transform);
286+
snapshot_entity.SetNewClipDepth(entity.GetNewClipDepth());
287+
result = result && snapshot_entity.Render(renderer, pass);
288+
return result;
274289
}),
275-
fml::MakeCopyable(
276-
[coverage](const Entity& entity) { return coverage; })));
290+
fml::MakeCopyable([blur_entity = blur_entity.Clone(),
291+
blurred_transform](const Entity& entity) mutable {
292+
blur_entity.SetTransform(entity.GetTransform() * blurred_transform);
293+
return blur_entity.GetCoverage();
294+
})));
277295
return result;
278296
}
279297
}

testing/impeller_golden_tests_output.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,21 @@ impeller_Play_AiksTest_GaussianBlurRotatedAndClipped_Vulkan.png
488488
impeller_Play_AiksTest_GaussianBlurScaledAndClipped_Metal.png
489489
impeller_Play_AiksTest_GaussianBlurScaledAndClipped_OpenGLES.png
490490
impeller_Play_AiksTest_GaussianBlurScaledAndClipped_Vulkan.png
491+
impeller_Play_AiksTest_GaussianBlurStyleInnerGradient_Metal.png
492+
impeller_Play_AiksTest_GaussianBlurStyleInnerGradient_OpenGLES.png
493+
impeller_Play_AiksTest_GaussianBlurStyleInnerGradient_Vulkan.png
491494
impeller_Play_AiksTest_GaussianBlurStyleInner_Metal.png
492495
impeller_Play_AiksTest_GaussianBlurStyleInner_OpenGLES.png
493496
impeller_Play_AiksTest_GaussianBlurStyleInner_Vulkan.png
497+
impeller_Play_AiksTest_GaussianBlurStyleOuterGradient_Metal.png
498+
impeller_Play_AiksTest_GaussianBlurStyleOuterGradient_OpenGLES.png
499+
impeller_Play_AiksTest_GaussianBlurStyleOuterGradient_Vulkan.png
494500
impeller_Play_AiksTest_GaussianBlurStyleOuter_Metal.png
495501
impeller_Play_AiksTest_GaussianBlurStyleOuter_OpenGLES.png
496502
impeller_Play_AiksTest_GaussianBlurStyleOuter_Vulkan.png
503+
impeller_Play_AiksTest_GaussianBlurStyleSolidGradient_Metal.png
504+
impeller_Play_AiksTest_GaussianBlurStyleSolidGradient_OpenGLES.png
505+
impeller_Play_AiksTest_GaussianBlurStyleSolidGradient_Vulkan.png
497506
impeller_Play_AiksTest_GaussianBlurStyleSolid_Metal.png
498507
impeller_Play_AiksTest_GaussianBlurStyleSolid_OpenGLES.png
499508
impeller_Play_AiksTest_GaussianBlurStyleSolid_Vulkan.png

0 commit comments

Comments
 (0)