Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 041ae35

Browse files
[Impeller] Add an API for sampling strictly within the bounds of the source rect in DrawImageRect (#49696)
Fixes flutter/flutter#140393
1 parent 602c354 commit 041ae35

18 files changed

+329
-23
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5261,6 +5261,7 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag +
52615261
ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.frag + ../../../flutter/LICENSE
52625262
ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.vert + ../../../flutter/LICENSE
52635263
ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill_external.frag + ../../../flutter/LICENSE
5264+
ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag + ../../../flutter/LICENSE
52645265
ORIGIN: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.frag + ../../../flutter/LICENSE
52655266
ORIGIN: ../../../flutter/impeller/entity/shaders/tiled_texture_fill_external.frag + ../../../flutter/LICENSE
52665267
ORIGIN: ../../../flutter/impeller/entity/shaders/vertices.frag + ../../../flutter/LICENSE
@@ -8090,6 +8091,7 @@ FILE: ../../../flutter/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag
80908091
FILE: ../../../flutter/impeller/entity/shaders/texture_fill.frag
80918092
FILE: ../../../flutter/impeller/entity/shaders/texture_fill.vert
80928093
FILE: ../../../flutter/impeller/entity/shaders/texture_fill_external.frag
8094+
FILE: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag
80938095
FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.frag
80948096
FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill_external.frag
80958097
FILE: ../../../flutter/impeller/entity/shaders/vertices.frag

impeller/aiks/canvas.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,8 @@ void Canvas::DrawImageRect(const std::shared_ptr<Image>& image,
662662
Rect source,
663663
Rect dest,
664664
const Paint& paint,
665-
SamplerDescriptor sampler) {
665+
SamplerDescriptor sampler,
666+
SourceRectConstraint src_rect_constraint) {
666667
if (!image || source.IsEmpty() || dest.IsEmpty()) {
667668
return;
668669
}
@@ -676,6 +677,8 @@ void Canvas::DrawImageRect(const std::shared_ptr<Image>& image,
676677
auto contents = TextureContents::MakeRect(dest);
677678
contents->SetTexture(image->GetTexture());
678679
contents->SetSourceRect(source);
680+
contents->SetStrictSourceRect(src_rect_constraint ==
681+
SourceRectConstraint::kStrict);
679682
contents->SetSamplerDescriptor(std::move(sampler));
680683
contents->SetOpacity(paint.color.alpha);
681684
contents->SetDeferApplyingOpacity(paint.HasColorFilter());

impeller/aiks/canvas.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ enum class PointStyle {
4545
kSquare,
4646
};
4747

48+
/// Controls the behavior of the source rectangle given to DrawImageRect.
49+
enum class SourceRectConstraint {
50+
/// @brief Faster, but may sample outside the bounds of the source rectangle.
51+
kFast,
52+
53+
/// @brief Sample only within the source rectangle. May be slower.
54+
kStrict,
55+
};
56+
4857
class Canvas {
4958
public:
5059
struct DebugOptions {
@@ -123,11 +132,13 @@ class Canvas {
123132
const Paint& paint,
124133
SamplerDescriptor sampler = {});
125134

126-
void DrawImageRect(const std::shared_ptr<Image>& image,
127-
Rect source,
128-
Rect dest,
129-
const Paint& paint,
130-
SamplerDescriptor sampler = {});
135+
void DrawImageRect(
136+
const std::shared_ptr<Image>& image,
137+
Rect source,
138+
Rect dest,
139+
const Paint& paint,
140+
SamplerDescriptor sampler = {},
141+
SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast);
131142

132143
void ClipPath(
133144
Path path,

impeller/aiks/canvas_recorder.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,16 @@ class CanvasRecorder {
237237
offset, paint, sampler);
238238
}
239239

240-
void DrawImageRect(const std::shared_ptr<Image>& image,
241-
Rect source,
242-
Rect dest,
243-
const Paint& paint,
244-
SamplerDescriptor sampler = {}) {
240+
void DrawImageRect(
241+
const std::shared_ptr<Image>& image,
242+
Rect source,
243+
Rect dest,
244+
const Paint& paint,
245+
SamplerDescriptor sampler = {},
246+
SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast) {
245247
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImageRect), image,
246-
source, dest, paint, sampler);
248+
source, dest, paint, sampler,
249+
src_rect_constraint);
247250
}
248251

249252
void ClipPath(

impeller/aiks/canvas_recorder_unittests.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class Serializer {
5454

5555
void Write(const std::vector<Color>& matrices) {}
5656

57+
void Write(const SourceRectConstraint& src_rect_constraint) {}
58+
5759
CanvasRecorderOp last_op_;
5860
};
5961
} // namespace
@@ -196,7 +198,7 @@ TEST(CanvasRecorder, DrawImage) {
196198

197199
TEST(CanvasRecorder, DrawImageRect) {
198200
CanvasRecorder<Serializer> recorder;
199-
recorder.DrawImageRect({}, {}, {}, {}, {});
201+
recorder.DrawImageRect({}, {}, {}, {}, {}, SourceRectConstraint::kFast);
200202
ASSERT_EQ(recorder.GetSerializer().last_op_,
201203
CanvasRecorderOp::kDrawImageRect);
202204
}

impeller/aiks/trace_serializer.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,9 @@ void TraceSerializer::Write(const std::vector<Rect>& matrices) {
254254
void TraceSerializer::Write(const std::vector<Color>& matrices) {
255255
buffer_ << "[std::vector<Color>] ";
256256
}
257+
258+
void TraceSerializer::Write(const SourceRectConstraint& src_rect_constraint) {
259+
buffer_ << "[SourceRectConstraint] ";
260+
}
261+
257262
} // namespace impeller

impeller/aiks/trace_serializer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ class TraceSerializer {
5858

5959
void Write(const std::vector<Color>& matrices);
6060

61+
void Write(const SourceRectConstraint& src_rect_constraint);
62+
6163
private:
6264
std::stringstream buffer_;
6365
};

impeller/display_list/dl_unittests.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,18 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCornersScaledDown) {
801801
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
802802
}
803803

804+
TEST_P(DisplayListTest, NinePatchImagePrecision) {
805+
// Draw a nine patch image with colored corners and verify that the corner
806+
// color does not leak outside the intended region.
807+
auto texture = CreateTextureForFixture("nine_patch_corners.png");
808+
flutter::DisplayListBuilder builder;
809+
builder.DrawImageNine(DlImageImpeller::Make(texture),
810+
SkIRect::MakeXYWH(10, 10, 1, 1),
811+
SkRect::MakeXYWH(0, 0, 200, 100),
812+
flutter::DlFilterMode::kNearest, nullptr);
813+
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
814+
}
815+
804816
TEST_P(DisplayListTest, CanDrawPoints) {
805817
flutter::DisplayListBuilder builder;
806818
SkPoint points[7] = {

impeller/display_list/nine_patch_converter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void NinePatchConverter::DrawNinePatch(const std::shared_ptr<Image>& image,
8686
// DrawImageAtlas.
8787
canvas->DrawImageRect(image, Rect::MakeLTRB(srcX0, srcY0, srcX1, srcY1),
8888
Rect::MakeLTRB(dstX0, dstY0, dstX1, dstY1), *paint,
89-
sampler);
89+
sampler, SourceRectConstraint::kStrict);
9090
}
9191
}
9292
}

impeller/entity/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ impeller_shaders("entity_shaders") {
5252
"shaders/texture_fill.frag",
5353
"shaders/texture_fill.vert",
5454
"shaders/texture_fill_external.frag",
55+
"shaders/texture_fill_strict_src.frag",
5556
"shaders/tiled_texture_fill.frag",
5657
"shaders/tiled_texture_fill_external.frag",
5758
"shaders/vertices.frag",

0 commit comments

Comments
 (0)