Add API to get canvas wrapped by SkPaintFilterCanvas

Implement SkAndroidFrameworkUtil::getBaseWrappedCanvas, which gets
the real canvas behind SkPaintFilterCanvas. This is useful, because
SkCanvas::drawDrawable works differently on a GPU backed canvas.

Test: Built and ran with Android
Bug: b/128792554
Change-Id: I5b75d42256d7a4efca987d55be2ce064c10fb4e7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/204442
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/include/android/SkAndroidFrameworkUtils.h b/include/android/SkAndroidFrameworkUtils.h
index 67b8492..a4a937e 100644
--- a/include/android/SkAndroidFrameworkUtils.h
+++ b/include/android/SkAndroidFrameworkUtils.h
@@ -40,6 +40,15 @@
     static sk_sp<SkSurface> getSurfaceFromCanvas(SkCanvas* canvas);
 
     static int SaveBehind(SkCanvas* canvas, const SkRect* subset);
+
+    /**
+     * Unrolls a chain of nested SkPaintFilterCanvas to return the base wrapped canvas.
+     *
+     *  @param  canvas A SkPaintFilterCanvas or any other SkCanvas subclass.
+     *
+     *  @return SkCanvas that was found in the innermost SkPaintFilterCanvas.
+     */
+    static SkCanvas* getBaseWrappedCanvas(SkCanvas* canvas);
 };
 
 #endif // SK_BUILD_FOR_ANDROID_ANDROID
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index d223e86..d66fd8d 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -31,6 +31,7 @@
 class SkGlyphRunBuilder;
 class SkImage;
 class SkImageFilter;
+class SkPaintFilterCanvas;
 class SkPath;
 class SkPicture;
 class SkPixmap;
@@ -2668,6 +2669,8 @@
      */
     bool androidFramework_isClipAA() const;
 
+    virtual SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const { return nullptr; }
+
     /**
      *  Keep track of the device clip bounds and if the matrix is scale-translate.  This allows
      *  us to do a fast quick reject in the common case.
diff --git a/include/utils/SkPaintFilterCanvas.h b/include/utils/SkPaintFilterCanvas.h
index 23019d3..a89c3ad 100644
--- a/include/utils/SkPaintFilterCanvas.h
+++ b/include/utils/SkPaintFilterCanvas.h
@@ -12,6 +12,8 @@
 #include "SkNWayCanvas.h"
 #include "SkTLazy.h"
 
+class SkAndroidFrameworkUtils;
+
 /** \class SkPaintFilterCanvas
 
     A utility proxy base class for implementing draw/paint filters.
@@ -119,6 +121,12 @@
     class AutoPaintFilter;
 
     SkCanvas* proxy() const { SkASSERT(fList.count() == 1); return fList[0]; }
+
+    SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const override {
+        return const_cast<SkPaintFilterCanvas*>(this);
+    }
+
+    friend class SkAndroidFrameworkUtils;
 };
 
 #endif
diff --git a/src/android/SkAndroidFrameworkUtils.cpp b/src/android/SkAndroidFrameworkUtils.cpp
index d0f4499..a13e8a2 100644
--- a/src/android/SkAndroidFrameworkUtils.cpp
+++ b/src/android/SkAndroidFrameworkUtils.cpp
@@ -8,6 +8,7 @@
 #include "SkAndroidFrameworkUtils.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
+#include "SkPaintFilterCanvas.h"
 #include "SkSurface_Base.h"
 
 #if SK_SUPPORT_GPU
@@ -67,5 +68,15 @@
 int SkAndroidFrameworkUtils::SaveBehind(SkCanvas* canvas, const SkRect* subset) {
     return canvas->only_axis_aligned_saveBehind(subset);
 }
+
+SkCanvas* SkAndroidFrameworkUtils::getBaseWrappedCanvas(SkCanvas* canvas) {
+    auto pfc = canvas->internal_private_asPaintFilterCanvas();
+    auto result = canvas;
+    while (pfc) {
+        result = pfc->proxy();
+        pfc = result->internal_private_asPaintFilterCanvas();
+    }
+    return result;
+}
 #endif // SK_BUILD_FOR_ANDROID_FRAMEWORK