Simplify SkCodecs' call to SkColorSpaceXform::apply

Most SkCodec subclasses did the following to apply their
SkColorSpaceXform:
  dstFormat = select_xform_format(dstInfo.colorType());
  srcFormat = select_xform_format(<something that doesn't change>);
  xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
                                      this->getInfo().alphaType());
  this->colorXform()->apply(dstFormat, dst, srcFormat, src, width,
                            xformAlphaType);

Consolidate the computation of these parameters into SkCodec and add a
new method to SkCodec that calls apply() with those parameters.

Add a SkColorSpaceXform::ColorFormat to SkCodec. This allows the new
method SkCodec::applyColorXform to supply the ColorFormat.

TBR=reed@google.com
(No change to public API.)

Change-Id: I8ea7ba4c0024be827a9f9359796c778744330f6e
Reviewed-on: https://skia-review.googlesource.com/18523
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 688cfaa..2cae6db 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -114,10 +114,12 @@
     return NewFromStream(new SkMemoryStream(data), reader);
 }
 
-SkCodec::SkCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
+SkCodec::SkCodec(int width, int height, const SkEncodedInfo& info,
+        XformFormat srcFormat, SkStream* stream,
         sk_sp<SkColorSpace> colorSpace, Origin origin)
     : fEncodedInfo(info)
     , fSrcInfo(info.makeImageInfo(width, height, std::move(colorSpace)))
+    , fSrcXformFormat(srcFormat)
     , fStream(stream)
     , fNeedsRewind(false)
     , fOrigin(origin)
@@ -126,10 +128,11 @@
     , fCurrScanline(-1)
 {}
 
-SkCodec::SkCodec(const SkEncodedInfo& info, const SkImageInfo& imageInfo, SkStream* stream,
-        Origin origin)
+SkCodec::SkCodec(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
+        XformFormat srcFormat, SkStream* stream, Origin origin)
     : fEncodedInfo(info)
     , fSrcInfo(imageInfo)
+    , fSrcXformFormat(srcFormat)
     , fStream(stream)
     , fNeedsRewind(false)
     , fOrigin(origin)
@@ -474,9 +477,29 @@
     }
 }
 
+static inline SkColorSpaceXform::ColorFormat select_xform_format_ct(SkColorType colorType) {
+    switch (colorType) {
+        case kRGBA_8888_SkColorType:
+            return SkColorSpaceXform::kRGBA_8888_ColorFormat;
+        case kBGRA_8888_SkColorType:
+            return SkColorSpaceXform::kBGRA_8888_ColorFormat;
+        case kRGB_565_SkColorType:
+        case kIndex_8_SkColorType:
+#ifdef SK_PMCOLOR_IS_RGBA
+            return SkColorSpaceXform::kRGBA_8888_ColorFormat;
+#else
+            return SkColorSpaceXform::kBGRA_8888_ColorFormat;
+#endif
+        default:
+            SkASSERT(false);
+            return SkColorSpaceXform::kRGBA_8888_ColorFormat;
+    }
+}
+
 bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo,
                                    SkTransferFunctionBehavior premulBehavior) {
     fColorXform = nullptr;
+    fXformOnDecode = false;
     bool needsColorCorrectPremul = needs_premul(dstInfo, fEncodedInfo) &&
                                    SkTransferFunctionBehavior::kRespect == premulBehavior;
     if (needs_color_xform(dstInfo, fSrcInfo, needsColorCorrectPremul)) {
@@ -485,13 +508,32 @@
         if (!fColorXform) {
             return false;
         }
-    } else {
-        fColorXform.reset();
+
+        // We will apply the color xform when reading the color table unless F16 is requested.
+        fXformOnDecode = SkEncodedInfo::kPalette_Color != fEncodedInfo.color()
+            || kRGBA_F16_SkColorType == dstInfo.colorType();
+        if (fXformOnDecode) {
+            fDstXformFormat = select_xform_format(dstInfo.colorType());
+        } else {
+            fDstXformFormat = select_xform_format_ct(dstInfo.colorType());
+        }
     }
 
     return true;
 }
 
+void SkCodec::applyColorXform(void* dst, const void* src, int count, SkAlphaType at) const {
+    SkASSERT(fColorXform);
+    SkAssertResult(fColorXform->apply(fDstXformFormat, dst,
+                                      fSrcXformFormat, src,
+                                      count, at));
+}
+
+void SkCodec::applyColorXform(void* dst, const void* src, int count) const {
+    auto alphaType = select_xform_alpha(fDstInfo.alphaType(), fSrcInfo.alphaType());
+    this->applyColorXform(dst, src, count, alphaType);
+}
+
 std::vector<SkCodec::FrameInfo> SkCodec::getFrameInfo() {
     const int frameCount = this->getFrameCount();
     SkASSERT(frameCount >= 0);