Add SkTransferFunctionBehavior flag: Use in codec and encoder

This is a step towards removing the non-linear blending flag from
SkColorSpace.  The flag on SkColorSpace used to control the premul
behavior - now it is controlled by this option.

BUG=skia:

Change-Id: Ia29bd8c2b0596a93c6aa14332dcd9bd39e388a90
Reviewed-on: https://skia-review.googlesource.com/10008
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index 76ad0f9..3a4d2b3 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -179,18 +179,15 @@
             if (encodedSpace->isNumericalTransferFn(&fn)) {
                 // Leave the pixels in the encoded color space.  Color space conversion
                 // will be handled after decode time.
-                return as_CSB(encodedSpace)->makeWithNonLinearBlending();
+                return sk_ref_sp(encodedSpace);
             }
 
             if (is_wide_gamut(encodedSpace)) {
                 return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                             SkColorSpace::kDCIP3_D65_Gamut,
-                                             SkColorSpace::kNonLinearBlending_ColorSpaceFlag);
+                                             SkColorSpace::kDCIP3_D65_Gamut);
             }
 
-            return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                         SkColorSpace::kSRGB_Gamut,
-                                         SkColorSpace::kNonLinearBlending_ColorSpaceFlag);
+            return SkColorSpace::MakeSRGB();
         }
         case kRGBA_F16_SkColorType:
             return SkColorSpace::MakeSRGBLinear();
diff --git a/src/codec/SkBmpCodec.cpp b/src/codec/SkBmpCodec.cpp
index 354bee6..3d3782b 100644
--- a/src/codec/SkBmpCodec.cpp
+++ b/src/codec/SkBmpCodec.cpp
@@ -615,7 +615,9 @@
 
 SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
         const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         return kInvalidConversion;
     }
 
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index e9eeb45..5bdb3e2 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -9,7 +9,7 @@
 #include "SkCodec.h"
 #include "SkCodecPriv.h"
 #include "SkColorSpace.h"
-#include "SkColorSpaceXform.h"
+#include "SkColorSpaceXform_Base.h"
 #include "SkData.h"
 #include "SkGifCodec.h"
 #include "SkHalf.h"
@@ -474,11 +474,14 @@
     }
 }
 
-bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo) {
+bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo,
+                                   SkTransferFunctionBehavior premulBehavior) {
     fColorXform = nullptr;
-    bool needsPremul = needs_premul(dstInfo, fEncodedInfo);
-    if (needs_color_xform(dstInfo, fSrcInfo, needsPremul)) {
-        fColorXform = SkColorSpaceXform::New(fSrcInfo.colorSpace(), dstInfo.colorSpace());
+    bool needsColorCorrectPremul = needs_premul(dstInfo, fEncodedInfo) &&
+                                   SkTransferFunctionBehavior::kRespect == premulBehavior;
+    if (needs_color_xform(dstInfo, fSrcInfo, needsColorCorrectPremul)) {
+        fColorXform = SkColorSpaceXform_Base::New(fSrcInfo.colorSpace(), dstInfo.colorSpace(),
+                                                  premulBehavior);
         if (!fColorXform) {
             return false;
         }
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index 026120f..5bf0272 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -301,7 +301,7 @@
 }
 
 static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo,
-                                     bool needsPremul) {
+                                     bool needsColorCorrectPremul) {
     // We never perform a color xform in legacy mode.
     if (!dstInfo.colorSpace()) {
         return false;
@@ -314,10 +314,6 @@
     bool srcDstNotEqual =
             !SkColorSpace_Base::EqualsIgnoreFlags(srcInfo.colorSpace(), dstInfo.colorSpace());
 
-    // We provide the option for both legacy premuls and color correct premuls.
-    bool needsColorCorrectPremul =
-            needsPremul && !as_CSB(dstInfo.colorSpace())->nonLinearBlending();
-
     return needsColorCorrectPremul || isF16 || srcDstNotEqual;
 }
 
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp
index 2903717..a70f7be 100644
--- a/src/codec/SkGifCodec.cpp
+++ b/src/codec/SkGifCodec.cpp
@@ -183,7 +183,9 @@
 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
         int* inputColorCount, const Options& opts) {
     // Check for valid input parameters
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, opts.fPremulBehavior))
+    {
         return gif_error("Cannot convert input type to output type.\n", kInvalidConversion);
     }
 
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index 624bc25..213c587 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -583,7 +583,7 @@
         return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
     }
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return kInvalidConversion;
     }
 
@@ -692,7 +692,7 @@
         return kInvalidInput;
     }
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return kInvalidConversion;
     }
 
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index b6258ab..901f55f 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -1093,7 +1093,7 @@
     // interlaced scanline decoder may need to rewind.
     fSwizzler.reset(nullptr);
 
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
         return false;
     }
 
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index 97baa9c..272f737 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -690,7 +690,9 @@
                                         size_t dstRowBytes, const Options& options,
                                         SkPMColor ctable[], int* ctableCount,
                                         int* rowsDecoded) {
-    if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         SkCodecPrintf("Error: cannot convert input type to output type.\n");
         return kInvalidConversion;
     }
diff --git a/src/codec/SkSampledCodec.cpp b/src/codec/SkSampledCodec.cpp
index 1d9953b..2b6483b 100644
--- a/src/codec/SkSampledCodec.cpp
+++ b/src/codec/SkSampledCodec.cpp
@@ -75,6 +75,7 @@
     // Create an Options struct for the codec.
     SkCodec::Options codecOptions;
     codecOptions.fZeroInitialized = options.fZeroInitialized;
+    codecOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
 
     SkIRect* subset = options.fSubset;
     if (!subset || subset->size() == this->codec()->getInfo().dimensions()) {
@@ -171,6 +172,7 @@
     // Create options struct for the codec.
     SkCodec::Options sampledOptions;
     sampledOptions.fZeroInitialized = options.fZeroInitialized;
+    sampledOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
 
     // FIXME: This was already called by onGetAndroidPixels. Can we reduce that?
     int sampleSize = options.fSampleSize;
diff --git a/src/codec/SkWebpAdapterCodec.cpp b/src/codec/SkWebpAdapterCodec.cpp
index 5aefe5d..cf1f0e0 100644
--- a/src/codec/SkWebpAdapterCodec.cpp
+++ b/src/codec/SkWebpAdapterCodec.cpp
@@ -40,6 +40,7 @@
     SkCodec::Options codecOptions;
     codecOptions.fZeroInitialized = options.fZeroInitialized;
     codecOptions.fSubset = options.fSubset;
+    codecOptions.fPremulBehavior = SkTransferFunctionBehavior::kIgnore;
     return this->codec()->getPixels(info, pixels, rowBytes, &codecOptions, options.fColorPtr,
             options.fColorCount);
 }
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
index c602fcd..ae8668b 100644
--- a/src/codec/SkWebpCodec.cpp
+++ b/src/codec/SkWebpCodec.cpp
@@ -194,11 +194,9 @@
 SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
                                          const Options& options, SkPMColor*, int*,
                                          int* rowsDecodedPtr) {
-    if (!conversion_possible(dstInfo, this->getInfo())) {
-        return kInvalidConversion;
-    }
-
-    if (!this->initializeColorXform(dstInfo)) {
+    if (!conversion_possible(dstInfo, this->getInfo()) ||
+        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
+    {
         return kInvalidConversion;
     }