More SkColorSpaceXformer caching

  * apply(SkColorFilter*)
  * apply(SkImage*)

Change-Id: I9b55632edd73dbbc5edb8b5ca9bb5bead1131260
Reviewed-on: https://skia-review.googlesource.com/21736
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/src/core/SkColorSpaceXformer.cpp b/src/core/SkColorSpaceXformer.cpp
index 71715ad..6b126a4 100644
--- a/src/core/SkColorSpaceXformer.cpp
+++ b/src/core/SkColorSpaceXformer.cpp
@@ -33,8 +33,29 @@
         : nullptr;
 }
 
+template <typename T>
+sk_sp<T> SkColorSpaceXformer::cachedApply(const T* src, Cache<T>* cache,
+                                          sk_sp<T> (*applyFunc)(const T*, SkColorSpaceXformer*)) {
+    if (!src) {
+        return nullptr;
+    }
+
+    auto key = sk_ref_sp(const_cast<T*>(src));
+    if (auto* xformed = cache->find(key)) {
+        return sk_ref_sp(xformed->get());
+    }
+
+    auto xformed = applyFunc(src, this);
+    cache->set(std::move(key), xformed);
+
+    return xformed;
+}
+
 sk_sp<SkImage> SkColorSpaceXformer::apply(const SkImage* src) {
-    return src->makeColorSpace(fDst, SkTransferFunctionBehavior::kIgnore);
+    return this->cachedApply<SkImage>(src, &fImageCache,
+        [](const SkImage* img, SkColorSpaceXformer* xformer) {
+            return img->makeColorSpace(xformer->fDst, SkTransferFunctionBehavior::kIgnore);
+        });
 }
 
 sk_sp<SkImage> SkColorSpaceXformer::apply(const SkBitmap& src) {
@@ -50,22 +71,17 @@
 }
 
 sk_sp<SkColorFilter> SkColorSpaceXformer::apply(const SkColorFilter* colorFilter) {
-    return colorFilter->makeColorSpace(this);
+    return this->cachedApply<SkColorFilter>(colorFilter, &fColorFilterCache,
+        [](const SkColorFilter* f, SkColorSpaceXformer* xformer) {
+            return f->makeColorSpace(xformer);
+        });
 }
 
 sk_sp<SkImageFilter> SkColorSpaceXformer::apply(const SkImageFilter* imageFilter) {
-    if (!imageFilter) {
-        return nullptr;
-    }
-
-    if (auto* xformedFilter = fFilterCache.find(imageFilter->fUniqueID)) {
-        return sk_ref_sp(xformedFilter->get());
-    }
-
-    auto xformedFilter = imageFilter->makeColorSpace(this);
-    fFilterCache.set(imageFilter->fUniqueID, xformedFilter);
-
-    return xformedFilter;
+    return this->cachedApply<SkImageFilter>(imageFilter, &fImageFilterCache,
+        [](const SkImageFilter* f, SkColorSpaceXformer* xformer) {
+            return f->makeColorSpace(xformer);
+        });
 }
 
 sk_sp<SkShader> SkColorSpaceXformer::apply(const SkShader* shader) {
diff --git a/src/core/SkColorSpaceXformer.h b/src/core/SkColorSpaceXformer.h
index fce8d03..15701c2 100644
--- a/src/core/SkColorSpaceXformer.h
+++ b/src/core/SkColorSpaceXformer.h
@@ -44,7 +44,15 @@
     sk_sp<SkColorSpace>                fDst;
     std::unique_ptr<SkColorSpaceXform> fFromSRGB;
 
-    SkTHashMap<uint32_t, sk_sp<SkImageFilter>> fFilterCache;
+    template <typename T>
+    using Cache = SkTHashMap<sk_sp<T>, sk_sp<T>>;
+
+    template <typename T>
+    sk_sp<T> cachedApply(const T*, Cache<T>*, sk_sp<T> (*)(const T*, SkColorSpaceXformer*));
+
+    Cache<SkImage      > fImageCache;
+    Cache<SkColorFilter> fColorFilterCache;
+    Cache<SkImageFilter> fImageFilterCache;
 };
 
 #endif