mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Ensure raster cache doesn't bleed over to adjacent physical pixels (flutter/engine#35602)
* Ensure raster cache doesn't bleed over to adjacent physical pixels * Only clip if necessary * Add tests * Reformat * Only save/restore when necessary
This commit is contained in:
parent
02c259c246
commit
5ab1c6712d
@ -47,8 +47,23 @@ void RasterCacheResult::draw(SkCanvas& canvas, const SkPaint* paint) const {
|
||||
#endif
|
||||
canvas.resetMatrix();
|
||||
flow_.Step();
|
||||
|
||||
bool exceeds_bounds = bounds.fLeft + image_->dimensions().width() >
|
||||
SkScalarCeilToScalar(bounds.fRight) ||
|
||||
bounds.fTop + image_->dimensions().height() >
|
||||
SkScalarCeilToScalar(bounds.fBottom);
|
||||
|
||||
// Make sure raster cache doesn't bleed to physical pixels outside of
|
||||
// original bounds. https://github.com/flutter/flutter/issues/110002
|
||||
if (exceeds_bounds) {
|
||||
canvas.save();
|
||||
canvas.clipRect(SkRect::Make(bounds.roundOut()));
|
||||
}
|
||||
canvas.drawImage(image_, bounds.fLeft, bounds.fTop, SkSamplingOptions(),
|
||||
paint);
|
||||
if (exceeds_bounds) {
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
RasterCache::RasterCache(size_t access_threshold,
|
||||
|
||||
@ -787,5 +787,67 @@ TEST_F(RasterCacheTest, RasterCacheKeyID_LayerChildrenIds) {
|
||||
ASSERT_EQ(ids, expected_ids);
|
||||
}
|
||||
|
||||
TEST_F(RasterCacheTest, RasterCacheBleedingNoClipNeeded) {
|
||||
SkImageInfo info =
|
||||
SkImageInfo::MakeN32(40, 40, SkAlphaType::kOpaque_SkAlphaType);
|
||||
|
||||
auto image = SkImage::MakeRasterData(
|
||||
info, SkData::MakeUninitialized(40 * 40 * 4), 40 * 4);
|
||||
auto canvas = MockCanvas();
|
||||
canvas.setMatrix(SkMatrix::Scale(2, 2));
|
||||
// Drawing cached image does not exceeds physical pixels of the original
|
||||
// bounds and does not need to be clipped.
|
||||
auto cache_result =
|
||||
RasterCacheResult(image, SkRect::MakeXYWH(100.3, 100.3, 20, 20), "");
|
||||
auto paint = SkPaint();
|
||||
cache_result.draw(canvas, &paint);
|
||||
|
||||
EXPECT_EQ(canvas.draw_calls(),
|
||||
std::vector({
|
||||
MockCanvas::DrawCall{
|
||||
0, MockCanvas::SetMatrixData{SkM44::Scale(2, 2)}},
|
||||
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkM44()}},
|
||||
MockCanvas::DrawCall{
|
||||
1, MockCanvas::DrawImageData{image, 200.6, 200.6,
|
||||
SkSamplingOptions(), paint}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(RasterCacheTest, RasterCacheBleedingClipNeeded) {
|
||||
SkImageInfo info =
|
||||
SkImageInfo::MakeN32(40, 40, SkAlphaType::kOpaque_SkAlphaType);
|
||||
|
||||
auto image = SkImage::MakeRasterData(
|
||||
info, SkData::MakeUninitialized(40 * 40 * 4), 40 * 4);
|
||||
auto canvas = MockCanvas();
|
||||
canvas.setMatrix(SkMatrix::Scale(2, 2));
|
||||
|
||||
auto cache_result =
|
||||
RasterCacheResult(image, SkRect::MakeXYWH(100.3, 100.3, 19.6, 19.6), "");
|
||||
auto paint = SkPaint();
|
||||
cache_result.draw(canvas, &paint);
|
||||
|
||||
EXPECT_EQ(
|
||||
canvas.draw_calls(),
|
||||
std::vector({
|
||||
MockCanvas::DrawCall{0,
|
||||
MockCanvas::SetMatrixData{SkM44::Scale(2, 2)}},
|
||||
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkM44()}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
|
||||
MockCanvas::DrawCall{
|
||||
2, MockCanvas::ClipRectData{SkRect::MakeLTRB(200, 200, 240, 240),
|
||||
SkClipOp::kIntersect,
|
||||
MockCanvas::kHard_ClipEdgeStyle}},
|
||||
MockCanvas::DrawCall{
|
||||
2, MockCanvas::DrawImageData{image, 200.6, 200.6,
|
||||
SkSamplingOptions(), paint}},
|
||||
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user