Skip to content

Commit 633d659

Browse files
[Impeller] Fix the source rectangle used when rendering an AtlasContents with the strict mode for nine-patch images (flutter#177860)
* Convert the source rectangle to texture coordinates and shrink it to adjust for linear filtering * Pass the coordinates of the rectangle in the order expected by the Porter-Duff shader Fixes flutter#176544
1 parent bf49578 commit 633d659

File tree

5 files changed

+25
-5
lines changed

5 files changed

+25
-5
lines changed

engine/src/flutter/impeller/display_list/dl_unittests.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,22 @@ TEST_P(DisplayListTest, NinePatchImagePrecision) {
809809
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
810810
}
811811

812+
TEST_P(DisplayListTest, NinePatchImageColorFilter) {
813+
auto texture = CreateTextureForFixture("nine_patch2.png");
814+
815+
auto filter = flutter::DlColorFilter::MakeBlend(flutter::DlColor::kGreen(),
816+
flutter::DlBlendMode::kSrcIn);
817+
flutter::DlPaint paint;
818+
paint.setColorFilter(filter);
819+
820+
flutter::DisplayListBuilder builder;
821+
builder.DrawImageNine(DlImageImpeller::Make(texture),
822+
DlIRect::MakeXYWH(10, 10, 1, 1),
823+
DlRect::MakeXYWH(0, 0, 200, 100),
824+
flutter::DlFilterMode::kNearest, &paint);
825+
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
826+
}
827+
812828
TEST_P(DisplayListTest, CanDrawPoints) {
813829
flutter::DisplayListBuilder builder;
814830
DlPoint points[7] = {

engine/src/flutter/impeller/entity/contents/atlas_contents.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ bool DrawImageRectAtlasGeometry::ShouldInvertBlendMode() const {
127127

128128
std::optional<Rect> DrawImageRectAtlasGeometry::GetStrictSrcRect() const {
129129
if (use_strict_src_rect_) {
130-
return source_;
130+
// For a strict source rect, shrink the texture coordinate range by half a
131+
// texel to ensure that linear filtering does not sample anything outside
132+
// the source rect bounds.
133+
return Rect::MakeSize(texture_->GetSize()).Project(source_.Expand(-0.5));
131134
}
132135
return std::nullopt;
133136
}
@@ -230,8 +233,8 @@ bool AtlasContents::Render(const ContentContext& renderer,
230233
if (auto rect = geometry_->GetStrictSrcRect(); rect.has_value()) {
231234
Rect src_rect = rect.value();
232235
frag_info.source_rect =
233-
Vector4(src_rect.GetX(), src_rect.GetY(), src_rect.GetBottom(),
234-
src_rect.GetRight());
236+
Vector4(src_rect.GetX(), src_rect.GetY(), src_rect.GetRight(),
237+
src_rect.GetBottom());
235238
frag_info.use_strict_source_rect = 1.0;
236239
} else {
237240
frag_info.use_strict_source_rect = 0.0;

engine/src/flutter/impeller/entity/contents/atlas_contents.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class AtlasGeometry {
4040

4141
virtual bool ShouldInvertBlendMode() const { return true; }
4242

43-
/// @brief The source rect of the draw if a strict source rect should
44-
/// be applied, or nullopt.
43+
/// @brief The source rect of the draw in texture coordinates if a strict
44+
/// source rect should be applied, or nullopt.
4545
///
4646
/// See also `Canvas::AttemptColorFilterOptimization`
4747
virtual std::optional<Rect> GetStrictSrcRect() const { return std::nullopt; }

engine/src/flutter/impeller/fixtures/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ test_fixtures("file_fixtures") {
130130
"monkey.png",
131131
"multiple_stages.hlsl",
132132
"nine_patch_corners.png",
133+
"nine_patch2.png",
133134
"resources_limit.vert",
134135
"sample.comp",
135136
"sample.frag",
263 Bytes
Loading

0 commit comments

Comments
 (0)