Skip to content

Commit f86c9b7

Browse files
bderodnfield
authored andcommitted
Implement mask blur in display list dispatcher (flutter#142)
1 parent 79f2e86 commit f86c9b7

File tree

6 files changed

+100
-6
lines changed

6 files changed

+100
-6
lines changed

impeller/aiks/canvas.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void Canvas::DrawPath(Path path, Paint paint) {
114114
entity.SetPath(std::move(path));
115115
entity.SetStencilDepth(GetStencilDepth());
116116
entity.SetBlendMode(paint.blend_mode);
117-
entity.SetContents(paint.CreateContentsForEntity());
117+
entity.SetContents(paint.WithFilters(paint.CreateContentsForEntity()));
118118

119119
GetCurrentPass().AddEntity(std::move(entity));
120120
}
@@ -242,7 +242,7 @@ void Canvas::DrawImageRect(std::shared_ptr<Image> image,
242242
entity.SetPath(PathBuilder{}.AddRect(dest).TakePath());
243243
entity.SetBlendMode(paint.blend_mode);
244244
entity.SetStencilDepth(GetStencilDepth());
245-
entity.SetContents(contents);
245+
entity.SetContents(paint.WithFilters(contents, false));
246246
entity.SetTransformation(GetCurrentTransformation());
247247

248248
GetCurrentPass().AddEntity(std::move(entity));
@@ -296,7 +296,7 @@ void Canvas::DrawTextFrame(TextFrame text_frame, Point position, Paint paint) {
296296
entity.SetPath({});
297297
entity.SetStencilDepth(GetStencilDepth());
298298
entity.SetBlendMode(paint.blend_mode);
299-
entity.SetContents(std::move(text_contents));
299+
entity.SetContents(paint.WithFilters(std::move(text_contents), true));
300300

301301
GetCurrentPass().AddEntity(std::move(entity));
302302
}

impeller/aiks/paint.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,24 @@ std::shared_ptr<Contents> Paint::CreateContentsForEntity() const {
3333
return nullptr;
3434
}
3535

36+
std::shared_ptr<Contents> Paint::WithFilters(
37+
std::shared_ptr<Contents> input,
38+
std::optional<bool> is_solid_color) const {
39+
bool is_solid_color_val = is_solid_color.value_or(!contents);
40+
41+
if (mask_blur.has_value()) {
42+
if (is_solid_color_val) {
43+
input = FilterContents::MakeGaussianBlur(
44+
FilterInput::Make(input), mask_blur->sigma, mask_blur->sigma,
45+
mask_blur->blur_style);
46+
} else {
47+
input = FilterContents::MakeBorderMaskBlur(
48+
FilterInput::Make(input), mask_blur->sigma, mask_blur->sigma,
49+
mask_blur->blur_style);
50+
}
51+
}
52+
53+
return input;
54+
}
55+
3656
} // namespace impeller

impeller/aiks/paint.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88

99
#include "flutter/fml/macros.h"
1010
#include "impeller/entity/contents/contents.h"
11+
#include "impeller/entity/contents/filters/filter_contents.h"
1112
#include "impeller/entity/contents/solid_stroke_contents.h"
1213
#include "impeller/entity/entity.h"
1314
#include "impeller/geometry/color.h"
1415

1516
namespace impeller {
1617

18+
struct MaskBlur {
19+
FilterContents::BlurStyle blur_style;
20+
FilterContents::Sigma sigma;
21+
};
22+
1723
struct Paint {
1824
enum class Style {
1925
kFill,
@@ -27,9 +33,25 @@ struct Paint {
2733
Scalar stroke_miter = 4.0;
2834
Style style = Style::kFill;
2935
Entity::BlendMode blend_mode = Entity::BlendMode::kSourceOver;
36+
std::optional<MaskBlur> mask_blur;
3037
std::shared_ptr<Contents> contents;
3138

3239
std::shared_ptr<Contents> CreateContentsForEntity() const;
40+
41+
/// @brief Wrap this paint's configured filters to the given contents.
42+
/// @param[in] input The contents to wrap with paint's filters.
43+
/// @param[in] is_solid_color Affects mask blurring behavior. If false, use
44+
/// the image border for mask blurring. If true,
45+
/// do a Gaussian blur to achieve the mask
46+
/// blurring effect for arbitrary paths. If unset,
47+
/// use the current paint configuration to infer
48+
/// the result.
49+
/// @return The filter-wrapped contents. If there are no filters that need
50+
/// to be wrapped for the current paint configuration, the
51+
/// original contents is returned.
52+
std::shared_ptr<Contents> WithFilters(
53+
std::shared_ptr<Contents> input,
54+
std::optional<bool> is_solid_color = std::nullopt) const;
3355
};
3456

3557
} // namespace impeller

impeller/display_list/display_list_dispatcher.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <optional>
88

99
#include "flutter/fml/trace_event.h"
10+
#include "impeller/entity/contents/filters/filter_contents.h"
1011
#include "impeller/entity/contents/linear_gradient_contents.h"
1112
#include "impeller/entity/contents/solid_stroke_contents.h"
1213
#include "impeller/entity/entity.h"
@@ -253,15 +254,33 @@ void DisplayListDispatcher::setPathEffect(sk_sp<SkPathEffect> effect) {
253254
UNIMPLEMENTED;
254255
}
255256

257+
static FilterContents::BlurStyle ToBlurStyle(SkBlurStyle blur_style) {
258+
switch (blur_style) {
259+
case kNormal_SkBlurStyle:
260+
return FilterContents::BlurStyle::kNormal;
261+
case kSolid_SkBlurStyle:
262+
return FilterContents::BlurStyle::kSolid;
263+
case kOuter_SkBlurStyle:
264+
return FilterContents::BlurStyle::kOuter;
265+
case kInner_SkBlurStyle:
266+
return FilterContents::BlurStyle::kInner;
267+
}
268+
}
269+
256270
// |flutter::Dispatcher|
257271
void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
258272
// Needs https://github.com/flutter/flutter/issues/95434
259273
if (filter == nullptr) {
260-
// Reset everything
274+
paint_.mask_blur = std::nullopt;
261275
return;
262276
}
263277
switch (filter->type()) {
264-
case flutter::DlMaskFilterType::kBlur:
278+
case flutter::DlMaskFilterType::kBlur: {
279+
auto blur = filter->asBlur();
280+
paint_.mask_blur = {.blur_style = ToBlurStyle(blur->style()),
281+
.sigma = FilterContents::Sigma(blur->sigma())};
282+
break;
283+
}
265284
case flutter::DlMaskFilterType::kUnknown:
266285
UNIMPLEMENTED;
267286
break;

impeller/display_list/display_list_unittests.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "third_party/skia/include/core/SkPathBuilder.h"
99

1010
#include "flutter/display_list/display_list_builder.h"
11+
#include "flutter/display_list/display_list_mask_filter.h"
12+
#include "flutter/display_list/types.h"
1113
#include "flutter/testing/testing.h"
1214
#include "impeller/display_list/display_list_image_impeller.h"
1315
#include "impeller/display_list/display_list_playground.h"
@@ -174,5 +176,36 @@ TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
174176
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
175177
}
176178

179+
TEST_F(DisplayListTest, CanDrawWithMaskBlur) {
180+
auto texture = CreateTextureForFixture("embarcadero.jpg");
181+
flutter::DisplayListBuilder builder;
182+
183+
// Mask blurred image.
184+
{
185+
auto filter = flutter::DlBlurMaskFilter(kNormal_SkBlurStyle, 10.0f);
186+
builder.setMaskFilter(&filter);
187+
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
188+
SkSamplingOptions{}, true);
189+
}
190+
191+
// Mask blurred filled path.
192+
{
193+
builder.setColor(SK_ColorYELLOW);
194+
auto filter = flutter::DlBlurMaskFilter(kOuter_SkBlurStyle, 10.0f);
195+
builder.setMaskFilter(&filter);
196+
builder.drawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true);
197+
}
198+
199+
// Mask blurred text.
200+
{
201+
auto filter = flutter::DlBlurMaskFilter(kSolid_SkBlurStyle, 10.0f);
202+
builder.setMaskFilter(&filter);
203+
builder.drawTextBlob(
204+
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170);
205+
}
206+
207+
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
208+
}
209+
177210
} // namespace testing
178211
} // namespace impeller

impeller/entity/contents/contents.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
4747
RenderPass& pass) -> bool {
4848
Entity sub_entity;
4949
sub_entity.SetPath(entity.GetPath());
50-
sub_entity.SetBlendMode(Entity::BlendMode::kSource);
50+
sub_entity.SetBlendMode(Entity::BlendMode::kSourceOver);
5151
sub_entity.SetTransformation(
5252
Matrix::MakeTranslation(Vector3(-bounds->origin)) *
5353
entity.GetTransformation());

0 commit comments

Comments
 (0)