Skip to content

Commit

Permalink
Implement mask blur in display list dispatcher (flutter#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored Apr 20, 2022
1 parent 191d3bf commit 03e9a79
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 6 deletions.
6 changes: 3 additions & 3 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void Canvas::DrawPath(Path path, Paint paint) {
entity.SetPath(std::move(path));
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);
entity.SetContents(paint.CreateContentsForEntity());
entity.SetContents(paint.WithFilters(paint.CreateContentsForEntity()));

GetCurrentPass().AddEntity(std::move(entity));
}
Expand Down Expand Up @@ -242,7 +242,7 @@ void Canvas::DrawImageRect(std::shared_ptr<Image> image,
entity.SetPath(PathBuilder{}.AddRect(dest).TakePath());
entity.SetBlendMode(paint.blend_mode);
entity.SetStencilDepth(GetStencilDepth());
entity.SetContents(contents);
entity.SetContents(paint.WithFilters(contents, false));
entity.SetTransformation(GetCurrentTransformation());

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

GetCurrentPass().AddEntity(std::move(entity));
}
Expand Down
20 changes: 20 additions & 0 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,24 @@ std::shared_ptr<Contents> Paint::CreateContentsForEntity() const {
return nullptr;
}

std::shared_ptr<Contents> Paint::WithFilters(
std::shared_ptr<Contents> input,
std::optional<bool> is_solid_color) const {
bool is_solid_color_val = is_solid_color.value_or(!contents);

if (mask_blur.has_value()) {
if (is_solid_color_val) {
input = FilterContents::MakeGaussianBlur(
FilterInput::Make(input), mask_blur->sigma, mask_blur->sigma,
mask_blur->blur_style);
} else {
input = FilterContents::MakeBorderMaskBlur(
FilterInput::Make(input), mask_blur->sigma, mask_blur->sigma,
mask_blur->blur_style);
}
}

return input;
}

} // namespace impeller
22 changes: 22 additions & 0 deletions impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@

#include "flutter/fml/macros.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/color.h"

namespace impeller {

struct MaskBlur {
FilterContents::BlurStyle blur_style;
FilterContents::Sigma sigma;
};

struct Paint {
enum class Style {
kFill,
Expand All @@ -27,9 +33,25 @@ struct Paint {
Scalar stroke_miter = 4.0;
Style style = Style::kFill;
Entity::BlendMode blend_mode = Entity::BlendMode::kSourceOver;
std::optional<MaskBlur> mask_blur;
std::shared_ptr<Contents> contents;

std::shared_ptr<Contents> CreateContentsForEntity() const;

/// @brief Wrap this paint's configured filters to the given contents.
/// @param[in] input The contents to wrap with paint's filters.
/// @param[in] is_solid_color Affects mask blurring behavior. If false, use
/// the image border for mask blurring. If true,
/// do a Gaussian blur to achieve the mask
/// blurring effect for arbitrary paths. If unset,
/// use the current paint configuration to infer
/// the result.
/// @return The filter-wrapped contents. If there are no filters that need
/// to be wrapped for the current paint configuration, the
/// original contents is returned.
std::shared_ptr<Contents> WithFilters(
std::shared_ptr<Contents> input,
std::optional<bool> is_solid_color = std::nullopt) const;
};

} // namespace impeller
23 changes: 21 additions & 2 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <optional>

#include "flutter/fml/trace_event.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/linear_gradient_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/entity.h"
Expand Down Expand Up @@ -253,15 +254,33 @@ void DisplayListDispatcher::setPathEffect(sk_sp<SkPathEffect> effect) {
UNIMPLEMENTED;
}

static FilterContents::BlurStyle ToBlurStyle(SkBlurStyle blur_style) {
switch (blur_style) {
case kNormal_SkBlurStyle:
return FilterContents::BlurStyle::kNormal;
case kSolid_SkBlurStyle:
return FilterContents::BlurStyle::kSolid;
case kOuter_SkBlurStyle:
return FilterContents::BlurStyle::kOuter;
case kInner_SkBlurStyle:
return FilterContents::BlurStyle::kInner;
}
}

// |flutter::Dispatcher|
void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
// Needs https://github.com/flutter/flutter/issues/95434
if (filter == nullptr) {
// Reset everything
paint_.mask_blur = std::nullopt;
return;
}
switch (filter->type()) {
case flutter::DlMaskFilterType::kBlur:
case flutter::DlMaskFilterType::kBlur: {
auto blur = filter->asBlur();
paint_.mask_blur = {.blur_style = ToBlurStyle(blur->style()),
.sigma = FilterContents::Sigma(blur->sigma())};
break;
}
case flutter::DlMaskFilterType::kUnknown:
UNIMPLEMENTED;
break;
Expand Down
33 changes: 33 additions & 0 deletions impeller/display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "third_party/skia/include/core/SkPathBuilder.h"

#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_mask_filter.h"
#include "flutter/display_list/types.h"
#include "flutter/testing/testing.h"
#include "impeller/display_list/display_list_image_impeller.h"
#include "impeller/display_list/display_list_playground.h"
Expand Down Expand Up @@ -174,5 +176,36 @@ TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

TEST_F(DisplayListTest, CanDrawWithMaskBlur) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;

// Mask blurred image.
{
auto filter = flutter::DlBlurMaskFilter(kNormal_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
SkSamplingOptions{}, true);
}

// Mask blurred filled path.
{
builder.setColor(SK_ColorYELLOW);
auto filter = flutter::DlBlurMaskFilter(kOuter_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true);
}

// Mask blurred text.
{
auto filter = flutter::DlBlurMaskFilter(kSolid_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawTextBlob(
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170);
}

ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

} // namespace testing
} // namespace impeller
2 changes: 1 addition & 1 deletion impeller/entity/contents/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
RenderPass& pass) -> bool {
Entity sub_entity;
sub_entity.SetPath(entity.GetPath());
sub_entity.SetBlendMode(Entity::BlendMode::kSource);
sub_entity.SetBlendMode(Entity::BlendMode::kSourceOver);
sub_entity.SetTransformation(
Matrix::MakeTranslation(Vector3(-bounds->origin)) *
entity.GetTransformation());
Expand Down

0 comments on commit 03e9a79

Please sign in to comment.