Disable LCD text explicitly in SkPictureImageFilter::onFilterImage()

As an intermediate fix for
https://code.google.com/p/skia/issues/detail?id=3142, we can use a
non-public SkCanvas constructor and force-disable LCD text.

BUG=skia:3142
R=reed@google.com,senorblanco@google.com

Review URL: https://codereview.chromium.org/725243004
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index d172674..0685b6a8 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -1330,6 +1330,7 @@
     friend class SkSurface_Raster;  // needs getDevice()
     friend class SkRecorder;        // InitFlags
     friend class SkNoSaveLayerCanvas;   // InitFlags
+    friend class SkPictureImageFilter;  // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
 
     enum InitFlags {
         kDefault_InitFlags                  = 0,
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 9f17f81..23456d3 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -16,6 +16,7 @@
 class SkBitmap;
 class SkColorFilter;
 class SkBaseDevice;
+class SkSurfaceProps;
 struct SkIPoint;
 class GrFragmentProcessor;
 class GrTexture;
@@ -87,6 +88,7 @@
         virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
                                  const Context&,
                                  SkBitmap* result, SkIPoint* offset) = 0;
+        virtual const SkSurfaceProps* surfaceProps() const = 0;
     };
 
     /**
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a4e4df3..bf736e9 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1219,7 +1219,7 @@
         SkImageFilter* filter = paint->getImageFilter();
         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
         if (filter && !dstDev->canHandleImageFilter(filter)) {
-            SkDeviceImageFilterProxy proxy(dstDev);
+            SkDeviceImageFilterProxy proxy(dstDev, fProps);
             SkBitmap dst;
             SkIPoint offset = SkIPoint::Make(0, 0);
             const SkBitmap& src = srcDev->accessBitmap(false);
@@ -1261,7 +1261,7 @@
         SkImageFilter* filter = paint->getImageFilter();
         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
         if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
-            SkDeviceImageFilterProxy proxy(iter.fDevice);
+            SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
             SkBitmap dst;
             SkIPoint offset = SkIPoint::Make(0, 0);
             SkMatrix matrix = *iter.fMatrix;
diff --git a/src/core/SkDeviceImageFilterProxy.h b/src/core/SkDeviceImageFilterProxy.h
index d7ab646..621ff3f 100644
--- a/src/core/SkDeviceImageFilterProxy.h
+++ b/src/core/SkDeviceImageFilterProxy.h
@@ -8,11 +8,19 @@
 #ifndef SkDeviceImageFilterProxy_DEFINED
 #define SkDeviceImageFilterProxy_DEFINED
 
+#include "SkDevice.h"
 #include "SkImageFilter.h"
+#include "SkSurfaceProps.h"
 
 class SkDeviceImageFilterProxy : public SkImageFilter::Proxy {
 public:
-    SkDeviceImageFilterProxy(SkBaseDevice* device) : fDevice(device) {}
+    SkDeviceImageFilterProxy(SkBaseDevice* device, const SkSurfaceProps& props)
+        : fDevice(device)
+        , fProps(props.flags(),
+                 SkBaseDevice::CreateInfo::AdjustGeometry(SkImageInfo(),
+                                                          SkBaseDevice::kImageFilter_Usage,
+                                                          props.pixelGeometry()))
+    {}
 
     virtual SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE {
         SkBaseDevice::CreateInfo cinfo(SkImageInfo::MakeN32Premul(w, h),
@@ -29,8 +37,13 @@
         return fDevice->filterImage(filter, src, ctx, result, offset);
     }
 
+    virtual const SkSurfaceProps* surfaceProps() const SK_OVERRIDE {
+        return &fProps;
+    }
+
 private:
-    SkBaseDevice* fDevice;
+    SkBaseDevice*  fDevice;
+    const SkSurfaceProps fProps;
 };
 
 #endif
diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp
index 0c95b32..da5597d 100644
--- a/src/effects/SkPictureImageFilter.cpp
+++ b/src/effects/SkPictureImageFilter.cpp
@@ -9,6 +9,7 @@
 #include "SkDevice.h"
 #include "SkCanvas.h"
 #include "SkReadBuffer.h"
+#include "SkSurfaceProps.h"
 #include "SkWriteBuffer.h"
 #include "SkValidationUtils.h"
 
@@ -97,8 +98,10 @@
         return false;
     }
 
-    SkCanvas canvas(device.get());
-    SkPaint paint;
+    // Pass explicit surface props, as the simplified canvas constructor discards device properties.
+    // FIXME: switch back to the public constructor (and unfriend) after
+    //        https://code.google.com/p/skia/issues/detail?id=3142 is fixed.
+    SkCanvas canvas(device.get(), proxy->surfaceProps(), SkCanvas::kDefault_InitFlags);
 
     canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
     canvas.concat(ctx.ctm());
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 34964d5..ca79d0a 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1348,12 +1348,15 @@
     fContext->drawRectToRect(grPaint, dstRect, paintRect);
 }
 
-static bool filter_texture(SkBaseDevice* device, GrContext* context,
-                           GrTexture* texture, const SkImageFilter* filter,
-                           const SkImageFilter::Context& ctx,
-                           SkBitmap* result, SkIPoint* offset) {
+bool SkGpuDevice::filterTexture(GrContext* context, GrTexture* texture,
+                                const SkImageFilter* filter,
+                                const SkImageFilter::Context& ctx,
+                                SkBitmap* result, SkIPoint* offset) {
     SkASSERT(filter);
-    SkDeviceImageFilterProxy proxy(device);
+
+    // FIXME: plumb actual surface props such that we don't have to lie about the flags here
+    //        (https://code.google.com/p/skia/issues/detail?id=3148).
+    SkDeviceImageFilterProxy proxy(this, SkSurfaceProps(0, getLeakyProperties().pixelGeometry()));
 
     if (filter->canFilterImageGPU()) {
         // Save the render target and set it to NULL, so we don't accidentally draw to it in the
@@ -1395,8 +1398,8 @@
         // This cache is transient, and is freed (along with all its contained
         // textures) when it goes out of scope.
         SkImageFilter::Context ctx(matrix, clipBounds, cache);
-        if (filter_texture(this, fContext, texture, filter, ctx, &filteredBitmap,
-                           &offset)) {
+        if (this->filterTexture(fContext, texture, filter, ctx, &filteredBitmap,
+                                &offset)) {
             texture = (GrTexture*) filteredBitmap.getTexture();
             w = filteredBitmap.width();
             h = filteredBitmap.height();
@@ -1506,8 +1509,8 @@
         // textures) when it goes out of scope.
         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
         SkImageFilter::Context ctx(matrix, clipBounds, cache);
-        if (filter_texture(this, fContext, devTex, filter, ctx, &filteredBitmap,
-                           &offset)) {
+        if (this->filterTexture(fContext, devTex, filter, ctx, &filteredBitmap,
+                                &offset)) {
             devTex = filteredBitmap.getTexture();
             w = filteredBitmap.width();
             h = filteredBitmap.height();
@@ -1559,7 +1562,7 @@
     // must be pushed upstack.
     AutoBitmapTexture abt(fContext, src, NULL, &texture);
 
-    return filter_texture(this, fContext, texture, filter, ctx, result, offset);
+    return this->filterTexture(fContext, texture, filter, ctx, result, offset);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index ef31276..bb6cb48 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -202,6 +202,10 @@
 
     bool drawDashLine(const SkPoint pts[2], const SkPaint& paint);
 
+    bool filterTexture(GrContext*, GrTexture*, const SkImageFilter*,
+                       const SkImageFilter::Context&,
+                       SkBitmap* result, SkIPoint* offset);
+
     static SkPicture::AccelData::Key ComputeAccelDataKey();
 
     typedef SkBaseDevice INHERITED;
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index e032a81..6fefe49 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -235,7 +235,7 @@
     SkBitmap bitmap;
     bitmap.allocN32Pixels(100, 100);
     bitmap.eraseARGB(0, 0, 0, 0);
-    SkDeviceImageFilterProxy proxy(device);
+    SkDeviceImageFilterProxy proxy(device, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
 
     SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
@@ -315,7 +315,7 @@
     // Check that SkBlurImageFilter will accept a negative sigma, either in
     // the given arguments or after CTM application.
     int width = 32, height = 32;
-    SkDeviceImageFilterProxy proxy(device);
+    SkDeviceImageFilterProxy proxy(device, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
     SkScalar five = SkIntToScalar(5);
 
     SkAutoTUnref<SkBlurImageFilter> positiveFilter(
@@ -825,7 +825,7 @@
     SkBitmap bitmap;
     bitmap.allocN32Pixels(2, 2);
     SkBitmapDevice device(bitmap);
-    SkDeviceImageFilterProxy proxy(&device);
+    SkDeviceImageFilterProxy proxy(&device, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
     REPORTER_ASSERT(reporter, !imageFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
 }