Pass sampling to drawImage

Bug: skia:7650
Change-Id: I050841a401610b4a68b549602e27c0bac8e62067
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/358196
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2021-01-23 18:10:39 -05:00 committed by Skia Commit-Bot
parent 07c5f52c94
commit 8d29ab6309
22 changed files with 114 additions and 100 deletions

View File

@ -213,7 +213,7 @@ private:
void onDraw(SkCanvas* canvas) override { void onDraw(SkCanvas* canvas) override {
canvas->scale(0.25f, 0.25f); canvas->scale(0.25f, 0.25f);
for (auto& p : fPlayers) { for (auto& p : fPlayers) {
canvas->drawImage(p->getFrame(), 0, 0, nullptr); canvas->drawImage(p->getFrame(), 0, 0);
canvas->translate(p->dimensions().width(), 0); canvas->translate(p->dimensions().width(), 0);
} }
} }
@ -285,7 +285,7 @@ class AnimCodecPlayerExifGM : public skiagm::GM {
auto image = fPlayer->getFrame(); auto image = fPlayer->getFrame();
canvas->drawImage(image, 0, 0, nullptr); canvas->drawImage(image, 0, 0);
duration += fFrameInfos[frame].fDuration; duration += fFrameInfos[frame].fDuration;
fPlayer->seek(duration); fPlayer->seek(duration);
} }

View File

@ -93,7 +93,7 @@ public:
canvas->drawPicture(pic); canvas->drawPicture(pic);
} else { } else {
auto image = animatedImage->getCurrentFrame(); auto image = animatedImage->getCurrentFrame();
canvas->drawImage(image, 0, 0, nullptr); canvas->drawImage(image, 0, 0);
} }
}; };
for (float scale : { 1.25f, 1.0f, .75f, .5f }) { for (float scale : { 1.25f, 1.0f, .75f, .5f }) {

View File

@ -209,7 +209,7 @@ static skiagm::DrawResult do_rescale_image_grid(SkCanvas* canvas,
} }
SkPaint paint; SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc); paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawImage(image, 0, 0, &paint); surface->getCanvas()->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
return do_rescale_grid(canvas, surface.get(), dContext, srcRect, newSize, return do_rescale_grid(canvas, surface.get(), dContext, srcRect, newSize,
doYUV420, errorMsg); doYUV420, errorMsg);
} else if (dContext) { } else if (dContext) {

View File

@ -34,7 +34,7 @@
/** Creates an image with two one-pixel wide borders around a checkerboard. The checkerboard is 2x2 /** Creates an image with two one-pixel wide borders around a checkerboard. The checkerboard is 2x2
checks where each check has as many pixels as is necessary to fill the interior. It returns checks where each check has as many pixels as is necessary to fill the interior. It returns
the image and a src rect that bounds the checkerboard portion. */ the image and a src rect that bounds the checkerboard portion. */
std::tuple<sk_sp<SkImage>, SkIRect> make_ringed_image(int width, int height) { std::tuple<sk_sp<SkImage>, SkRect> make_ringed_image(int width, int height) {
// These are kRGBA_8888_SkColorType values. // These are kRGBA_8888_SkColorType values.
static constexpr uint32_t kOuterRingColor = 0xFFFF0000, static constexpr uint32_t kOuterRingColor = 0xFFFF0000,
@ -102,7 +102,7 @@ std::tuple<sk_sp<SkImage>, SkIRect> make_ringed_image(int width, int height) {
scanline[x] = kOuterRingColor; scanline[x] = kOuterRingColor;
} }
bitmap.setImmutable(); bitmap.setImmutable();
return {bitmap.asImage(), {2, 2, width - 2, height - 2}}; return {bitmap.asImage(), SkRect::Make({2, 2, width - 2, height - 2})};
} }
/** /**
@ -121,95 +121,95 @@ protected:
SkString onShortName() override { return fShortName; } SkString onShortName() override { return fShortName; }
SkISize onISize() override { return SkISize::Make(800, 1000); } SkISize onISize() override { return SkISize::Make(800, 1000); }
void drawImage(SkCanvas* canvas, sk_sp<SkImage> image, void drawImage(SkCanvas* canvas, sk_sp<SkImage> image, SkRect srcRect, SkRect dstRect,
SkIRect srcRect, SkRect dstRect, SkPaint* paint) { const SkSamplingOptions& sampling, SkPaint* paint) {
if (fBatch) { if (fBatch) {
SkCanvas::ImageSetEntry imageSetEntry[1]; SkCanvas::ImageSetEntry imageSetEntry[1];
imageSetEntry[0].fImage = image; imageSetEntry[0].fImage = image;
imageSetEntry[0].fSrcRect = SkRect::Make(srcRect); imageSetEntry[0].fSrcRect = srcRect;
imageSetEntry[0].fDstRect = dstRect; imageSetEntry[0].fDstRect = dstRect;
imageSetEntry[0].fAAFlags = paint->isAntiAlias() ? SkCanvas::kAll_QuadAAFlags imageSetEntry[0].fAAFlags = paint->isAntiAlias() ? SkCanvas::kAll_QuadAAFlags
: SkCanvas::kNone_QuadAAFlags; : SkCanvas::kNone_QuadAAFlags;
canvas->experimental_DrawEdgeAAImageSet(imageSetEntry, SK_ARRAY_COUNT(imageSetEntry), canvas->experimental_DrawEdgeAAImageSet(imageSetEntry, SK_ARRAY_COUNT(imageSetEntry),
/*dstClips=*/nullptr, /*dstClips=*/nullptr,
/*preViewMatrices=*/nullptr, /*preViewMatrices=*/nullptr,
paint, fConstraint); sampling, paint, fConstraint);
} else { } else {
canvas->drawImageRect(image.get(), srcRect, dstRect, paint, fConstraint); canvas->drawImageRect(image.get(), srcRect, dstRect, sampling, paint, fConstraint);
} }
} }
// Draw the area of interest of the small image // Draw the area of interest of the small image
void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) { void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa,
const SkSamplingOptions& sampling) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint; SkPaint paint;
paint.setFilterQuality(filter);
paint.setColor(SK_ColorBLUE); paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa); paint.setAntiAlias(aa);
drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint); drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
} }
// Draw the area of interest of the large image // Draw the area of interest of the large image
void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) { void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa,
const SkSamplingOptions& sampling) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint; SkPaint paint;
paint.setFilterQuality(filter);
paint.setColor(SK_ColorBLUE); paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa); paint.setAntiAlias(aa);
drawImage(canvas, fBigImage, fBigSrcRect, dst, &paint); drawImage(canvas, fBigImage, fBigSrcRect, dst, sampling, &paint);
} }
// Draw upper-left 1/4 of the area of interest of the large image // Draw upper-left 1/4 of the area of interest of the large image
void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) { void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa,
SkIRect src = SkIRect::MakeXYWH(fBigSrcRect.fLeft, const SkSamplingOptions& sampling) {
fBigSrcRect.fTop, SkRect src = SkRect::MakeXYWH(fBigSrcRect.fLeft,
fBigSrcRect.width()/2, fBigSrcRect.fTop,
fBigSrcRect.height()/2); fBigSrcRect.width()/2,
fBigSrcRect.height()/2);
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint; SkPaint paint;
paint.setFilterQuality(filter);
paint.setColor(SK_ColorBLUE); paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa); paint.setAntiAlias(aa);
drawImage(canvas, fBigImage, src, dst, &paint); drawImage(canvas, fBigImage, src, dst, sampling, &paint);
} }
// Draw the area of interest of the small image with a normal blur // Draw the area of interest of the small image with a normal blur
void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) { void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa,
const SkSamplingOptions& sampling) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint; SkPaint paint;
paint.setFilterQuality(filter);
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(3))); SkBlurMask::ConvertRadiusToSigma(3)));
paint.setColor(SK_ColorBLUE); paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa); paint.setAntiAlias(aa);
drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint); drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
} }
// Draw the area of interest of the small image with a outer blur // Draw the area of interest of the small image with a outer blur
void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) { void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa,
const SkSamplingOptions& sampling) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY), SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize)); SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint; SkPaint paint;
paint.setFilterQuality(filter);
paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(7))); SkBlurMask::ConvertRadiusToSigma(7)));
paint.setColor(SK_ColorBLUE); paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa); paint.setAntiAlias(aa);
drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint); drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
} }
void onOnceBeforeDraw() override { void onOnceBeforeDraw() override {
@ -240,6 +240,10 @@ protected:
m.preScale(0.2f, 0.2f); m.preScale(0.2f, 0.2f);
matrices.push_back(m); matrices.push_back(m);
const SkSamplingOptions none(SkFilterMode::kNearest);
const SkSamplingOptions low(SkFilterMode::kLinear);
const SkSamplingOptions high({1.0f/3, 1.0f/3});
SkScalar maxX = 0; SkScalar maxX = 0;
for (bool antiAlias : {false, true}) { for (bool antiAlias : {false, true}) {
canvas->save(); canvas->save();
@ -249,18 +253,18 @@ protected:
canvas->concat(matrix); canvas->concat(matrix);
// First draw a column with no filtering // First draw a column with no filtering
this->drawCase1(canvas, kCol0X, kRow0Y, antiAlias, kNone_SkFilterQuality); this->drawCase1(canvas, kCol0X, kRow0Y, antiAlias, none);
this->drawCase2(canvas, kCol0X, kRow1Y, antiAlias, kNone_SkFilterQuality); this->drawCase2(canvas, kCol0X, kRow1Y, antiAlias, none);
this->drawCase3(canvas, kCol0X, kRow2Y, antiAlias, kNone_SkFilterQuality); this->drawCase3(canvas, kCol0X, kRow2Y, antiAlias, none);
this->drawCase4(canvas, kCol0X, kRow3Y, antiAlias, kNone_SkFilterQuality); this->drawCase4(canvas, kCol0X, kRow3Y, antiAlias, none);
this->drawCase5(canvas, kCol0X, kRow4Y, antiAlias, kNone_SkFilterQuality); this->drawCase5(canvas, kCol0X, kRow4Y, antiAlias, none);
// Then draw a column with low filtering // Then draw a column with low filtering
this->drawCase1(canvas, kCol1X, kRow0Y, antiAlias, kLow_SkFilterQuality); this->drawCase1(canvas, kCol1X, kRow0Y, antiAlias, low);
this->drawCase2(canvas, kCol1X, kRow1Y, antiAlias, kLow_SkFilterQuality); this->drawCase2(canvas, kCol1X, kRow1Y, antiAlias, low);
this->drawCase3(canvas, kCol1X, kRow2Y, antiAlias, kLow_SkFilterQuality); this->drawCase3(canvas, kCol1X, kRow2Y, antiAlias, low);
this->drawCase4(canvas, kCol1X, kRow3Y, antiAlias, kLow_SkFilterQuality); this->drawCase4(canvas, kCol1X, kRow3Y, antiAlias, low);
this->drawCase5(canvas, kCol1X, kRow4Y, antiAlias, kLow_SkFilterQuality); this->drawCase5(canvas, kCol1X, kRow4Y, antiAlias, low);
// Then draw a column with high filtering. Skip it if in kStrict mode and MIP // Then draw a column with high filtering. Skip it if in kStrict mode and MIP
// mapping will be used. On GPU we allow bleeding at non-base levels because // mapping will be used. On GPU we allow bleeding at non-base levels because
@ -268,11 +272,11 @@ protected:
SkScalar scales[2]; SkScalar scales[2];
SkAssertResult(matrix.getMinMaxScales(scales)); SkAssertResult(matrix.getMinMaxScales(scales));
if (fConstraint != SkCanvas::kStrict_SrcRectConstraint || scales[0] >= 1.f) { if (fConstraint != SkCanvas::kStrict_SrcRectConstraint || scales[0] >= 1.f) {
this->drawCase1(canvas, kCol2X, kRow0Y, antiAlias, kHigh_SkFilterQuality); this->drawCase1(canvas, kCol2X, kRow0Y, antiAlias, high);
this->drawCase2(canvas, kCol2X, kRow1Y, antiAlias, kHigh_SkFilterQuality); this->drawCase2(canvas, kCol2X, kRow1Y, antiAlias, high);
this->drawCase3(canvas, kCol2X, kRow2Y, antiAlias, kHigh_SkFilterQuality); this->drawCase3(canvas, kCol2X, kRow2Y, antiAlias, high);
this->drawCase4(canvas, kCol2X, kRow3Y, antiAlias, kHigh_SkFilterQuality); this->drawCase4(canvas, kCol2X, kRow3Y, antiAlias, high);
this->drawCase5(canvas, kCol2X, kRow4Y, antiAlias, kHigh_SkFilterQuality); this->drawCase5(canvas, kCol2X, kRow4Y, antiAlias, high);
} }
SkPoint innerCorners[] = {{0, 0}, {0, kBottom}, {kWidth, kBottom}, {kWidth, 0}}; SkPoint innerCorners[] = {{0, 0}, {0, kBottom}, {kWidth, kBottom}, {kWidth, 0}};
@ -311,8 +315,8 @@ private:
SkString fShortName; SkString fShortName;
sk_sp<SkImage> fBigImage; sk_sp<SkImage> fBigImage;
sk_sp<SkImage> fSmallImage; sk_sp<SkImage> fSmallImage;
SkIRect fBigSrcRect; SkRect fBigSrcRect;
SkIRect fSmallSrcRect; SkRect fSmallSrcRect;
SkCanvas::SrcRectConstraint fConstraint; SkCanvas::SrcRectConstraint fConstraint;
bool fBatch = false; bool fBatch = false;
using INHERITED = GM; using INHERITED = GM;

View File

@ -127,7 +127,7 @@ DEF_SIMPLE_GM(BlurDrawImage, canvas, 256, 256) {
canvas->clear(0xFF88FF88); canvas->clear(0xFF88FF88);
if (auto image = GetResourceAsImage("images/mandrill_512_q075.jpg")) { if (auto image = GetResourceAsImage("images/mandrill_512_q075.jpg")) {
canvas->scale(0.25, 0.25); canvas->scale(0.25, 0.25);
canvas->drawImage(image, 256, 256, &paint); canvas->drawImage(image, 256, 256, SkSamplingOptions(), &paint);
} }
} }

View File

@ -217,7 +217,7 @@ DEF_SIMPLE_GM(clip_shader, canvas, 840, 650) {
SkPaint p; SkPaint p;
canvas->translate(10, 10); canvas->translate(10, 10);
canvas->drawImage(img, 0, 0, nullptr); canvas->drawImage(img, 0, 0);
canvas->save(); canvas->save();
canvas->translate(img->width() + 10, 0); canvas->translate(img->width() + 10, 0);
@ -240,7 +240,7 @@ DEF_SIMPLE_GM(clip_shader, canvas, 840, 650) {
SkMatrix lm = SkMatrix::Scale(1.0f/5, 1.0f/5); SkMatrix lm = SkMatrix::Scale(1.0f/5, 1.0f/5);
canvas->clipShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, canvas->clipShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
SkSamplingOptions(), lm)); SkSamplingOptions(), lm));
canvas->drawImage(img, 0, 0, nullptr); canvas->drawImage(img, 0, 0);
canvas->restore(); canvas->restore();
canvas->restore(); canvas->restore();

View File

@ -60,9 +60,9 @@ DEF_SIMPLE_GPU_GM_CAN_FAIL(cross_context_image, context, rtc, canvas, errorMsg,
0, 0); 0, 0);
canvas->translate(128, 0); canvas->translate(128, 0);
SkPaint paint; canvas->drawImageRect(images[i], SkRect::MakeWH(128, 128),
paint.setFilterQuality(kMedium_SkFilterQuality); SkSamplingOptions(SkFilterMode::kLinear,
canvas->drawImageRect(images[i], SkRect::MakeWH(128, 128), &paint); SkMipmapMode::kLinear));
canvas->restore(); canvas->restore();
canvas->translate(256 + 10, 0); canvas->translate(256 + 10, 0);

View File

@ -247,7 +247,7 @@ DEF_SIMPLE_GM(HSL_duck, canvas, 1110, 620) {
p.setShader(nullptr); p.setShader(nullptr);
p.setBlendMode(mode); p.setBlendMode(mode);
p.setAlphaf(src_a); p.setAlphaf(src_a);
canvas->drawImageRect(src, r, &p); canvas->drawImageRect(src, r, SkSamplingOptions(), &p);
canvas->translate(r.width() + 10, 0); canvas->translate(r.width() + 10, 0);
} }

View File

@ -155,14 +155,14 @@ DEF_SIMPLE_GM(imageblurrepeatunclipped, canvas, 256, 128) {
// Draw the blurred image once // Draw the blurred image once
canvas->translate(0, 50); canvas->translate(0, 50);
canvas->drawImage(img, 0, 0, &paint); canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
// Draw the blurred image with a clip positioned such that the draw would be excluded except // Draw the blurred image with a clip positioned such that the draw would be excluded except
// that the image filter causes it to intersect with the clip. Ideally should look like the // that the image filter causes it to intersect with the clip. Ideally should look like the
// left image, but clipped to the debug-black rectangle (Narrator: it does not look like that). // left image, but clipped to the debug-black rectangle (Narrator: it does not look like that).
canvas->translate(110, 0); canvas->translate(110, 0);
canvas->clipRect(SkRect::MakeXYWH(0, -30, 100, 10)); canvas->clipRect(SkRect::MakeXYWH(0, -30, 100, 10));
canvas->drawImage(img, 0, 0, &paint); canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
// Visualize the clip // Visualize the clip
SkPaint line; SkPaint line;

View File

@ -207,7 +207,7 @@ protected:
SkPaint p; SkPaint p;
p.setImageFilter(filter); p.setImageFilter(filter);
canvas->drawImage(fImage.get(), 128, 128, &p); canvas->drawImage(fImage.get(), 128, 128, SkSamplingOptions(), &p);
} }
private: private:
@ -264,7 +264,7 @@ private:
canvas->clipRect(SkRect::MakeIWH(256, 256)); canvas->clipRect(SkRect::MakeIWH(256, 256));
canvas->scale(0.5f, 0.5f); canvas->scale(0.5f, 0.5f);
canvas->translate(128, 128); canvas->translate(128, 128);
canvas->drawImage(fImage, 0, 0, &p); canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &p);
canvas->restore(); canvas->restore();
} }

View File

@ -216,7 +216,8 @@ protected:
// Resize to 100x100 // Resize to 100x100
surface->getCanvas()->drawImageRect( surface->getCanvas()->drawImageRect(
colorImage, SkRect::MakeWH(colorImage->width(), colorImage->height()), colorImage, SkRect::MakeWH(colorImage->width(), colorImage->height()),
SkRect::MakeWH(info.width(), info.height()), nullptr); SkRect::MakeWH(info.width(), info.height()), SkSamplingOptions(), nullptr,
SkCanvas::kStrict_SrcRectConstraint);
fMainImage = surface->makeImageSnapshot(); fMainImage = surface->makeImageSnapshot();
ToolUtils::draw_checkerboard(surface->getCanvas()); ToolUtils::draw_checkerboard(surface->getCanvas());
@ -319,7 +320,7 @@ protected:
// filtered result. // filtered result.
SkPaint alpha; SkPaint alpha;
alpha.setAlphaf(0.3f); alpha.setAlphaf(0.3f);
canvas->drawImage(mainImage, 0, 0, &alpha); canvas->drawImage(mainImage, 0, 0, SkSamplingOptions(), &alpha);
this->drawImageWithFilter(canvas, mainImage, auxImage, filters[i], clipBound, this->drawImageWithFilter(canvas, mainImage, auxImage, filters[i], clipBound,
subset, &outSubset); subset, &outSubset);
@ -368,7 +369,9 @@ private:
canvas->saveLayer(nullptr, &paint); canvas->saveLayer(nullptr, &paint);
// Draw the original subset of the image // Draw the original subset of the image
canvas->drawImageRect(mainImage, subset, SkRect::Make(subset), nullptr); SkRect r = SkRect::Make(subset);
canvas->drawImageRect(mainImage, r, r, SkSamplingOptions(),
nullptr, SkCanvas::kStrict_SrcRectConstraint);
*dstRect = subset; *dstRect = subset;
} else { } else {
@ -385,7 +388,9 @@ private:
*dstRect = SkIRect::MakeXYWH(offset.x(), offset.y(), *dstRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
outSubset.width(), outSubset.height()); outSubset.width(), outSubset.height());
canvas->drawImageRect(result, outSubset, SkRect::Make(*dstRect), nullptr); canvas->drawImageRect(result, SkRect::Make(outSubset), SkRect::Make(*dstRect),
SkSamplingOptions(), nullptr,
SkCanvas::kStrict_SrcRectConstraint);
} }
} }

View File

@ -125,7 +125,7 @@ protected:
{ 200, 200, }, { 200, 200, },
}; };
canvas->drawImage(image, 10, 10, nullptr); canvas->drawImage(image, 10, 10);
SkScalar x = SkIntToScalar(100); SkScalar x = SkIntToScalar(100);
SkScalar y = SkIntToScalar(100); SkScalar y = SkIntToScalar(100);
@ -299,7 +299,7 @@ public:
sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom); sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
canvas->drawImage(image, 10, 10, nullptr); canvas->drawImage(image, 10, 10);
SkCanvas::Lattice lattice; SkCanvas::Lattice lattice;
lattice.fXCount = 2; lattice.fXCount = 2;

View File

@ -52,7 +52,7 @@ DEF_SIMPLE_GM_BG(overdraw_canvas, canvas, WIDTH, HEIGHT, SK_ColorWHITE) {
// Draw overdraw colors to the canvas. The color filter will convert counts to colors. // Draw overdraw colors to the canvas. The color filter will convert counts to colors.
SkPaint paint; SkPaint paint;
paint.setColorFilter(SkOverdrawColorFilter::MakeWithSkColors(kOverdrawColors)); paint.setColorFilter(SkOverdrawColorFilter::MakeWithSkColors(kOverdrawColors));
canvas->drawImage(counts.get(), 0.0f, 0.0f, &paint); canvas->drawImage(counts.get(), 0.0f, 0.0f, SkSamplingOptions(), &paint);
canvas->drawString("This is some text:", 180, 300, SkFont(), SkPaint()); canvas->drawString("This is some text:", 180, 300, SkFont(), SkPaint());
} }

View File

@ -56,9 +56,8 @@ protected:
} }
void onOnceBeforeDraw() override { void onOnceBeforeDraw() override {
fBitmap = ToolUtils::create_checkerboard_bitmap( fBitmapImage = ToolUtils::create_checkerboard_image(
kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10); kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);
fBitmap.setImmutable();
SkPoint pts1[] = { SkPoint pts1[] = {
{ 0, 0 }, { 0, 0 },
@ -89,13 +88,12 @@ protected:
fPath.close(); fPath.close();
} }
void drawRow(SkCanvas* canvas, SkFilterQuality filterQ) { void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) {
SkPaint filterPaint; SkPaint filterPaint;
filterPaint.setFilterQuality(filterQ);
filterPaint.setAntiAlias(fDoAA); filterPaint.setAntiAlias(fDoAA);
SkPaint pathPaint; SkPaint pathPaint;
pathPaint.setShader(fBitmap.makeShader(SkSamplingOptions(filterQ))); pathPaint.setShader(fBitmapImage->makeShader(sampling));
pathPaint.setAntiAlias(fDoAA); pathPaint.setAntiAlias(fDoAA);
SkPaint gradPaint1; SkPaint gradPaint1;
@ -111,13 +109,13 @@ protected:
canvas->save(); canvas->save();
canvas->concat(fPerspMatrix); canvas->concat(fPerspMatrix);
canvas->drawBitmapRect(fBitmap, r, &filterPaint); canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint);
canvas->restore(); canvas->restore();
canvas->translate(SkIntToScalar(kCellSize), 0); canvas->translate(SkIntToScalar(kCellSize), 0);
canvas->save(); canvas->save();
canvas->concat(fPerspMatrix); canvas->concat(fPerspMatrix);
canvas->drawImage(fImage.get(), 0, 0, &filterPaint); canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint);
canvas->restore(); canvas->restore();
canvas->translate(SkIntToScalar(kCellSize), 0); canvas->translate(SkIntToScalar(kCellSize), 0);
@ -152,13 +150,14 @@ protected:
fImage = make_image(canvas, kCellSize, kCellSize); fImage = make_image(canvas, kCellSize, kCellSize);
} }
this->drawRow(canvas, kNone_SkFilterQuality); this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest));
canvas->translate(0, SkIntToScalar(kCellSize)); canvas->translate(0, SkIntToScalar(kCellSize));
this->drawRow(canvas, kLow_SkFilterQuality); this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear));
canvas->translate(0, SkIntToScalar(kCellSize)); canvas->translate(0, SkIntToScalar(kCellSize));
this->drawRow(canvas, kMedium_SkFilterQuality); this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear,
SkMipmapMode::kNearest));
canvas->translate(0, SkIntToScalar(kCellSize)); canvas->translate(0, SkIntToScalar(kCellSize));
this->drawRow(canvas, kHigh_SkFilterQuality); this->drawRow(canvas, SkSamplingOptions({1.0f/3, 1.0f/3}));
canvas->translate(0, SkIntToScalar(kCellSize)); canvas->translate(0, SkIntToScalar(kCellSize));
} }
private: private:
@ -172,7 +171,7 @@ private:
sk_sp<SkShader> fLinearGrad2; sk_sp<SkShader> fLinearGrad2;
SkMatrix fPerspMatrix; SkMatrix fPerspMatrix;
sk_sp<SkImage> fImage; sk_sp<SkImage> fImage;
SkBitmap fBitmap; sk_sp<SkImage> fBitmapImage;
using INHERITED = GM; using INHERITED = GM;
}; };

View File

@ -124,7 +124,7 @@ static void draw_image(GrDirectContext* dContext, SkCanvas* canvas, SkImage* ima
// Now that we have called readPixels(), dump the raw pixels into an srgb image. // Now that we have called readPixels(), dump the raw pixels into an srgb image.
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes); sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr); canvas->drawImage(raw.get(), 0.0f, 0.0f);
} }
class ReadPixelsGM : public skiagm::GM { class ReadPixelsGM : public skiagm::GM {

View File

@ -109,7 +109,7 @@ DEF_SIMPLE_GM(runtimecolorfilter, canvas, 256 * 3, 256 * 2) {
SkPaint p; SkPaint p;
sk_sp<SkColorFilter> input = nullptr; sk_sp<SkColorFilter> input = nullptr;
p.setColorFilter(effect->makeColorFilter(nullptr, &input, 1)); p.setColorFilter(effect->makeColorFilter(nullptr, &input, 1));
canvas->drawImage(img, 0, 0, &p); canvas->drawImage(img, 0, 0, SkSamplingOptions(), &p);
canvas->translate(256, 0); canvas->translate(256, 0);
}; };

View File

@ -47,7 +47,7 @@
// restore with kPlus mode, which should show the mandrill super-bright on the outside, but // restore with kPlus mode, which should show the mandrill super-bright on the outside, but
// normal where we punched the hole. // normal where we punched the hole.
DEF_SIMPLE_GM(savelayer_initfromprev, canvas, 256, 256) { DEF_SIMPLE_GM(savelayer_initfromprev, canvas, 256, 256) {
canvas->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0, nullptr); canvas->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0);
SkCanvas::SaveLayerRec rec; SkCanvas::SaveLayerRec rec;
SkPaint paint; SkPaint paint;
@ -88,7 +88,7 @@ DEF_SIMPLE_GM(savelayer_coverage, canvas, 500, 500) {
canvas->translate(x * 200.f, y * 200.f); canvas->translate(x * 200.f, y * 200.f);
SkCanvas::SaveLayerRec rec(&r, &layerPaint, yflags[y] | xflags[x]); SkCanvas::SaveLayerRec rec(&r, &layerPaint, yflags[y] | xflags[x]);
canvas->drawImageRect(image, r, nullptr); canvas->drawImageRect(image, r, SkSamplingOptions(), nullptr);
proc(canvas, rec); proc(canvas, rec);
canvas->restore(); canvas->restore();

View File

@ -148,7 +148,7 @@ protected:
drawInto(surf->getCanvas()); drawInto(surf->getCanvas());
sk_sp<SkImage> image(surf->makeImageSnapshot()); sk_sp<SkImage> image(surf->makeImageSnapshot());
canvas->drawImage(image, 10, 10, nullptr); canvas->drawImage(image, 10, 10);
auto surf2(surf->makeSurface(info)); auto surf2(surf->makeSurface(info));
drawInto(surf2->getCanvas()); drawInto(surf2->getCanvas());
@ -157,7 +157,7 @@ protected:
SkASSERT(equal(surf->props(), surf2->props())); SkASSERT(equal(surf->props(), surf2->props()));
sk_sp<SkImage> image2(surf2->makeImageSnapshot()); sk_sp<SkImage> image2(surf2->makeImageSnapshot());
canvas->drawImage(image2.get(), 10 + SkIntToScalar(image->width()) + 10, 10, nullptr); canvas->drawImage(image2.get(), 10 + SkIntToScalar(image->width()) + 10, 10);
} }
private: private:
@ -182,7 +182,7 @@ DEF_SIMPLE_GM(copy_on_write_retain, canvas, 256, 256) {
surf->getCanvas()->clear(SK_ColorBLUE); surf->getCanvas()->clear(SK_ColorBLUE);
// expect to see two rects: blue | red // expect to see two rects: blue | red
canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr); canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
} }
DEF_SIMPLE_GM(copy_on_write_savelayer, canvas, 256, 256) { DEF_SIMPLE_GM(copy_on_write_savelayer, canvas, 256, 256) {
@ -203,7 +203,7 @@ DEF_SIMPLE_GM(copy_on_write_savelayer, canvas, 256, 256) {
surf->getCanvas()->restore(); surf->getCanvas()->restore();
// expect to see two rects: blue blended on red // expect to see two rects: blue blended on red
canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr); canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
} }
DEF_SIMPLE_GM(surface_underdraw, canvas, 256, 256) { DEF_SIMPLE_GM(surface_underdraw, canvas, 256, 256) {
@ -258,7 +258,7 @@ DEF_SIMPLE_GM(surface_underdraw, canvas, 256, 256) {
paint.setBlendMode(SkBlendMode::kDstOver); paint.setBlendMode(SkBlendMode::kDstOver);
surf->getCanvas()->drawImage(saveImg, surf->getCanvas()->drawImage(saveImg,
SkIntToScalar(subset.left()), SkIntToScalar(subset.top()), SkIntToScalar(subset.left()), SkIntToScalar(subset.top()),
&paint); SkSamplingOptions(), &paint);
} }
// show it on screen // show it on screen

View File

@ -176,7 +176,7 @@ protected:
SkAutoCanvasRestore acr(inputCanvas, true); SkAutoCanvasRestore acr(inputCanvas, true);
// since we prepended this matrix already, we blit using identity // since we prepended this matrix already, we blit using identity
inputCanvas->resetMatrix(); inputCanvas->resetMatrix();
inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0);
} }
} }

View File

@ -64,19 +64,20 @@ static void show_image(SkCanvas* canvas, int width, int height, SkColor colors[2
canvas->save(); canvas->save();
canvas->clipRect(dstRect); canvas->clipRect(dstRect);
canvas->drawImage(image, 0, 0, nullptr); canvas->drawImage(image, 0, 0);
canvas->restore(); canvas->restore();
canvas->drawRect(dstRect, borderPaint); canvas->drawRect(dstRect, borderPaint);
dstRect.offset(SkIntToScalar(150), 0); dstRect.offset(SkIntToScalar(150), 0);
int hw = width / 2; int hw = width / 2;
int hh = height / 2; int hh = height / 2;
SkIRect subset = SkIRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32); SkRect subset = SkRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32);
canvas->drawImageRect(image, subset, dstRect, nullptr); canvas->drawImageRect(image, subset, dstRect, SkSamplingOptions(), nullptr,
SkCanvas::kStrict_SrcRectConstraint);
canvas->drawRect(dstRect, borderPaint); canvas->drawRect(dstRect, borderPaint);
dstRect.offset(SkIntToScalar(150), 0); dstRect.offset(SkIntToScalar(150), 0);
canvas->drawImageRect(image, dstRect, nullptr); canvas->drawImageRect(image, dstRect, SkSamplingOptions(), nullptr);
canvas->drawRect(dstRect, borderPaint); canvas->drawRect(dstRect, borderPaint);
} }

View File

@ -1852,11 +1852,6 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
this->onDrawPath(path, paint); this->onDrawPath(path, paint);
} }
#ifdef SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
this->drawImage(image, x, y, paint_to_sampling(paint, this->recordingContext()), paint);
}
// Returns true if the rect can be "filled" : non-empty and finite // Returns true if the rect can be "filled" : non-empty and finite
static bool fillable(const SkRect& r) { static bool fillable(const SkRect& r) {
SkScalar w = r.width(); SkScalar w = r.width();
@ -1864,6 +1859,11 @@ static bool fillable(const SkRect& r) {
return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0; return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0;
} }
#ifdef SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
this->drawImage(image, x, y, paint_to_sampling(paint, this->recordingContext()), paint);
}
void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst, void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) { const SkPaint* paint, SrcRectConstraint constraint) {
this->drawImageRect(image, src, dst, paint_to_sampling(paint, this->recordingContext()), this->drawImageRect(image, src, dst, paint_to_sampling(paint, this->recordingContext()),

View File

@ -139,12 +139,17 @@ sk_sp<SkSpecialImage> SkImageSourceImpl::onFilterImage(const Context& ctx,
// Subtract off the integer component of the translation (will be applied in offset, below). // Subtract off the integer component of the translation (will be applied in offset, below).
dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop));
paint.setBlendMode(SkBlendMode::kSrc); paint.setBlendMode(SkBlendMode::kSrc);
// TODO: take sampling explicitly, rather than filter-quality
SkSamplingOptions sampling(fFilterQuality, canvas->recordingContext() ?
SkSamplingOptions::kMedium_asMipmapLinear :
SkSamplingOptions::kMedium_asMipmapNearest);
// FIXME: this probably shouldn't be necessary, but drawImageRect asserts // FIXME: this probably shouldn't be necessary, but drawImageRect asserts
// None filtering when it's translate-only // None filtering when it's translate-only
paint.setFilterQuality( if (fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height()) {
fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ? sampling = SkSamplingOptions();
kNone_SkFilterQuality : fFilterQuality); }
canvas->drawImageRect(fImage.get(), fSrcRect, dstRect, &paint, canvas->drawImageRect(fImage.get(), fSrcRect, dstRect, sampling, &paint,
SkCanvas::kStrict_SrcRectConstraint); SkCanvas::kStrict_SrcRectConstraint);
offset->fX = dstIRect.fLeft; offset->fX = dstIRect.fLeft;