Add SkColorSpaceXform to the public API

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2390263002

Review-Url: https://codereview.chromium.org/2390263002
diff --git a/bench/ColorCodecBench.cpp b/bench/ColorCodecBench.cpp
index b2bb658..3b0ff67 100644
--- a/bench/ColorCodecBench.cpp
+++ b/bench/ColorCodecBench.cpp
@@ -101,9 +101,9 @@
     void* dst = fDst.get();
     void* src = fSrc.get();
     for (int y = 0; y < fSrcInfo.height(); y++) {
-        xform->apply(dst, (uint32_t*) src, fSrcInfo.width(),
-                     select_xform_format(fDstInfo.colorType()),
-                     SkColorSpaceXform::kRGBA_8888_ColorFormat, fDstInfo.alphaType());
+        SkAssertResult(xform->apply(select_xform_format(fDstInfo.colorType()), dst,
+                                    SkColorSpaceXform::kRGBA_8888_ColorFormat, src,
+                                    fSrcInfo.width(), fDstInfo.alphaType()));
         dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes());
         src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes());
     }
diff --git a/gm/colorspacexform.cpp b/gm/colorspacexform.cpp
index 34abdc4b..33320ba 100644
--- a/gm/colorspacexform.cpp
+++ b/gm/colorspacexform.cpp
@@ -41,9 +41,9 @@
         std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace.get(),
                                                                           dstSpace.get());
 
-        xform->apply(fWideGamutColors, colors, kNumColors,
-                     SkColorSpaceXform::kRGBA_F32_ColorFormat,
-                     SkColorSpaceXform::kBGRA_8888_ColorFormat, kOpaque_SkAlphaType);
+        xform->apply(SkColorSpaceXform::kRGBA_F32_ColorFormat, fWideGamutColors,
+                     SkColorSpaceXform::kBGRA_8888_ColorFormat, colors, kNumColors,
+                     kOpaque_SkAlphaType);
     }
 
     SkString onShortName() override {
diff --git a/include/core/SkColorSpaceXform.h b/include/core/SkColorSpaceXform.h
new file mode 100644
index 0000000..15b3d49
--- /dev/null
+++ b/include/core/SkColorSpaceXform.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpaceXform_DEFINED
+#define SkColorSpaceXform_DEFINED
+
+#include "SkImageInfo.h"
+
+class SkColorSpace;
+
+class SkColorSpaceXform : SkNoncopyable {
+public:
+
+    /**
+     *  Create an object to handle color space conversions.
+     *
+     *  @param srcSpace The encoded color space.
+     *  @param dstSpace The destination color space.
+     *
+     */
+    static std::unique_ptr<SkColorSpaceXform> New(SkColorSpace* srcSpace, SkColorSpace* dstSpace);
+
+    enum ColorFormat {
+        kRGBA_8888_ColorFormat,
+        kBGRA_8888_ColorFormat,
+        kRGBA_F16_ColorFormat,
+        kRGBA_F32_ColorFormat,
+    };
+
+    /**
+     *  Apply the color conversion to a |src| buffer, storing the output in the |dst| buffer.
+     *
+     *  F16 and F32 are only supported as dst color formats, and only when the dst color space
+     *  is linear.  This function will return false in unsupported cases.
+     *
+     *  @param dst            Stored in the format described by |dstColorFormat|
+     *  @param src            Stored in the format described by |srcColorFormat|
+     *  @param len            Number of pixels in the buffers
+     *  @param dstColorFormat Describes color format of |dst|
+     *  @param srcColorFormat Describes color format of |src|
+     *                        Must be kRGBA_8888 or kBGRA_8888
+     *  @param alphaType      Describes alpha properties of the |dst| (and |src|)
+     *                        kUnpremul preserves input alpha values
+     *                        kPremul   performs a premultiplication and also preserves alpha values
+     *                        kOpaque   optimization hint, |dst| alphas set to 1
+     *
+     */
+    bool apply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src, int count,
+               SkAlphaType alphaType) const {
+        return this->onApply(dstFormat, dst, srcFormat, src, count, alphaType);
+    }
+
+
+    virtual ~SkColorSpaceXform() {}
+
+protected:
+    virtual bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
+                         int count, SkAlphaType alphaType) const = 0;
+
+    SkColorSpaceXform() {}
+};
+
+#endif
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index b93def8..f210303 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -176,8 +176,8 @@
             SkASSERT(colorXform);
             uint64_t dstColor;
             uint32_t srcColor = colorPtr[fillIndex];
-            colorXform->apply(&dstColor, &srcColor, 1, select_xform_format(dstColorType),
-                              SkColorSpaceXform::kRGBA_8888_ColorFormat, alphaType);
+            SkAssertResult(colorXform->apply(select_xform_format(dstColorType), &dstColor,
+                    SkColorSpaceXform::kRGBA_8888_ColorFormat, &srcColor, 1, alphaType));
             return dstColor;
         }
         default:
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index f6c856e..92ab2bc 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -517,8 +517,9 @@
         }
 
         if (fColorXform) {
-            fColorXform->apply(dst, swizzleDst, dstWidth, select_xform_format(dstInfo.colorType()),
-                               SkColorSpaceXform::kRGBA_8888_ColorFormat, kOpaque_SkAlphaType);
+            SkAssertResult(fColorXform->apply(select_xform_format(dstInfo.colorType()), dst,
+                                              SkColorSpaceXform::kRGBA_8888_ColorFormat, swizzleDst,
+                                              dstWidth, kOpaque_SkAlphaType));
             dst = SkTAddOffset<void>(dst, rowBytes);
         }
 
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 55a2960..83032e6 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -272,8 +272,9 @@
                 SkColorSpaceXform::kBGRA_8888_ColorFormat;
         SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
                                                         this->getInfo().alphaType());
-        fColorXform->apply(colorTable, colorTable, numColors, xformColorFormat,
-                           SkColorSpaceXform::kRGBA_8888_ColorFormat, xformAlphaType);
+        SkAssertResult(fColorXform->apply(xformColorFormat, colorTable,
+                                          SkColorSpaceXform::kRGBA_8888_ColorFormat, colorTable,
+                                          numColors, xformAlphaType));
     }
 
     // Pad the color table with the last color in the table (or black) in the case that
@@ -441,13 +442,13 @@
             fSwizzler->swizzle(dst, (const uint8_t*) src);
             break;
         case kColorOnly_XformMode:
-            fColorXform->apply(dst, (const uint32_t*) src, fXformWidth, fXformColorFormat,
-                               srcColorFormat, fXformAlphaType);
+            SkAssertResult(fColorXform->apply(fXformColorFormat, dst, srcColorFormat, src,
+                                              fXformWidth, fXformAlphaType));
             break;
         case kSwizzleColor_XformMode:
             fSwizzler->swizzle(fColorXformSrcRow, (const uint8_t*) src);
-            fColorXform->apply(dst, fColorXformSrcRow, fXformWidth, fXformColorFormat,
-                               srcColorFormat, fXformAlphaType);
+            SkAssertResult(fColorXform->apply(fXformColorFormat, dst, srcColorFormat, fColorXformSrcRow,
+                                              fXformWidth, fXformAlphaType));
             break;
     }
 }
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
index 3e5ef2a..443a4a0 100644
--- a/src/codec/SkWebpCodec.cpp
+++ b/src/codec/SkWebpCodec.cpp
@@ -315,8 +315,9 @@
         uint32_t* src = (uint32_t*) config.output.u.RGBA.rgba;
         size_t srcRowBytes = config.output.u.RGBA.stride;
         for (int y = 0; y < rowsDecoded; y++) {
-            colorXform->apply(dst, src, dstInfo.width(), dstColorFormat,
-                              SkColorSpaceXform::kBGRA_8888_ColorFormat, xformAlphaType);
+            SkAssertResult(colorXform->apply(dstColorFormat, dst,
+                                             SkColorSpaceXform::kBGRA_8888_ColorFormat, src,
+                                             dstInfo.width(), xformAlphaType));
             dst = SkTAddOffset<void>(dst, rowBytes);
             src = SkTAddOffset<uint32_t>(src, srcRowBytes);
         }
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
index 6a67875..5abc476 100644
--- a/src/core/SkColorSpaceXform.cpp
+++ b/src/core/SkColorSpaceXform.cpp
@@ -8,7 +8,7 @@
 #include "SkColorPriv.h"
 #include "SkColorSpace_Base.h"
 #include "SkColorSpacePriv.h"
-#include "SkColorSpaceXform.h"
+#include "SkColorSpaceXform_Base.h"
 #include "SkHalf.h"
 #include "SkOpts.h"
 #include "SkSRGB.h"
@@ -584,8 +584,9 @@
     }
 }
 
-static void handle_color_lut(uint32_t* dst, const uint32_t* src, int len,
+static void handle_color_lut(uint32_t* dst, const void* vsrc, int len,
                              SkColorLookUpTable* colorLUT) {
+    const uint32_t* src = (const uint32_t*) vsrc;
     while (len-- > 0) {
         uint8_t r = (*src >>  0) & 0xFF,
                 g = (*src >>  8) & 0xFF,
@@ -1012,10 +1013,11 @@
 
 template <SkAlphaType kAlphaType,
           ColorSpaceMatch kCSM>
-static inline void do_color_xform(void* dst, const uint32_t* src, int len,
+static inline void do_color_xform(void* dst, const void* vsrc, int len,
                                   const float* const srcTables[3], const float matrix[16],
                                   const uint8_t* const dstTables[3], LoadFn load, Load1Fn load_1,
                                   StoreFn store, Store1Fn store_1, size_t sizeOfDstPixel) {
+    const uint32_t* src = (const uint32_t*) vsrc;
     Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT;
     load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT);
 
@@ -1117,7 +1119,7 @@
           DstFormat kDst,
           SkAlphaType kAlphaType,
           ColorSpaceMatch kCSM>
-static void color_xform_RGBA(void* dst, const uint32_t* src, int len,
+static void color_xform_RGBA(void* dst, const void* src, int len,
                              const float* const srcTables[3], const float matrix[16],
                              const uint8_t* const dstTables[3]) {
     LoadFn load;
@@ -1276,27 +1278,29 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
-static inline void apply_set_alpha(void* dst, const uint32_t* src, int len, SkAlphaType alphaType,
+static inline bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaType alphaType,
                                    const float* const srcTables[3], const float matrix[16],
                                    const uint8_t* const dstTables[3]) {
     switch (alphaType) {
         case kOpaque_SkAlphaType:
-            return color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM>
+            color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM>
                     (dst, src, len, srcTables, matrix, dstTables);
+            return true;
         case kPremul_SkAlphaType:
-            return color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM>
+            color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM>
                     (dst, src, len, srcTables, matrix, dstTables);
+            return true;
         case kUnpremul_SkAlphaType:
-            return color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM>
+            color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM>
                     (dst, src, len, srcTables, matrix, dstTables);
+            return true;
         default:
-            SkASSERT(false);
-            return;
+            return false;
     }
 }
 
 template <SrcGamma kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
-static inline void apply_set_src(void* dst, const uint32_t* src, int len, SkAlphaType alphaType,
+static inline bool apply_set_src(void* dst, const void* src, int len, SkAlphaType alphaType,
                                  const float* const srcTables[3], const float matrix[16],
                                  const uint8_t* const dstTables[3],
                                  SkColorSpaceXform::ColorFormat srcColorFormat) {
@@ -1320,15 +1324,14 @@
                             (dst, src, len, alphaType, srcTables, matrix, dstTables);
             }
         default:
-            SkASSERT(false);
+            return false;
     }
 }
 
 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
-void SkColorSpaceXform_Base<kSrc, kDst, kCSM>
-::apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat,
-        ColorFormat srcColorFormat, SkAlphaType alphaType)
-const
+bool SkColorSpaceXform_Base<kSrc, kDst, kCSM>
+::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src,
+          int len, SkAlphaType alphaType) const
 {
     if (kFull_ColorSpaceMatch == kCSM) {
         switch (alphaType) {
@@ -1339,16 +1342,17 @@
             default:
                 switch (dstColorFormat) {
                     case kRGBA_8888_ColorFormat:
-                        return (void) memcpy(dst, src, len * sizeof(uint32_t));
+                        memcpy(dst, src, len * sizeof(uint32_t));
+                        return true;
                     case kBGRA_8888_ColorFormat:
-                        return SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
+                        SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
+                        return true;
                     case kRGBA_F16_ColorFormat:
                     case kRGBA_F32_ColorFormat:
                         // There's still work to do to xform to linear floats.
                         break;
                     default:
-                        SkASSERT(false);
-                        return;
+                        return false;
                 }
         }
     }
@@ -1412,8 +1416,7 @@
                             (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
                              srcColorFormat);
                 default:
-                    SkASSERT(false);
-                    return;
+                    return false;
             }
         case kRGBA_F32_ColorFormat:
             switch (kDst) {
@@ -1422,12 +1425,10 @@
                             (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
                              srcColorFormat);
                 default:
-                    SkASSERT(false);
-                    return;
+                    return false;
             }
         default:
-            SkASSERT(false);
-            return;
+            return false;
     }
 }
 
diff --git a/src/core/SkColorSpaceXform.h b/src/core/SkColorSpaceXform.h
deleted file mode 100644
index bb99071..0000000
--- a/src/core/SkColorSpaceXform.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkColorSpaceXform_DEFINED
-#define SkColorSpaceXform_DEFINED
-
-#include "SkColorSpace.h"
-#include "SkColorSpace_Base.h"
-#include "SkImageInfo.h"
-
-class SkColorSpaceXform : SkNoncopyable {
-public:
-
-    /**
-     *  Create an object to handle color space conversions.
-     *
-     *  @param srcSpace The encoded color space.
-     *  @param dstSpace The destination color space.
-     *
-     */
-    static std::unique_ptr<SkColorSpaceXform> New(SkColorSpace* srcSpace, SkColorSpace* dstSpace);
-
-    enum ColorFormat : uint8_t {
-        kRGBA_8888_ColorFormat,
-        kBGRA_8888_ColorFormat,
-        kRGBA_F16_ColorFormat,
-        kRGBA_F32_ColorFormat,
-    };
-
-    /**
-     *  Apply the color conversion to a |src| buffer, storing the output in the |dst| buffer.
-     *
-     *  @param dst            Stored in the format described by |dstColorFormat|
-     *  @param src            Stored in the format described by |srcColorFormat|
-     *  @param len            Number of pixels in the buffers
-     *  @param dstColorFormat Describes color format of |dst|
-     *  @param srcColorFormat Describes color format of |src|
-     *                        Must be kRGBA_8888 or kBGRA_8888
-     *  @param alphaType      Describes alpha properties of the |dst| (and |src|)
-     *                        kUnpremul preserves input alpha values
-     *                        kPremul   performs a premultiplication and also preserves alpha values
-     *                        kOpaque   optimization hint, |dst| alphas set to 1
-     *
-     */
-    virtual void apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat,
-                       ColorFormat srcColorFormat, SkAlphaType alphaType) const = 0;
-
-    virtual ~SkColorSpaceXform() {}
-};
-
-enum SrcGamma {
-    kLinear_SrcGamma,
-    kTable_SrcGamma,
-};
-
-enum DstGamma {
-    kLinear_DstGamma,
-    kSRGB_DstGamma,
-    k2Dot2_DstGamma,
-    kTable_DstGamma,
-};
-
-enum ColorSpaceMatch {
-    kNone_ColorSpaceMatch,
-    kGamut_ColorSpaceMatch,
-    kFull_ColorSpaceMatch,
-};
-
-template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
-class SkColorSpaceXform_Base : public SkColorSpaceXform {
-public:
-
-    void apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat,
-               ColorFormat srcColorFormat, SkAlphaType alphaType) const override;
-
-    static constexpr int      kDstGammaTableSize = 1024;
-
-private:
-    SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst,
-                           SkColorSpace* dstSpace);
-
-    sk_sp<SkColorLookUpTable> fColorLUT;
-
-    // Contain pointers into storage or pointers into precomputed tables.
-    const float*              fSrcGammaTables[3];
-    const uint8_t*            fDstGammaTables[3];
-    SkAutoMalloc              fStorage;
-
-    float                     fSrcToDst[16];
-
-    friend class SkColorSpaceXform;
-    friend std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space);
-};
-
-// For testing.  Bypasses opts for when src and dst color spaces are equal.
-std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space);
-
-#endif
diff --git a/src/core/SkColorSpaceXform_Base.h b/src/core/SkColorSpaceXform_Base.h
new file mode 100644
index 0000000..02714ad
--- /dev/null
+++ b/src/core/SkColorSpaceXform_Base.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpaceXform_Base_DEFINED
+#define SkColorSpaceXform_Base_DEFINED
+
+#include "SkColorSpace.h"
+#include "SkColorSpace_Base.h"
+#include "SkColorSpaceXform.h"
+
+enum SrcGamma {
+    kLinear_SrcGamma,
+    kTable_SrcGamma,
+};
+
+enum DstGamma {
+    kLinear_DstGamma,
+    kSRGB_DstGamma,
+    k2Dot2_DstGamma,
+    kTable_DstGamma,
+};
+
+enum ColorSpaceMatch {
+    kNone_ColorSpaceMatch,
+    kGamut_ColorSpaceMatch,
+    kFull_ColorSpaceMatch,
+};
+
+template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
+class SkColorSpaceXform_Base : public SkColorSpaceXform {
+public:
+    static constexpr int kDstGammaTableSize = 1024;
+
+protected:
+    bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
+                 int count, SkAlphaType alphaType) const override;
+
+private:
+    SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst,
+                           SkColorSpace* dstSpace);
+
+    sk_sp<SkColorLookUpTable> fColorLUT;
+
+    // Contain pointers into storage or pointers into precomputed tables.
+    const float*              fSrcGammaTables[3];
+    const uint8_t*            fDstGammaTables[3];
+    SkAutoMalloc              fStorage;
+
+    float                     fSrcToDst[16];
+
+    friend class SkColorSpaceXform;
+    friend std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space);
+};
+
+// For testing.  Bypasses opts for when src and dst color spaces are equal.
+std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space);
+
+#endif
diff --git a/tests/ColorSpaceXformTest.cpp b/tests/ColorSpaceXformTest.cpp
index ed990fc..f792c6a 100644
--- a/tests/ColorSpaceXformTest.cpp
+++ b/tests/ColorSpaceXformTest.cpp
@@ -11,7 +11,7 @@
 #include "SkColorPriv.h"
 #include "SkColorSpace.h"
 #include "SkColorSpace_Base.h"
-#include "SkColorSpaceXform.h"
+#include "SkColorSpaceXform_Base.h"
 #include "Test.h"
 
 class ColorSpaceXformTest {
@@ -40,8 +40,10 @@
 
     // Create and perform an identity xform.
     std::unique_ptr<SkColorSpaceXform> xform = ColorSpaceXformTest::CreateIdentityXform(gammas);
-    xform->apply(dstPixels, srcPixels, width, select_xform_format(kN32_SkColorType),
-                 SkColorSpaceXform::kBGRA_8888_ColorFormat, kOpaque_SkAlphaType);
+    bool result = xform->apply(select_xform_format(kN32_SkColorType), dstPixels,
+                               SkColorSpaceXform::kBGRA_8888_ColorFormat, srcPixels, width,
+                               kOpaque_SkAlphaType);
+    REPORTER_ASSERT(r, result);
 
     // Since the src->dst matrix is the identity, and the gamma curves match,
     // the pixels should be unchanged.
@@ -182,6 +184,8 @@
     sk_sp<SkColorSpace> srcSpace = SkColorSpace::NewICC(iccData->bytes(), iccData->size());
     sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
     auto xform = SkColorSpaceXform::New(srcSpace.get(), dstSpace.get());
-    xform->apply(dst.get(), src.get(), len, SkColorSpaceXform::kRGBA_8888_ColorFormat,
-                 SkColorSpaceXform::kRGBA_8888_ColorFormat, kUnpremul_SkAlphaType);
+    bool result = xform->apply(SkColorSpaceXform::kRGBA_8888_ColorFormat, dst.get(),
+                               SkColorSpaceXform::kRGBA_8888_ColorFormat, src.get(), len,
+                               kUnpremul_SkAlphaType);
+    REPORTER_ASSERT(r, result);
 }