| Index: src/core/SkColorSpace.cpp
|
| diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
|
| index c6bf4b9431300460b4fbe4dd2b6f276de9dda4a2..5541a403928a6c24b02ed6a88cb3711fbeaebd11 100644
|
| --- a/src/core/SkColorSpace.cpp
|
| +++ b/src/core/SkColorSpace.cpp
|
| @@ -7,26 +7,14 @@
|
|
|
| #include "SkColorSpace.h"
|
| #include "SkColorSpace_Base.h"
|
| +#include "SkColorSpace_A2B0.h"
|
| +#include "SkColorSpace_XYZTRC.h"
|
| #include "SkColorSpacePriv.h"
|
| #include "SkOnce.h"
|
|
|
| -SkColorSpace_Base::SkColorSpace_Base(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50)
|
| - : fGammaNamed(gammaNamed)
|
| - , fGammas(nullptr)
|
| - , fProfileData(nullptr)
|
| - , fToXYZD50(toXYZD50)
|
| - , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
|
| -{}
|
| -
|
| -SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, SkGammaNamed gammaNamed,
|
| - sk_sp<SkGammas> gammas, const SkMatrix44& toXYZD50,
|
| - sk_sp<SkData> profileData)
|
| - : fColorLUT(std::move(colorLUT))
|
| - , fGammaNamed(gammaNamed)
|
| - , fGammas(std::move(gammas))
|
| - , fProfileData(std::move(profileData))
|
| - , fToXYZD50(toXYZD50)
|
| - , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
|
| +SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkData> profileData, Type type)
|
| + : fProfileData(std::move(profileData))
|
| + , fType(type)
|
| {}
|
|
|
| static constexpr float gSRGB_toXYZD50[] {
|
| @@ -90,8 +78,8 @@ sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(const float values[3], const SkMat
|
| gammas->fRedData.fValue = values[0];
|
| gammas->fGreenData.fValue = values[1];
|
| gammas->fBlueData.fValue = values[2];
|
| - return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, kNonStandard_SkGammaNamed, gammas,
|
| - toXYZD50, nullptr));
|
| + return sk_sp<SkColorSpace>(new SkColorSpace_XYZTRC(kNonStandard_SkGammaNamed,
|
| + gammas, toXYZD50, nullptr));
|
| }
|
|
|
| return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50);
|
| @@ -121,7 +109,7 @@ sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(SkGammaNamed gammaNamed, const SkM
|
| break;
|
| }
|
|
|
| - return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50));
|
| + return sk_sp<SkColorSpace>(new SkColorSpace_XYZTRC(gammaNamed, toXYZD50));
|
| }
|
|
|
| sk_sp<SkColorSpace> SkColorSpace::NewRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50) {
|
| @@ -152,7 +140,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
|
|
| // Force the mutable type mask to be computed. This avoids races.
|
| (void)srgbToxyzD50.getType();
|
| - gSRGB = new SkColorSpace_Base(kSRGB_SkGammaNamed, srgbToxyzD50);
|
| + gSRGB = new SkColorSpace_XYZTRC(kSRGB_SkGammaNamed, srgbToxyzD50);
|
| });
|
| return sk_ref_sp<SkColorSpace>(gSRGB);
|
| }
|
| @@ -163,7 +151,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
|
|
| // Force the mutable type mask to be computed. This avoids races.
|
| (void)adobergbToxyzD50.getType();
|
| - gAdobeRGB = new SkColorSpace_Base(k2Dot2Curve_SkGammaNamed, adobergbToxyzD50);
|
| + gAdobeRGB = new SkColorSpace_XYZTRC(k2Dot2Curve_SkGammaNamed, adobergbToxyzD50);
|
| });
|
| return sk_ref_sp<SkColorSpace>(gAdobeRGB);
|
| }
|
| @@ -174,7 +162,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
|
|
| // Force the mutable type mask to be computed. This avoids races.
|
| (void)srgbToxyzD50.getType();
|
| - gSRGBLinear = new SkColorSpace_Base(kLinear_SkGammaNamed, srgbToxyzD50);
|
| + gSRGBLinear = new SkColorSpace_XYZTRC(kLinear_SkGammaNamed, srgbToxyzD50);
|
| });
|
| return sk_ref_sp<SkColorSpace>(gSRGBLinear);
|
| }
|
| @@ -188,32 +176,45 @@ sk_sp<SkColorSpace> SkColorSpace::makeLinearGamma() {
|
| if (this->gammaIsLinear()) {
|
| return sk_ref_sp(this);
|
| }
|
| - return SkColorSpace_Base::NewRGB(kLinear_SkGammaNamed, as_CSB(this)->fToXYZD50);
|
| + // A2B0 Color Spaces do not have a single Gamma, so this method should not be
|
| + // called on them.
|
| + SkASSERT(as_CSB(this)->type() == SkColorSpace_Base::Type::kXYZTRC);
|
| + return SkColorSpace_Base::NewRGB(kLinear_SkGammaNamed, as_CSXYZ(this)->fToXYZD50);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| bool SkColorSpace::gammaCloseToSRGB() const {
|
| - return kSRGB_SkGammaNamed == as_CSB(this)->fGammaNamed ||
|
| - k2Dot2Curve_SkGammaNamed == as_CSB(this)->fGammaNamed;
|
| + switch (as_CSB(this)->type())
|
| + {
|
| + case SkColorSpace_Base::Type::kXYZTRC:
|
| + return kSRGB_SkGammaNamed == as_CSXYZ(this)->fGammaNamed ||
|
| + k2Dot2Curve_SkGammaNamed == as_CSXYZ(this)->fGammaNamed;
|
| + case SkColorSpace_Base::Type::kA2B0:
|
| + // Uncomment this assert later on
|
| + //SkASSERT(false);
|
| + return false;
|
| + default:
|
| + break;
|
| + }
|
| + SkASSERT(false);
|
| + return false;
|
| }
|
|
|
| bool SkColorSpace::gammaIsLinear() const {
|
| - return kLinear_SkGammaNamed == as_CSB(this)->fGammaNamed;
|
| -}
|
| -
|
| -const SkMatrix44& SkColorSpace_Base::fromXYZD50() const {
|
| - fFromXYZOnce([this] {
|
| - if (!fToXYZD50.invert(&fFromXYZD50)) {
|
| - // If a client gives us a dst gamut with a transform that we can't invert, we will
|
| - // simply give them back a transform to sRGB gamut.
|
| - SkDEBUGFAIL("Non-invertible XYZ matrix, defaulting to sRGB");
|
| - SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
|
| - srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
|
| - srgbToxyzD50.invert(&fFromXYZD50);
|
| - }
|
| - });
|
| - return fFromXYZD50;
|
| + switch (as_CSB(this)->type())
|
| + {
|
| + case SkColorSpace_Base::Type::kXYZTRC:
|
| + return kLinear_SkGammaNamed == as_CSXYZ(this)->fGammaNamed;
|
| + case SkColorSpace_Base::Type::kA2B0:
|
| + // Uncomment this assert later on
|
| + //SkASSERT(false);
|
| + return false;
|
| + default:
|
| + break;
|
| + }
|
| + SkASSERT(false);
|
| + return false;
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
| @@ -273,41 +274,40 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
|
| // Start by trying the serialization fast path. If we haven't saved ICC profile data,
|
| // we must have a profile that we can serialize easily.
|
| if (!as_CSB(this)->fProfileData) {
|
| + // Profile data is mandatory for A2B0 color spaces.
|
| // If we have a named profile, only write the enum.
|
| + const SkGammaNamed gammaNamed = as_CSXYZ(this)->gammaNamed();
|
| if (this == gSRGB) {
|
| if (memory) {
|
| *((ColorSpaceHeader*) memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, kSRGB_Named,
|
| - as_CSB(this)->fGammaNamed, 0);
|
| + ColorSpaceHeader::Pack(k0_Version, kSRGB_Named, gammaNamed, 0);
|
| }
|
| return sizeof(ColorSpaceHeader);
|
| } else if (this == gAdobeRGB) {
|
| if (memory) {
|
| *((ColorSpaceHeader*) memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, kAdobeRGB_Named,
|
| - as_CSB(this)->fGammaNamed, 0);
|
| + ColorSpaceHeader::Pack(k0_Version, kAdobeRGB_Named, gammaNamed, 0);
|
| }
|
| return sizeof(ColorSpaceHeader);
|
| } else if (this == gSRGBLinear) {
|
| if (memory) {
|
| *((ColorSpaceHeader*)memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, kSRGBLinear_Named,
|
| - as_CSB(this)->fGammaNamed, 0);
|
| + ColorSpaceHeader::Pack(k0_Version, kSRGBLinear_Named, gammaNamed, 0);
|
| }
|
| return sizeof(ColorSpaceHeader);
|
| }
|
|
|
| // If we have a named gamma, write the enum and the matrix.
|
| - switch (as_CSB(this)->fGammaNamed) {
|
| + switch (gammaNamed) {
|
| case kSRGB_SkGammaNamed:
|
| case k2Dot2Curve_SkGammaNamed:
|
| case kLinear_SkGammaNamed: {
|
| if (memory) {
|
| *((ColorSpaceHeader*) memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
| + ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
|
| ColorSpaceHeader::kMatrix_Flag);
|
| memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
| - as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
| + as_CSXYZ(this)->toXYZD50().as3x4RowMajorf((float*) memory);
|
| }
|
| return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
|
| }
|
| @@ -315,11 +315,11 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
|
| // Otherwise, write the gamma values and the matrix.
|
| if (memory) {
|
| *((ColorSpaceHeader*) memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
| + ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
|
| ColorSpaceHeader::kFloatGamma_Flag);
|
| memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
|
|
| - const SkGammas* gammas = as_CSB(this)->gammas();
|
| + const SkGammas* gammas = as_CSXYZ(this)->gammas();
|
| SkASSERT(gammas);
|
| SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType &&
|
| SkGammas::Type::kValue_Type == gammas->fGreenType &&
|
| @@ -329,7 +329,7 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
|
| *(((float*) memory) + 2) = gammas->fBlueData.fValue;
|
| memory = SkTAddOffset<void>(memory, 3 * sizeof(float));
|
|
|
| - as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
| + as_CSXYZ(this)->toXYZD50().as3x4RowMajorf((float*) memory);
|
| }
|
| return sizeof(ColorSpaceHeader) + 15 * sizeof(float);
|
| }
|
| @@ -438,6 +438,10 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
|
| if (!src || !dst) {
|
| return false;
|
| }
|
| +
|
| + if (as_CSB(src)->type() != as_CSB(dst)->type()) {
|
| + return false;
|
| + }
|
|
|
| SkData* srcData = as_CSB(src)->fProfileData.get();
|
| SkData* dstData = as_CSB(dst)->fProfileData.get();
|
| @@ -451,22 +455,47 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
|
| }
|
|
|
| // It's important to check fProfileData before named gammas. Some profiles may have named
|
| - // gammas, but also include other wacky features that cause us to save the data.
|
| - switch (as_CSB(src)->fGammaNamed) {
|
| - case kSRGB_SkGammaNamed:
|
| - case k2Dot2Curve_SkGammaNamed:
|
| - case kLinear_SkGammaNamed:
|
| - return (as_CSB(src)->fGammaNamed == as_CSB(dst)->fGammaNamed) &&
|
| - (as_CSB(src)->fToXYZD50 == as_CSB(dst)->fToXYZD50);
|
| - default:
|
| - if (as_CSB(src)->fGammaNamed != as_CSB(dst)->fGammaNamed) {
|
| + // gammas, but also include other wacky features that cause us to save the data.
|
| + if (as_CSB(src)->type() == SkColorSpace_Base::Type::kXYZTRC) {
|
| + switch (as_CSXYZ(src)->gammaNamed()) {
|
| + case kSRGB_SkGammaNamed:
|
| + case k2Dot2Curve_SkGammaNamed:
|
| + case kLinear_SkGammaNamed:
|
| + return (as_CSXYZ(src)->gammaNamed() == as_CSXYZ(dst)->gammaNamed()) &&
|
| + (as_CSXYZ(src)->toXYZD50() == as_CSXYZ(dst)->toXYZD50());
|
| + default:
|
| + if (as_CSXYZ(src)->gammaNamed() != as_CSXYZ(dst)->gammaNamed()) {
|
| + return false;
|
| + }
|
| + }
|
| + // TRC tables still need checking
|
| + } else {
|
| + const SkGammaNamed aNamed = as_CSA2B(src)->aCurveNamed();
|
| + const SkGammaNamed bNamed = as_CSA2B(src)->bCurveNamed();
|
| + const SkGammaNamed mNamed = as_CSA2B(src)->mCurveNamed();
|
| + if ((aNamed != as_CSA2B(dst)->aCurveNamed()) ||
|
| + (bNamed != as_CSA2B(dst)->bCurveNamed()) ||
|
| + (mNamed != as_CSA2B(dst)->mCurveNamed())) {
|
| + return false;
|
| + }
|
| + if (aNamed != kNonStandard_SkGammaNamed &&
|
| + bNamed != kNonStandard_SkGammaNamed &&
|
| + mNamed != kNonStandard_SkGammaNamed) {
|
| + // All gammas are the same type and are not tables, so see if
|
| + // the matrices differ
|
| + if ((as_CSA2B(src)->toPCS() != as_CSA2B(dst)->toPCS()) ||
|
| + (as_CSA2B(src)->toPCS() != as_CSA2B(dst)->toPCS()) ||
|
| + (as_CSA2B(src)->toPCS() != as_CSA2B(dst)->toPCS())) {
|
| return false;
|
| }
|
| -
|
| - // It is unlikely that we will reach this case.
|
| - sk_sp<SkData> srcData = src->serialize();
|
| - sk_sp<SkData> dstData = dst->serialize();
|
| - return srcData->size() == dstData->size() &&
|
| - 0 == memcmp(srcData->data(), dstData->data(), srcData->size());
|
| + }
|
| + // a/b/m-curve tables (if applicable) and CLUT still needs checking
|
| }
|
| +
|
| + // It is unlikely that we will reach this case.
|
| + sk_sp<SkData> serializedSrcData = src->serialize();
|
| + sk_sp<SkData> serializedDstData = dst->serialize();
|
| + return serializedSrcData->size() == serializedDstData->size() &&
|
| + 0 == memcmp(serializedSrcData->data(), serializedDstData->data(),
|
| + serializedSrcData->size());
|
| }
|
|
|