Reland "Add SkColorSpace factory from 3x3 row-major gamut and transfer function"

Moved named common transfer functions and gamuts to constexpr values in
SkColorSpace.h, in SkNamedTransferFn and SkNamedGamut namespaces.

Converted nearly all SkColorSpace::MakeRGB calls within Skia to use the
new factory with the named values. Multiple clients want a way to
extract named transfer function and gamut - this still doesn't provide
that, but this may be a better path forward for honestly advertising how
SkColorSpace works internally.

Originally landed as:
https://skia.googlesource.com/skia/+/a9549ab31630fc244094e6f1692371cbaf87f666

Re-landing with a new serialization format, but maintaining ability to
load old serialized color spaces, for SKP compatibility.

Bug: skia:
Change-Id: Ib84a6e1cd5d7d9816175773fdbaff2ca32658667
Reviewed-on: https://skia-review.googlesource.com/c/181176
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index 581640f..d741d6d 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -164,9 +164,8 @@
     switch (outputColorType) {
         case kRGBA_8888_SkColorType:
         case kBGRA_8888_SkColorType: {
-            // If |prefColorSpace| is supported, choose it.
-            SkColorSpaceTransferFn fn;
-            if (prefColorSpace && prefColorSpace->isNumericalTransferFn(&fn)) {
+            // If |prefColorSpace| is supplied, choose it.
+            if (prefColorSpace) {
                 return prefColorSpace;
             }
 
@@ -179,8 +178,7 @@
                 }
 
                 if (is_wide_gamut(*encodedProfile)) {
-                    return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                                 SkColorSpace::kDCIP3_D65_Gamut);
+                    return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
                 }
             }
 
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index fb7efb9..a8ec40b 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -612,17 +612,6 @@
     bool fIsXtransImage;
 };
 
-static constexpr skcms_Matrix3x3 gAdobe_RGB_to_XYZD50 = {{
-    // ICC fixed-point (16.16) repesentation of:
-    // 0.60974, 0.20528, 0.14919,
-    // 0.31111, 0.62567, 0.06322,
-    // 0.01947, 0.06087, 0.74457,
-    { SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) }, // Rx, Gx, Bx
-    { SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) }, // Ry, Gy, By
-    { SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) }, // Rz, Gz, Bz
-}};
-
-
 /*
  * Tries to handle the image with PIEX. If PIEX returns kOk and finds the preview image, create a
  * SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr. In other cases,
@@ -649,12 +638,10 @@
 
         std::unique_ptr<SkEncodedInfo::ICCProfile> profile;
         if (imageData.color_space == ::piex::PreviewImageData::kAdobeRgb) {
-            constexpr skcms_TransferFunction twoDotTwo =
-                    { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
             skcms_ICCProfile skcmsProfile;
             skcms_Init(&skcmsProfile);
-            skcms_SetTransferFunction(&skcmsProfile, &twoDotTwo);
-            skcms_SetXYZD50(&skcmsProfile, &gAdobe_RGB_to_XYZD50);
+            skcms_SetTransferFunction(&skcmsProfile, &SkNamedTransferFn::k2Dot2);
+            skcms_SetXYZD50(&skcmsProfile, &SkNamedGamut::kAdobeRGB);
             profile = SkEncodedInfo::ICCProfile::Make(skcmsProfile);
         }
 
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 66ddaf4..f54f2ec 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -20,6 +20,10 @@
     return true;
 }
 
+bool SkColorSpacePrimaries::toXYZD50(skcms_Matrix3x3* toXYZ_D50) const {
+    return skcms_PrimariesToXYZD50(fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY, toXYZ_D50);
+}
+
 static bool is_3x3(const SkMatrix44& m44) {
     return m44.getFloat(0, 3) == 0.0f
         && m44.getFloat(1, 3) == 0.0f
@@ -57,9 +61,9 @@
     fToXYZD50Hash = SkOpts::hash_fn(fToXYZD50_3x3, 9*sizeof(float), 0);
 
     switch (fGammaNamed) {
-        case kSRGB_SkGammaNamed:        transferFn = &  gSRGB_TransferFn.fG; break;
-        case k2Dot2Curve_SkGammaNamed:  transferFn = & g2Dot2_TransferFn.fG; break;
-        case kLinear_SkGammaNamed:      transferFn = &gLinear_TransferFn.fG; break;
+        case kSRGB_SkGammaNamed:        transferFn = &  SkNamedTransferFn::kSRGB.g; break;
+        case k2Dot2Curve_SkGammaNamed:  transferFn = & SkNamedTransferFn::k2Dot2.g; break;
+        case kLinear_SkGammaNamed:      transferFn = &SkNamedTransferFn::kLinear.g; break;
         case kNonStandard_SkGammaNamed:                                      break;
     }
     memcpy(fTransferFn, transferFn, 7*sizeof(float));
@@ -73,12 +77,12 @@
     }
     switch (gammaNamed) {
         case kSRGB_SkGammaNamed:
-            if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
+            if (xyz_almost_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0])) {
                 return SkColorSpace::MakeSRGB();
             }
             break;
         case kLinear_SkGammaNamed:
-            if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
+            if (xyz_almost_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0])) {
                 return SkColorSpace::MakeSRGBLinear();
             }
             break;
@@ -136,6 +140,16 @@
     return SkColorSpace::MakeRGB(coeffs, toXYZD50);
 }
 
+sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const skcms_TransferFunction& transferFn,
+                                          const skcms_Matrix3x3& toXYZ) {
+    SkMatrix44 toXYZD50;
+    toXYZD50.set3x3RowMajorf(&toXYZ.vals[0][0]);
+    SkColorSpaceTransferFn tf;
+    memcpy(&tf, &transferFn, sizeof(tf));
+    // Going through this old path makes sure we classify transferFn as an SkGammaNamed
+    return SkColorSpace::MakeRGB(tf, toXYZD50);
+}
+
 class SkColorSpaceSingletonFactory {
 public:
     static SkColorSpace* Make(SkGammaNamed gamma, const float to_xyz[9]) {
@@ -148,12 +162,12 @@
 
 SkColorSpace* sk_srgb_singleton() {
     static SkColorSpace* cs = SkColorSpaceSingletonFactory::Make(kSRGB_SkGammaNamed,
-                                                                 gSRGB_toXYZD50);
+                                                                 &SkNamedGamut::kSRGB.vals[0][0]);
     return cs;
 }
 SkColorSpace* sk_srgb_linear_singleton() {
     static SkColorSpace* cs = SkColorSpaceSingletonFactory::Make(kLinear_SkGammaNamed,
-                                                                 gSRGB_toXYZD50);
+                                                                 &SkNamedGamut::kSRGB.vals[0][0]);
     return cs;
 }
 
@@ -196,6 +210,11 @@
     return true;
 }
 
+bool SkColorSpace::isNumericalTransferFn(skcms_TransferFunction* coeffs) const {
+    this->transferFn(&coeffs->g);
+    return true;
+}
+
 void SkColorSpace::transferFn(float gabcdef[7]) const {
     memcpy(gabcdef, &fTransferFn, 7*sizeof(float));
 }
@@ -210,6 +229,10 @@
     return true;
 }
 
+bool SkColorSpace::toXYZD50(skcms_Matrix3x3* toXYZD50) const {
+    memcpy(toXYZD50, fToXYZD50_3x3, 9*sizeof(float));
+    return true;
+}
 
 void SkColorSpace::gamutTransformTo(const SkColorSpace* dst, float src_to_dst[9]) const {
     dst->computeLazyDstFields();
@@ -314,134 +337,47 @@
 
 enum Version {
     k0_Version, // Initial version, header + flags for matrix and profile
+    k1_Version, // Simple header (version tag) + 16 floats
+
+    kCurrent_Version = k1_Version,
 };
 
 enum NamedColorSpace {
     kSRGB_NamedColorSpace,
-    // No longer a singleton, preserved to support reading data from branches m65 and older
     kAdobeRGB_NamedColorSpace,
     kSRGBLinear_NamedColorSpace,
 };
 
 struct ColorSpaceHeader {
-    /**
-     *  It is only valid to set zero or one flags.
-     *  Setting multiple flags is invalid.
-     */
-
-    /**
-     *  If kMatrix_Flag is set, we will write 12 floats after the header.
-     */
+    // Flag values, only used by old (k0_Version) serialization
     static constexpr uint8_t kMatrix_Flag     = 1 << 0;
-
-    /**
-     *  If kICC_Flag is set, we will write an ICC profile after the header.
-     *  The ICC profile will be written as a uint32 size, followed immediately
-     *  by the data (padded to 4 bytes).
-     *  DEPRECATED / UNUSED
-     */
     static constexpr uint8_t kICC_Flag        = 1 << 1;
-
-    /**
-     *  If kTransferFn_Flag is set, we will write 19 floats after the header.
-     *  The first seven represent the transfer fn, and the next twelve are the
-     *  matrix.
-     */
     static constexpr uint8_t kTransferFn_Flag = 1 << 3;
 
-    static ColorSpaceHeader Pack(Version version, uint8_t named, uint8_t gammaNamed, uint8_t flags)
-    {
-        ColorSpaceHeader header;
+    uint8_t fVersion = kCurrent_Version;
 
-        SkASSERT(k0_Version == version);
-        header.fVersion = (uint8_t) version;
-
-        SkASSERT(named <= kSRGBLinear_NamedColorSpace);
-        header.fNamed = (uint8_t) named;
-
-        SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
-        header.fGammaNamed = (uint8_t) gammaNamed;
-
-        SkASSERT(flags <= kTransferFn_Flag);
-        header.fFlags = flags;
-        return header;
-    }
-
-    uint8_t fVersion;            // Always zero
-    uint8_t fNamed;              // Must be a SkColorSpace::Named
-    uint8_t fGammaNamed;         // Must be a SkGammaNamed
-    uint8_t fFlags;
+    // Other fields are only used by k0_Version. Could be re-purposed in future versions.
+    uint8_t fNamed      = 0;
+    uint8_t fGammaNamed = 0;
+    uint8_t fFlags      = 0;
 };
 
 size_t SkColorSpace::writeToMemory(void* memory) const {
-    // If we have a named profile, only write the enum.
-    const SkGammaNamed gammaNamed = this->gammaNamed();
-    if (this == sk_srgb_singleton()) {
-        if (memory) {
-            *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
-                    k0_Version, kSRGB_NamedColorSpace, gammaNamed, 0);
-        }
-        return sizeof(ColorSpaceHeader);
-    } else if (this == sk_srgb_linear_singleton()) {
-        if (memory) {
-            *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
-                    k0_Version, kSRGBLinear_NamedColorSpace, gammaNamed, 0);
-        }
-        return sizeof(ColorSpaceHeader);
+    if (memory) {
+        *((ColorSpaceHeader*) memory) = ColorSpaceHeader();
+        memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
+
+        memcpy(memory, fTransferFn, 7 * sizeof(float));
+        memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
+
+        memcpy(memory, fToXYZD50_3x3, 9 * sizeof(float));
     }
 
-    // If we have a named gamma, write the enum and the matrix.
-    switch (gammaNamed) {
-        case kSRGB_SkGammaNamed:
-        case k2Dot2Curve_SkGammaNamed:
-        case kLinear_SkGammaNamed: {
-            if (memory) {
-                *((ColorSpaceHeader*) memory) =
-                        ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
-                                                ColorSpaceHeader::kMatrix_Flag);
-                memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
-                SkMatrix44 m44;
-                this->toXYZD50(&m44);
-                m44.as3x4RowMajorf((float*) memory);
-            }
-            return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
-        }
-        default: {
-            SkColorSpaceTransferFn transferFn;
-            SkAssertResult(this->isNumericalTransferFn(&transferFn));
-
-            if (memory) {
-                *((ColorSpaceHeader*) memory) =
-                        ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
-                                                ColorSpaceHeader::kTransferFn_Flag);
-                memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
-
-                *(((float*) memory) + 0) = transferFn.fA;
-                *(((float*) memory) + 1) = transferFn.fB;
-                *(((float*) memory) + 2) = transferFn.fC;
-                *(((float*) memory) + 3) = transferFn.fD;
-                *(((float*) memory) + 4) = transferFn.fE;
-                *(((float*) memory) + 5) = transferFn.fF;
-                *(((float*) memory) + 6) = transferFn.fG;
-                memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
-
-                SkMatrix44 m44;
-                this->toXYZD50(&m44);
-                m44.as3x4RowMajorf((float*) memory);
-            }
-
-            return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
-        }
-    }
+    return sizeof(ColorSpaceHeader) + 16 * sizeof(float);
 }
 
 sk_sp<SkData> SkColorSpace::serialize() const {
-    size_t size = this->writeToMemory(nullptr);
-    if (0 == size) {
-        return nullptr;
-    }
-
-    sk_sp<SkData> data = SkData::MakeUninitialized(size);
+    sk_sp<SkData> data = SkData::MakeUninitialized(this->writeToMemory(nullptr));
     this->writeToMemory(data->writable_data());
     return data;
 }
@@ -454,59 +390,81 @@
     ColorSpaceHeader header = *((const ColorSpaceHeader*) data);
     data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader));
     length -= sizeof(ColorSpaceHeader);
-    if (0 == header.fFlags) {
-        switch ((NamedColorSpace)header.fNamed) {
-            case kSRGB_NamedColorSpace:
-                return SkColorSpace::MakeSRGB();
-            case kSRGBLinear_NamedColorSpace:
-                return SkColorSpace::MakeSRGBLinear();
-            case kAdobeRGB_NamedColorSpace:
-                return SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
-        }
-    }
-
-    switch ((SkGammaNamed) header.fGammaNamed) {
-        case kSRGB_SkGammaNamed:
-        case k2Dot2Curve_SkGammaNamed:
-        case kLinear_SkGammaNamed: {
-            if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 * sizeof(float)) {
-                return nullptr;
-            }
-
-            SkMatrix44 toXYZ;
-            toXYZ.set3x4RowMajorf((const float*) data);
-            return SkColorSpace::MakeRGB((SkGammaNamed) header.fGammaNamed, toXYZ);
-        }
-        default:
-            break;
-    }
-
-    switch (header.fFlags) {
-        case ColorSpaceHeader::kICC_Flag: {
-            // Deprecated and unsupported code path
+    if (k1_Version == header.fVersion) {
+        if (length < 16 * sizeof(float)) {
             return nullptr;
         }
-        case ColorSpaceHeader::kTransferFn_Flag: {
-            if (length < 19 * sizeof(float)) {
+
+        skcms_TransferFunction transferFn;
+        memcpy(&transferFn, data, 7 * sizeof(float));
+        data = SkTAddOffset<const void>(data, 7 * sizeof(float));
+
+        skcms_Matrix3x3 toXYZ;
+        memcpy(&toXYZ, data, 9 * sizeof(float));
+        return SkColorSpace::MakeRGB(transferFn, toXYZ);
+    } else if (k0_Version == header.fVersion) {
+        if (0 == header.fFlags) {
+            switch ((NamedColorSpace)header.fNamed) {
+                case kSRGB_NamedColorSpace:
+                    return SkColorSpace::MakeSRGB();
+                case kSRGBLinear_NamedColorSpace:
+                    return SkColorSpace::MakeSRGBLinear();
+                case kAdobeRGB_NamedColorSpace:
+                    return SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2,
+                                                 SkNamedGamut::kAdobeRGB);
+            }
+        }
+
+        switch ((SkGammaNamed) header.fGammaNamed) {
+            case kSRGB_SkGammaNamed:
+            case k2Dot2Curve_SkGammaNamed:
+            case kLinear_SkGammaNamed: {
+                if (ColorSpaceHeader::kMatrix_Flag != header.fFlags ||
+                    length < 12 * sizeof(float)) {
+                    return nullptr;
+                }
+
+                SkMatrix44 toXYZ;
+                toXYZ.set3x4RowMajorf((const float*) data);
+                return SkColorSpace::MakeRGB((SkGammaNamed) header.fGammaNamed, toXYZ);
+            }
+            default:
+                break;
+        }
+
+        switch (header.fFlags) {
+            case ColorSpaceHeader::kICC_Flag: {
+                // Deprecated and unsupported code path
                 return nullptr;
             }
+            case ColorSpaceHeader::kTransferFn_Flag: {
+                if (length < 19 * sizeof(float)) {
+                    return nullptr;
+                }
 
-            SkColorSpaceTransferFn transferFn;
-            transferFn.fA = *(((const float*) data) + 0);
-            transferFn.fB = *(((const float*) data) + 1);
-            transferFn.fC = *(((const float*) data) + 2);
-            transferFn.fD = *(((const float*) data) + 3);
-            transferFn.fE = *(((const float*) data) + 4);
-            transferFn.fF = *(((const float*) data) + 5);
-            transferFn.fG = *(((const float*) data) + 6);
-            data = SkTAddOffset<const void>(data, 7 * sizeof(float));
+                // Version 0 TF is in abcdefg order
+                skcms_TransferFunction transferFn;
+                transferFn.a = *(((const float*) data) + 0);
+                transferFn.b = *(((const float*) data) + 1);
+                transferFn.c = *(((const float*) data) + 2);
+                transferFn.d = *(((const float*) data) + 3);
+                transferFn.e = *(((const float*) data) + 4);
+                transferFn.f = *(((const float*) data) + 5);
+                transferFn.g = *(((const float*) data) + 6);
+                data = SkTAddOffset<const void>(data, 7 * sizeof(float));
 
-            SkMatrix44 toXYZ;
-            toXYZ.set3x4RowMajorf((const float*) data);
-            return SkColorSpace::MakeRGB(transferFn, toXYZ);
+                // Version 0 matrix is row-major 3x4
+                skcms_Matrix3x3 toXYZ;
+                memcpy(&toXYZ.vals[0][0], (const float*)data + 0, 3 * sizeof(float));
+                memcpy(&toXYZ.vals[1][0], (const float*)data + 4, 3 * sizeof(float));
+                memcpy(&toXYZ.vals[2][0], (const float*)data + 8, 3 * sizeof(float));
+                return SkColorSpace::MakeRGB(transferFn, toXYZ);
+            }
+            default:
+                return nullptr;
         }
-        default:
-            return nullptr;
+    } else {
+        return nullptr;
     }
 }
 
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpacePriv.h
index 4d93d59..298b932 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpacePriv.h
@@ -14,70 +14,26 @@
 
 #define SkColorSpacePrintf(...)
 
-static constexpr float gSRGB_toXYZD50[] {
-    // These are taken from skcms, and there originally from 16-bit fixed point.
-    // For best results, please keep them exactly in sync with skcms.
-    0.436065674f, 0.385147095f, 0.143066406f,
-    0.222488403f, 0.716873169f, 0.060607910f,
-    0.013916016f, 0.097076416f, 0.714096069f,
-};
-
-static constexpr float gAdobeRGB_toXYZD50[] {
-    // ICC fixed-point (16.16) repesentation of:
-    // 0.60974, 0.20528, 0.14919,
-    // 0.31111, 0.62567, 0.06322,
-    // 0.01947, 0.06087, 0.74457,
-    SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631), // Rx, Gx, Bx
-    SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f), // Ry, Gy, By
-    SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c), // Rz, Gz, Bz
-};
-
-static constexpr float gDCIP3_toXYZD50[] {
-    0.515102f,   0.291965f,  0.157153f,  // Rx, Gx, Bx
-    0.241182f,   0.692236f,  0.0665819f, // Ry, Gy, By
-   -0.00104941f, 0.0418818f, 0.784378f,  // Rz, Gz, Bz
-};
-
-static constexpr float gRec2020_toXYZD50[] {
-    0.673459f,   0.165661f,  0.125100f,  // Rx, Gx, Bx
-    0.279033f,   0.675338f,  0.0456288f, // Ry, Gy, By
-   -0.00193139f, 0.0299794f, 0.797162f,  // Rz, Gz, Bz
-};
-
 // A gamut narrower than sRGB, useful for testing.
-static constexpr float gNarrow_toXYZD50[] {
-    0.190974f,  0.404865f,  0.368380f,
-    0.114746f,  0.582937f,  0.302318f,
-    0.032925f,  0.153615f,  0.638669f,
-};
-
-// Like gSRGB_toXYZD50, keeping this bitwise exactly the same as skcms makes things fastest.
-static constexpr SkColorSpaceTransferFn gSRGB_TransferFn =
-#ifdef SK_LEGACY_SRGB_TRANSFER_FUNCTION
-        { 2.4f, 1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f };
-#else
-        { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
-#endif
-
-static constexpr SkColorSpaceTransferFn g2Dot2_TransferFn =
-        { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
-
-static constexpr SkColorSpaceTransferFn gLinear_TransferFn =
-        { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+static constexpr skcms_Matrix3x3 gNarrow_toXYZD50 = {{
+    { 0.190974f,  0.404865f,  0.368380f },
+    { 0.114746f,  0.582937f,  0.302318f },
+    { 0.032925f,  0.153615f,  0.638669f },
+}};
 
 static inline void to_xyz_d50(SkMatrix44* toXYZD50, SkColorSpace::Gamut gamut) {
     switch (gamut) {
         case SkColorSpace::kSRGB_Gamut:
-            toXYZD50->set3x3RowMajorf(gSRGB_toXYZD50);
+            toXYZD50->set3x3RowMajorf(&SkNamedGamut::kSRGB.vals[0][0]);
             break;
         case SkColorSpace::kAdobeRGB_Gamut:
-            toXYZD50->set3x3RowMajorf(gAdobeRGB_toXYZD50);
+            toXYZD50->set3x3RowMajorf(&SkNamedGamut::kAdobeRGB.vals[0][0]);
             break;
         case SkColorSpace::kDCIP3_D65_Gamut:
-            toXYZD50->set3x3RowMajorf(gDCIP3_toXYZD50);
+            toXYZD50->set3x3RowMajorf(&SkNamedGamut::kDCIP3.vals[0][0]);
             break;
         case SkColorSpace::kRec2020_Gamut:
-            toXYZD50->set3x3RowMajorf(gRec2020_toXYZD50);
+            toXYZD50->set3x3RowMajorf(&SkNamedGamut::kRec2020.vals[0][0]);
             break;
     }
 }
@@ -149,13 +105,13 @@
 }
 
 static inline bool is_almost_srgb(const SkColorSpaceTransferFn& coeffs) {
-    return transfer_fn_almost_equal(gSRGB_TransferFn.fA, coeffs.fA) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fB, coeffs.fB) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fC, coeffs.fC) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fD, coeffs.fD) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fE, coeffs.fE) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fF, coeffs.fF) &&
-           transfer_fn_almost_equal(gSRGB_TransferFn.fG, coeffs.fG);
+    return transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.a, coeffs.fA) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.b, coeffs.fB) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.c, coeffs.fC) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.d, coeffs.fD) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.e, coeffs.fE) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.f, coeffs.fF) &&
+           transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.g, coeffs.fG);
 }
 
 static inline bool is_almost_2dot2(const SkColorSpaceTransferFn& coeffs) {
diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp
index a2f73fc..5fff910 100644
--- a/src/core/SkColorSpaceXformSteps.cpp
+++ b/src/core/SkColorSpaceXformSteps.cpp
@@ -53,10 +53,10 @@
         this->src_to_dst_matrix[8] = row_major[8];
     } else {
     #ifdef SK_DEBUG
-        SkMatrix44 srcM, dstM;
+        skcms_Matrix3x3 srcM, dstM;
         src->toXYZD50(&srcM);
         dst->toXYZD50(&dstM);
-        SkASSERT(0 == memcmp(&srcM, &dstM, 16*sizeof(SkMScalar)) && "Hash collision");
+        SkASSERT(0 == memcmp(&srcM, &dstM, 9*sizeof(float)) && "Hash collision");
     #endif
     }
 
diff --git a/src/core/SkICC.cpp b/src/core/SkICC.cpp
index a9df5b0..d1db49e 100644
--- a/src/core/SkICC.cpp
+++ b/src/core/SkICC.cpp
@@ -206,14 +206,14 @@
 }
 
 static bool nearly_equal(const SkColorSpaceTransferFn& u,
-                         const SkColorSpaceTransferFn& v) {
-    return nearly_equal(u.fG, v.fG)
-        && nearly_equal(u.fA, v.fA)
-        && nearly_equal(u.fB, v.fB)
-        && nearly_equal(u.fC, v.fC)
-        && nearly_equal(u.fD, v.fD)
-        && nearly_equal(u.fE, v.fE)
-        && nearly_equal(u.fF, v.fF);
+                         const skcms_TransferFunction& v) {
+    return nearly_equal(u.fG, v.g)
+        && nearly_equal(u.fA, v.a)
+        && nearly_equal(u.fB, v.b)
+        && nearly_equal(u.fC, v.c)
+        && nearly_equal(u.fD, v.d)
+        && nearly_equal(u.fE, v.e)
+        && nearly_equal(u.fF, v.f);
 }
 
 static bool nearly_equal(const float u[9], const float v[9]) {
@@ -228,23 +228,23 @@
 // Return nullptr if the color profile doen't have a special name.
 const char* get_color_profile_description(const SkColorSpaceTransferFn& fn,
                                           const float toXYZD50[9]) {
-    bool srgb_xfer = nearly_equal(fn, gSRGB_TransferFn);
-    bool srgb_gamut = nearly_equal(toXYZD50, gSRGB_toXYZD50);
+    bool srgb_xfer = nearly_equal(fn, SkNamedTransferFn::kSRGB);
+    bool srgb_gamut = nearly_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0]);
     if (srgb_xfer && srgb_gamut) {
         return "sRGB";
     }
-    bool line_xfer = nearly_equal(fn, gLinear_TransferFn);
+    bool line_xfer = nearly_equal(fn, SkNamedTransferFn::kLinear);
     if (line_xfer && srgb_gamut) {
         return "Linear Transfer with sRGB Gamut";
     }
-    bool twoDotTwo = nearly_equal(fn, g2Dot2_TransferFn);
+    bool twoDotTwo = nearly_equal(fn, SkNamedTransferFn::k2Dot2);
     if (twoDotTwo && srgb_gamut) {
         return "2.2 Transfer with sRGB Gamut";
     }
-    if (twoDotTwo && nearly_equal(toXYZD50, gAdobeRGB_toXYZD50)) {
+    if (twoDotTwo && nearly_equal(toXYZD50, &SkNamedGamut::kAdobeRGB.vals[0][0])) {
         return "AdobeRGB";
     }
-    bool dcip3_gamut = nearly_equal(toXYZD50, gDCIP3_toXYZD50);
+    bool dcip3_gamut = nearly_equal(toXYZD50, &SkNamedGamut::kDCIP3.vals[0][0]);
     if (srgb_xfer || line_xfer) {
         if (srgb_xfer && dcip3_gamut) {
             return "sRGB Transfer with DCI-P3 Gamut";
@@ -252,7 +252,7 @@
         if (line_xfer && dcip3_gamut) {
             return "Linear Transfer with DCI-P3 Gamut";
         }
-        bool rec2020 = nearly_equal(toXYZD50, gRec2020_toXYZD50);
+        bool rec2020 = nearly_equal(toXYZD50, &SkNamedGamut::kRec2020.vals[0][0]);
         if (srgb_xfer && rec2020) {
             return "sRGB Transfer with Rec-BT-2020 Gamut";
         }
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index e8cb662..2cd5e5a 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -8,7 +8,6 @@
 #include "GrColorSpaceXform.h"
 #include "SkColorSpace.h"
 #include "SkColorSpacePriv.h"
-#include "SkMatrix44.h"
 #include "glsl/GrGLSLColorSpaceXformHelper.h"
 #include "glsl/GrGLSLFragmentProcessor.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"