Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
../../../flutter/impeller/display_list/aiks_dl_gradient_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_opacity_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_path_unittests.cc
../../../flutter/impeller/display_list/dl_golden_blur_unittests.cc
../../../flutter/impeller/display_list/dl_golden_unittests.cc
../../../flutter/impeller/display_list/dl_golden_unittests.h
../../../flutter/impeller/display_list/dl_unittests.cc
Expand Down
4 changes: 2 additions & 2 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -909,8 +909,8 @@ void Canvas::DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
// needs to be reworked in order to interact correctly with
// mask filters.
// https://github.com/flutter/flutter/issues/133297
entity.SetContents(
paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
entity.SetContents(paint.WithFilters(paint.WithMaskBlur(
std::move(text_contents), true, GetCurrentTransform())));

AddRenderEntityToCurrentPass(std::move(entity));
}
Expand Down
4 changes: 2 additions & 2 deletions impeller/aiks/experimental_canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ void ExperimentalCanvas::DrawTextFrame(
// needs to be reworked in order to interact correctly with
// mask filters.
// https://github.com/flutter/flutter/issues/133297
entity.SetContents(
paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
entity.SetContents(paint.WithFilters(paint.WithMaskBlur(
std::move(text_contents), true, GetCurrentTransform())));

AddRenderEntityToCurrentPass(std::move(entity), false);
}
Expand Down
18 changes: 13 additions & 5 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
}

std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
bool is_solid_color) const {
bool is_solid_color,
const Matrix& ctm) const {
if (mask_blur_descriptor.has_value()) {
input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
is_solid_color);
is_solid_color, ctm);
}
return input;
}
Expand Down Expand Up @@ -203,12 +204,19 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(

std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
const FilterInput::Ref& input,
bool is_solid_color) const {
bool is_solid_color,
const Matrix& ctm) const {
Vector2 blur_sigma(sigma.sigma, sigma.sigma);
if (!respect_ctm) {
blur_sigma /= Vector2(ctm.GetBasisX().Length(), ctm.GetBasisY().Length());
}
if (is_solid_color) {
return FilterContents::MakeGaussianBlur(input, sigma, sigma,
return FilterContents::MakeGaussianBlur(input, Sigma(blur_sigma.x),
Sigma(blur_sigma.y),
Entity::TileMode::kDecal, style);
}
return FilterContents::MakeBorderMaskBlur(input, sigma, sigma, style);
return FilterContents::MakeBorderMaskBlur(input, Sigma(blur_sigma.x),
Sigma(blur_sigma.y), style);
}

std::shared_ptr<ColorFilter> Paint::GetColorFilter() const {
Expand Down
9 changes: 7 additions & 2 deletions impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct Paint {
struct MaskBlurDescriptor {
FilterContents::BlurStyle style;
Sigma sigma;
/// Text mask blurs need to not apply the CTM to the blur kernel.
/// See: https://github.com/flutter/flutter/issues/115112
bool respect_ctm = true;

std::shared_ptr<FilterContents> CreateMaskBlur(
std::shared_ptr<ColorSourceContents> color_source_contents,
Expand All @@ -58,7 +61,8 @@ struct Paint {

std::shared_ptr<FilterContents> CreateMaskBlur(
const FilterInput::Ref& input,
bool is_solid_color) const;
bool is_solid_color,
const Matrix& ctm) const;
};

Color color = Color::Black();
Expand Down Expand Up @@ -104,7 +108,8 @@ struct Paint {
bool HasColorFilter() const;

std::shared_ptr<Contents> WithMaskBlur(std::shared_ptr<Contents> input,
bool is_solid_color) const;
bool is_solid_color,
const Matrix& ctm) const;

std::shared_ptr<FilterContents> WithImageFilter(
const FilterInput::Variant& input,
Expand Down
1 change: 1 addition & 0 deletions impeller/display_list/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ template("display_list_unittests_component") {
"aiks_dl_gradient_unittests.cc",
"aiks_dl_opacity_unittests.cc",
"aiks_dl_path_unittests.cc",
"dl_golden_blur_unittests.cc",
"dl_golden_unittests.cc",
"dl_playground.cc",
"dl_playground.h",
Expand Down
1 change: 1 addition & 0 deletions impeller/display_list/dl_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ void DlDispatcherBase::setMaskFilter(const flutter::DlMaskFilter* filter) {
paint_.mask_blur_descriptor = {
.style = ToBlurStyle(blur->style()),
.sigma = Sigma(blur->sigma()),
.respect_ctm = blur->respectCTM(),
};
break;
}
Expand Down
114 changes: 114 additions & 0 deletions impeller/display_list/dl_golden_blur_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/display_list/dl_golden_unittests.h"

#include "flutter/display_list/dl_builder.h"
#include "flutter/display_list/effects/dl_mask_filter.h"
#include "flutter/testing/testing.h"
#include "gtest/gtest.h"
#include "impeller/typographer/backends/skia/text_frame_skia.h"
#include "txt/platform.h"

namespace flutter {
namespace testing {

using impeller::Font;

namespace {
struct TextRenderOptions {
bool stroke = false;
SkScalar font_size = 50;
DlColor color = DlColor::kYellow();
std::shared_ptr<DlMaskFilter> mask_filter;
};

bool RenderTextInCanvasSkia(DlCanvas* canvas,
const std::string& text,
const std::string_view& font_fixture,
SkPoint position,
const TextRenderOptions& options = {}) {
auto c_font_fixture = std::string(font_fixture);
auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
if (!mapping) {
return false;
}
sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
if (!blob) {
return false;
}

auto frame = impeller::MakeTextFrameFromTextBlobSkia(blob);

DlPaint text_paint;
text_paint.setColor(options.color);
text_paint.setMaskFilter(options.mask_filter);
// text_paint.mask_blur_descriptor = options.mask_blur_descriptor;
// text_paint.stroke_width = 1;
// text_paint.style =
// options.stroke ? Paint::Style::kStroke : Paint::Style::kFill;
canvas->DrawTextFrame(frame, position.x(), position.y(), text_paint);
return true;
}

} // namespace

TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM) {
impeller::Point content_scale = GetContentScale();
auto draw = [&](DlCanvas* canvas,
const std::vector<std::unique_ptr<DlImage>>& images) {
canvas->DrawColor(DlColor(0xff111111));
canvas->Scale(content_scale.x, content_scale.y);
canvas->Scale(2, 2);
TextRenderOptions options;
options.mask_filter =
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, /*sigma=*/10,
/*respect_ctm=*/true);
ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
"Roboto-Regular.ttf",
SkPoint::Make(101, 101), options));
options.mask_filter = nullptr;
options.color = DlColor::kRed();
ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
"Roboto-Regular.ttf",
SkPoint::Make(100, 100), options));
};

DisplayListBuilder builder;
draw(&builder, /*images=*/{});

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

TEST_P(DlGoldenTest, TextBlurMaskFilterDisrespectCTM) {
impeller::Point content_scale = GetContentScale();
auto draw = [&](DlCanvas* canvas,
const std::vector<std::unique_ptr<DlImage>>& images) {
canvas->DrawColor(DlColor(0xff111111));
canvas->Scale(content_scale.x, content_scale.y);
canvas->Scale(2, 2);
TextRenderOptions options;
options.mask_filter =
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, /*sigma=*/10,
/*respect_ctm=*/false);
ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
"Roboto-Regular.ttf",
SkPoint::Make(101, 101), options));
options.mask_filter = nullptr;
options.color = DlColor::kRed();
ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
"Roboto-Regular.ttf",
SkPoint::Make(100, 100), options));
};

DisplayListBuilder builder;
draw(&builder, /*images=*/{});

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

} // namespace testing
} // namespace flutter
Loading