Pass sampling to surface.draw

Bug: skia:7650
Change-Id: I97941a44faa4176f94d57a9c1626ac36b0c0c4ea
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/350557
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/docs/examples/Surface_MakeRenderTarget_2.cpp b/docs/examples/Surface_MakeRenderTarget_2.cpp
index ff8046d..f610d94 100644
--- a/docs/examples/Surface_MakeRenderTarget_2.cpp
+++ b/docs/examples/Surface_MakeRenderTarget_2.cpp
@@ -27,7 +27,7 @@
                         ? SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, &props)
                         : SkSurface::MakeRaster(info, &props);
         test_draw(surface->getCanvas());
-        surface->draw(canvas, 0, y, nullptr);
+        surface->draw(canvas, 0, y);
         sk_sp<SkImage> image(surface->makeImageSnapshot());
         SkAutoCanvasRestore acr(canvas, true);
         canvas->scale(8, 8);
diff --git a/docs/examples/Surface_draw.cpp b/docs/examples/Surface_draw.cpp
index d4e9d71..4808836 100644
--- a/docs/examples/Surface_draw.cpp
+++ b/docs/examples/Surface_draw.cpp
@@ -8,7 +8,7 @@
     sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
     big->getCanvas()->clear(SK_ColorRED);
     lil->getCanvas()->clear(SK_ColorBLACK);
-    lil->draw(big->getCanvas(), 16, 16, nullptr);
+    lil->draw(big->getCanvas(), 16, 16);
     SkPixmap pixmap;
     if (big->peekPixels(&pixmap)) {
         SkBitmap bigBits;
diff --git a/docs/examples/Surface_makeImageSnapshot.cpp b/docs/examples/Surface_makeImageSnapshot.cpp
index 9d40184..1b60a30 100644
--- a/docs/examples/Surface_makeImageSnapshot.cpp
+++ b/docs/examples/Surface_makeImageSnapshot.cpp
@@ -9,7 +9,7 @@
     big->getCanvas()->clear(SK_ColorRED);
     lil->getCanvas()->clear(SK_ColorBLACK);
     sk_sp<SkImage> early(big->makeImageSnapshot());
-    lil->draw(big->getCanvas(), 16, 16, nullptr);
+    lil->draw(big->getCanvas(), 16, 16);
     sk_sp<SkImage> later(big->makeImageSnapshot());
     canvas->drawImage(early, 0, 0);
     canvas->drawImage(later, 128, 0);
diff --git a/docs/examples/Surface_makeImageSnapshot_2.cpp b/docs/examples/Surface_makeImageSnapshot_2.cpp
index 225d0be..80c5580 100644
--- a/docs/examples/Surface_makeImageSnapshot_2.cpp
+++ b/docs/examples/Surface_makeImageSnapshot_2.cpp
@@ -9,7 +9,7 @@
     big->getCanvas()->clear(SK_ColorRED);
     lil->getCanvas()->clear(SK_ColorBLACK);
     sk_sp<SkImage> early(big->makeImageSnapshot());
-    lil->draw(big->getCanvas(), 16, 16, nullptr);
+    lil->draw(big->getCanvas(), 16, 16);
     sk_sp<SkImage> later(big->makeImageSnapshot({0, 0, 16, 16}));
     canvas->drawImage(early, 0, 0);
     canvas->drawImage(later, 0, 0);
diff --git a/docs/examples/blur4444.cpp b/docs/examples/blur4444.cpp
index 873c97e..0d24c90 100644
--- a/docs/examples/blur4444.cpp
+++ b/docs/examples/blur4444.cpp
@@ -57,6 +57,6 @@
 
     SkPaint postPaint;
     postPaint.setDither(postDither);
-    surf->draw(canvas, 0, 0, &postPaint);
+    surf->draw(canvas, 0, 0, SkSamplingOptions(), &postPaint);
 }
 }  // END FIDDLE
diff --git a/gm/color4f.cpp b/gm/color4f.cpp
index 3b9dfe4..92ffcbe 100644
--- a/gm/color4f.cpp
+++ b/gm/color4f.cpp
@@ -87,7 +87,7 @@
         auto surface(SkSurface::MakeRaster(info));
         surface->getCanvas()->drawPaint(bg);
         draw_into_canvas(surface->getCanvas());
-        surface->draw(canvas, 0, 0, nullptr);
+        surface->draw(canvas, 0, 0);
         canvas->translate(0, 120);
     }
 }
diff --git a/gm/discard.cpp b/gm/discard.cpp
index c564abe..7a5a15e 100644
--- a/gm/discard.cpp
+++ b/gm/discard.cpp
@@ -82,7 +82,7 @@
                       surface->getCanvas()->drawPaint(paint);
                       break;
               }
-              surface->draw(canvas, 10.f*x, 10.f*y, nullptr);
+              surface->draw(canvas, 10.f*x, 10.f*y);
             }
         }
 
diff --git a/gm/fatpathfill.cpp b/gm/fatpathfill.cpp
index bd82d17..0dd2b57 100644
--- a/gm/fatpathfill.cpp
+++ b/gm/fatpathfill.cpp
@@ -41,7 +41,7 @@
 
     surface->getCanvas()->clear(SK_ColorTRANSPARENT);
     surface->getCanvas()->drawPath(path, paint);
-    surface->draw(canvas, 0, 0, nullptr);
+    surface->draw(canvas, 0, 0);
 
     paint.setAntiAlias(true);
     paint.setColor(SK_ColorRED);
diff --git a/gm/hugepath.cpp b/gm/hugepath.cpp
index 0d2902a..f76ade3 100644
--- a/gm/hugepath.cpp
+++ b/gm/hugepath.cpp
@@ -54,7 +54,7 @@
         canvas->save();
         canvas->clipRect(SkRect::MakeXYWH(4, 4, 64, 64));
         can->drawPath(path, paint);
-        surf->draw(canvas, 64 - w, 0, nullptr);
+        surf->draw(canvas, 64 - w, 0);
         canvas->restore();
 
         canvas->translate(80, 0);
@@ -63,7 +63,7 @@
         can->clear(0);
         paint.setAntiAlias(true);
         can->drawPath(path, paint);
-        surf->draw(canvas, 64 - w, 0, nullptr);
+        surf->draw(canvas, 64 - w, 0);
         canvas->restore();
     };
 
diff --git a/gm/image.cpp b/gm/image.cpp
index a9dae3b3..afbbe56 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -80,12 +80,10 @@
     drawContents(surf, SK_ColorBLUE);
 
     SkPaint paint;
-//    paint.setFilterBitmap(true);
-//    paint.setAlpha(0x80);
 
     canvas->drawImage(imgR, 0, 0, usePaint ? &paint : nullptr);
     canvas->drawImage(imgG, 0, 80, usePaint ? &paint : nullptr);
-    surf->draw(canvas, 0, 160, usePaint ? &paint : nullptr);
+    surf->draw(canvas, 0, 160, SkSamplingOptions(), usePaint ? &paint : nullptr);
 
     SkRect src1, src2, src3;
     src1.setIWH(surf->width(), surf->height());
diff --git a/gm/lcdblendmodes.cpp b/gm/lcdblendmodes.cpp
index 670a826..a054e2b 100644
--- a/gm/lcdblendmodes.cpp
+++ b/gm/lcdblendmodes.cpp
@@ -86,7 +86,7 @@
 
         SkPaint surfPaint;
         surfPaint.setBlendMode(SkBlendMode::kSrcOver);
-        surface->draw(canvas, 0, 0, &surfPaint);
+        surface->draw(canvas, 0, 0, SkSamplingOptions(), &surfPaint);
     }
 
     void drawColumn(SkCanvas* canvas, SkColor backgroundColor, SkColor textColor, bool useGrad) {
diff --git a/gm/mac_aa_explorer.cpp b/gm/mac_aa_explorer.cpp
index 572ddf5..d78beb5 100644
--- a/gm/mac_aa_explorer.cpp
+++ b/gm/mac_aa_explorer.cpp
@@ -91,7 +91,7 @@
             CGContextSetShouldSmoothFonts(ctx, smooth);
             CGContextShowTextAtPoint(ctx, 2 + xpos, 2, "A", 1);
 
-            surf->draw(canvas, x, y, nullptr);
+            surf->draw(canvas, x, y);
             x += pm.width();
         }
         y += pm.height();
diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp
index c2d4046..881e58a 100644
--- a/gm/pathfill.cpp
+++ b/gm/pathfill.cpp
@@ -663,7 +663,7 @@
 
     canvas->drawPath(path, p);
 
-    surf->draw(orig, 0, 0, nullptr);
+    surf->draw(orig, 0, 0);
 }
 
 DEF_SIMPLE_GM(path_arcto_skbug_9077, canvas, 200, 200) {
diff --git a/gm/srcmode.cpp b/gm/srcmode.cpp
index 69ec695..fad75a8 100644
--- a/gm/srcmode.cpp
+++ b/gm/srcmode.cpp
@@ -133,7 +133,7 @@
         auto surf(compat_surface(canvas, this->getISize()));
         surf->getCanvas()->drawColor(SK_ColorWHITE);
         this->drawContent(surf->getCanvas());
-        surf->draw(canvas, 0, 0, nullptr);
+        surf->draw(canvas, 0, 0);
     }
 };
 
diff --git a/gm/surface.cpp b/gm/surface.cpp
index afed502..9af76d9 100644
--- a/gm/surface.cpp
+++ b/gm/surface.cpp
@@ -108,7 +108,7 @@
                 continue;
             }
             test_draw(surface->getCanvas(), rec.fLabel);
-            surface->draw(canvas, x, y, nullptr);
+            surface->draw(canvas, x, y);
             y += H;
         }
     }
@@ -262,5 +262,5 @@
     }
 
     // show it on screen
-   surf->draw(canvas, 0, 0, nullptr);
+   surf->draw(canvas, 0, 0);
 }
diff --git a/gm/textblobgeometrychange.cpp b/gm/textblobgeometrychange.cpp
index ab561dc..122133c 100644
--- a/gm/textblobgeometrychange.cpp
+++ b/gm/textblobgeometrychange.cpp
@@ -65,7 +65,7 @@
         // (i.e., unknown pixel geometry)
         c->clear(0x00ffffff);
         c->drawTextBlob(blob, 10, 150, SkPaint());
-        surface->draw(canvas, 0, 0, nullptr);
+        surface->draw(canvas, 0, 0);
     }
 
 private:
diff --git a/gm/textblobrandomfont.cpp b/gm/textblobrandomfont.cpp
index f1afc91..2c3d430 100644
--- a/gm/textblobrandomfont.cpp
+++ b/gm/textblobrandomfont.cpp
@@ -146,7 +146,7 @@
         // Rotate in the surface canvas, not the final canvas, to avoid aliasing
         surfaceCanvas->rotate(-0.05f);
         surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
-        surface->draw(canvas, 0, 0, nullptr);
+        surface->draw(canvas, 0, 0);
         yOffset += stride;
 
         if (auto direct = context->asDirectContext()) {
diff --git a/gm/transparency.cpp b/gm/transparency.cpp
index 1083e3e..1c3f61a 100644
--- a/gm/transparency.cpp
+++ b/gm/transparency.cpp
@@ -74,6 +74,6 @@
         auto surface(SkSurface::MakeRasterN32Premul(256, 9));
         make_transparency(surface->getCanvas(), 256.0f, 9.0f);
         canvas->scale(7.0f, 120.0f);
-        surface->draw(canvas, 0, 0, nullptr);
+        surface->draw(canvas, 0, 0);
     }
 }
diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp
index 1945f18..44dee16 100644
--- a/gm/xfermodes3.cpp
+++ b/gm/xfermodes3.cpp
@@ -162,7 +162,7 @@
         if (nullptr == surface) {
             canvas->restore();
         } else {
-            surface->draw(canvas, 0, 0, nullptr);
+            surface->draw(canvas, 0, 0);
         }
 
         r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 50d592b..acb4590 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -620,11 +620,19 @@
         @param canvas  SkCanvas drawn into
         @param x       horizontal offset in SkCanvas
         @param y       vertical offset in SkCanvas
+        @param sampling what technique to use when sampling the surface pixels
         @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
                        and so on; or nullptr
 
         example: https://fiddle.skia.org/c/@Surface_draw
     */
+    void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
+              const SkPaint* paint);
+    void draw(SkCanvas* canvas, SkScalar x, SkScalar y) {
+        this->draw(canvas, x, y, SkSamplingOptions(), nullptr);
+    }
+
+    // DEPRECATED -- use explicit sampling options
     void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint);
 
     /** Copies SkSurface pixel address, row bytes, and SkImageInfo to SkPixmap, if address
diff --git a/samplecode/SampleFatBits.cpp b/samplecode/SampleFatBits.cpp
index 72dac8f..abc6707 100644
--- a/samplecode/SampleFatBits.cpp
+++ b/samplecode/SampleFatBits.cpp
@@ -172,7 +172,7 @@
         SkCanvas* canvas = fMaxSurface->getCanvas();
         canvas->save();
         canvas->concat(fMatrix);
-        fMinSurface->draw(canvas, 0, 0, nullptr);
+        fMinSurface->draw(canvas, 0, 0);
         canvas->restore();
 
         SkPaint paint;
@@ -284,7 +284,7 @@
     fMatrix.mapPoints(pts, 2);
     this->drawLineSkeleton(max, pts);
 
-    fMaxSurface->draw(canvas, 0, 0, nullptr);
+    fMaxSurface->draw(canvas, 0, 0);
 }
 
 void FatBits::drawRect(SkCanvas* canvas, SkPoint pts[2]) {
@@ -314,7 +314,7 @@
     r.setBounds(pts, 2);
     this->drawRectSkeleton(max, r);
 
-    fMaxSurface->draw(canvas, 0, 0, nullptr);
+    fMaxSurface->draw(canvas, 0, 0);
 }
 
 void FatBits::drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]) {
@@ -356,7 +356,7 @@
     fMatrix.mapPoints(pts, 3);
     this->drawTriangleSkeleton(max, pts);
 
-    fMaxSurface->draw(canvas, 0, 0, nullptr);
+    fMaxSurface->draw(canvas, 0, 0);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/samplecode/SampleQuadStroker.cpp b/samplecode/SampleQuadStroker.cpp
index 3652bea..bd98ad7 100644
--- a/samplecode/SampleQuadStroker.cpp
+++ b/samplecode/SampleQuadStroker.cpp
@@ -252,7 +252,7 @@
         SkCanvas* canvas = fMaxSurface->getCanvas();
         canvas->save();
         canvas->concat(fMatrix);
-        fMinSurface->draw(canvas, 0, 0, nullptr);
+        fMinSurface->draw(canvas, 0, 0);
         canvas->restore();
 
         SkPaint paint;
@@ -414,7 +414,7 @@
         if (drawText) {
             fMinSurface->getCanvas()->drawPath(path, paint);
             this->copyMinToMax();
-            fMaxSurface->draw(canvas, 0, 0, nullptr);
+            fMaxSurface->draw(canvas, 0, 0);
         }
         paint.setAntiAlias(true);
         paint.setStyle(SkPaint::kStroke_Style);
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 0d9a719..f18a2bb 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -11,6 +11,7 @@
 #include "include/gpu/GrBackendSurface.h"
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/core/SkImagePriv.h"
+#include "src/core/SkPaintPriv.h"
 #include "src/image/SkRescaleAndReadPixels.h"
 #include "src/image/SkSurface_Base.h"
 
@@ -59,10 +60,11 @@
     return false;
 }
 
-void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
+void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+                            const SkSamplingOptions& sampling, const SkPaint* paint) {
     auto image = this->makeImageSnapshot();
     if (image) {
-        canvas->drawImage(image, x, y, paint);
+        canvas->drawImage(image.get(), x, y, sampling, paint);
     }
 }
 
@@ -211,9 +213,14 @@
     return this->makeSurface(this->imageInfo().makeWH(width, height));
 }
 
-void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
+void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
                      const SkPaint* paint) {
-    return asSB(this)->onDraw(canvas, x, y, paint);
+    asSB(this)->onDraw(canvas, x, y, sampling, paint);
+}
+
+void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
+    SkSamplingOptions sampling(paint ? SkPaintPriv::GetFQ(*paint) : kNone_SkFilterQuality);
+    this->draw(canvas, x, y, sampling, paint);
 }
 
 bool SkSurface::peekPixels(SkPixmap* pmap) {
@@ -362,7 +369,7 @@
     }
     sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subsetOrNull) override { return nullptr; }
     void onWritePixels(const SkPixmap&, int x, int y) override {}
-    void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {}
+    void onDraw(SkCanvas*, SkScalar, SkScalar, const SkSamplingOptions&, const SkPaint*) override {}
     void onCopyOnWrite(ContentChangeMode) override {}
 };
 
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index 1925b56..b82d179 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -82,7 +82,7 @@
      *      image->unref();
      *  }
      */
-    virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+    virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkSamplingOptions&,const SkPaint*);
 
     /**
      * Called as a performance hint when the Surface is allowed to make it's contents
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index c8ed421..43ec497 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -268,7 +268,8 @@
     return true;
 }
 
-void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
+void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
+                           const SkSamplingOptions& sampling, const SkPaint* paint) {
     // If the dst is also GPU we try to not force a new image snapshot (by calling the base class
     // onDraw) since that may not always perform the copy-on-write optimization.
     auto tryDraw = [&] {
@@ -296,11 +297,11 @@
         image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(canvasContext), kNeedNewImageUniqueID,
                                         std::move(view), info.colorType(), info.alphaType(),
                                         info.refColorSpace());
-        canvas->drawImage(image, x, y, paint);
+        canvas->drawImage(image.get(), x, y, sampling, paint);
         return true;
     };
     if (!tryDraw()) {
-        INHERITED::onDraw(canvas, x, y, paint);
+        INHERITED::onDraw(canvas, x, y, sampling, paint);
     }
 }
 
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index 29d8a47..a7f8ec8 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -57,7 +57,8 @@
                  bool deleteSemaphoresAfterWait) override;
     bool onCharacterize(SkSurfaceCharacterization*) const override;
     bool onIsCompatible(const SkSurfaceCharacterization&) const override;
-    void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) override;
+    void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions&,
+                const SkPaint* paint) override;
     bool onDraw(sk_sp<const SkDeferredDisplayList>, SkIPoint offset) override;
 
     SkGpuDevice* getDevice() { return fDevice.get(); }
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index 77ebedb..8758eec 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -23,7 +23,7 @@
     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override;
     sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override;
     void onWritePixels(const SkPixmap&, int x, int y) override;
-    void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override;
+    void onDraw(SkCanvas*, SkScalar, SkScalar, const SkSamplingOptions&, const SkPaint*) override;
     void onCopyOnWrite(ContentChangeMode) override;
     void onRestoreBackingMutability() override;
 
@@ -83,8 +83,8 @@
 }
 
 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
-                              const SkPaint* paint) {
-    canvas->drawBitmap(fBitmap, x, y, paint);
+                              const SkSamplingOptions& sampling, const SkPaint* paint) {
+    canvas->drawImage(fBitmap.asImage().get(), x, y, sampling, paint);
 }
 
 sk_sp<SkImage> SkSurface_Raster::onNewImageSnapshot(const SkIRect* subset) {