| Index: src/core/SkColorSpace.cpp
|
| diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
|
| index 5df45fff4126d7e9a08a1251e9b9cde029ae7de8..95c38f22639dba6cd35ed1b9d844248ee064d9b1 100644
|
| --- a/src/core/SkColorSpace.cpp
|
| +++ b/src/core/SkColorSpace.cpp
|
| @@ -9,6 +9,8 @@
|
| #include "SkColorSpace_Base.h"
|
| #include "SkEndian.h"
|
| #include "SkOnce.h"
|
| +#include "SkReadBuffer.h"
|
| +#include "SkWriteBuffer.h"
|
|
|
| #define SkColorSpacePrintf(...)
|
|
|
| @@ -24,11 +26,10 @@ SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na
|
| , fNamed(named)
|
| {}
|
|
|
| -SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named,
|
| - sk_sp<SkData> profileData)
|
| +SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named)
|
| : INHERITED(gammaNamed, toXYZD50, named)
|
| , fGammas(nullptr)
|
| - , fProfileData(std::move(profileData))
|
| + , fProfileData(nullptr)
|
| {}
|
|
|
| SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGammas> gammas,
|
| @@ -102,11 +103,10 @@ sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44&
|
| return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, gammas, toXYZD50, nullptr));
|
| }
|
|
|
| - return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr);
|
| + return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50);
|
| }
|
|
|
| -sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50,
|
| - sk_sp<SkData> profileData) {
|
| +sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50) {
|
| switch (gammaNamed) {
|
| case kSRGB_GammaNamed:
|
| if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
|
| @@ -125,12 +125,11 @@ sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMat
|
| break;
|
| }
|
|
|
| - return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnknown_Named,
|
| - profileData));
|
| + return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnknown_Named));
|
| }
|
|
|
| sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50) {
|
| - return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr);
|
| + return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50);
|
| }
|
|
|
| sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
| @@ -144,7 +143,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
| sRGBOnce([] {
|
| SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
|
| srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50);
|
| - sRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50, kSRGB_Named, nullptr);
|
| + sRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50, kSRGB_Named);
|
| });
|
| return sk_ref_sp(sRGB);
|
| }
|
| @@ -153,7 +152,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
| SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Constructor);
|
| adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50);
|
| adobeRGB = new SkColorSpace_Base(k2Dot2Curve_GammaNamed, adobergbToxyzD50,
|
| - kAdobeRGB_Named, nullptr);
|
| + kAdobeRGB_Named);
|
| });
|
| return sk_ref_sp(adobeRGB);
|
| }
|
| @@ -930,7 +929,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
|
| return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, std::move(gammas),
|
| mat, std::move(data)));
|
| } else {
|
| - return SkColorSpace_Base::NewRGB(gammaNamed, mat, std::move(data));
|
| + return SkColorSpace_Base::NewRGB(gammaNamed, mat);
|
| }
|
| }
|
|
|
| @@ -955,7 +954,7 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
|
| std::move(gammas), toXYZ,
|
| std::move(data)));
|
| } else {
|
| - return SkColorSpace_Base::NewRGB(gammaNamed, toXYZ, std::move(data));
|
| + return SkColorSpace_Base::NewRGB(gammaNamed, toXYZ);
|
| }
|
| }
|
| }
|
| @@ -1208,3 +1207,153 @@ sk_sp<SkData> SkColorSpace_Base::writeToICC() const {
|
| // the client calls again?
|
| return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
|
| }
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +enum Version {
|
| + k0_Version, // Initial version, header + flags for matrix and profile
|
| +};
|
| +
|
| +struct ColorSpaceHeader {
|
| + /**
|
| + * If kMatrix_Flag is set, we will write 12 floats after the header.
|
| + * Should not be set at the same time as the kICC_Flag.
|
| + */
|
| + 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).
|
| + * Should not be set at the same time as the kMatrix_Flag.
|
| + */
|
| + static constexpr uint8_t kICC_Flag = 1 << 1;
|
| +
|
| + static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named,
|
| + SkColorSpace::GammaNamed gammaNamed, uint8_t flags) {
|
| + ColorSpaceHeader header;
|
| +
|
| + SkASSERT(k0_Version == version);
|
| + header.fVersion = (uint8_t) version;
|
| +
|
| + SkASSERT(named <= SkColorSpace::kAdobeRGB_Named);
|
| + header.fNamed = (uint8_t) named;
|
| +
|
| + SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed);
|
| + header.fGammaNamed = (uint8_t) gammaNamed;
|
| +
|
| + SkASSERT(flags <= kICC_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 SkColorSpace::GammaNamed
|
| + uint8_t fFlags; // Some combination of the flags listed above
|
| +};
|
| +
|
| +sk_sp<SkData> SkColorSpace::serialize() const {
|
| + // If we have a named profile, only write the enum.
|
| + switch (fNamed) {
|
| + case kSRGB_Named:
|
| + case kAdobeRGB_Named: {
|
| + sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader));
|
| + *((ColorSpaceHeader*) data->writable_data()) =
|
| + ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed, 0);
|
| + return data;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + // If we have a named gamma, write the enum and the matrix.
|
| + switch (fGammaNamed) {
|
| + case kSRGB_GammaNamed:
|
| + case k2Dot2Curve_GammaNamed:
|
| + case kLinear_GammaNamed: {
|
| + sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader) +
|
| + 12 * sizeof(float));
|
| + void* dataPtr = data->writable_data();
|
| +
|
| + *((ColorSpaceHeader*) dataPtr) = ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed,
|
| + ColorSpaceHeader::kMatrix_Flag);
|
| + dataPtr = SkTAddOffset<void>(dataPtr, sizeof(ColorSpaceHeader));
|
| +
|
| + fToXYZD50.as4x3ColMajorf((float*) dataPtr);
|
| + return data;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + // If we do not have a named gamma, this must have been created from an ICC profile.
|
| + // Since we were unable to recognize the gamma, we will have saved the ICC data.
|
| + SkASSERT(as_CSB(this)->fProfileData);
|
| +
|
| + size_t profileSize = as_CSB(this)->fProfileData->size();
|
| + if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader) + sizeof(uint32_t) +
|
| + SkAlign4(profileSize));
|
| + void* dataPtr = data->writable_data();
|
| +
|
| + *((ColorSpaceHeader*) dataPtr) = ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed,
|
| + ColorSpaceHeader::kICC_Flag);
|
| + dataPtr = SkTAddOffset<void>(dataPtr, sizeof(ColorSpaceHeader));
|
| +
|
| + *((uint32_t*) dataPtr) = (uint32_t) SkAlign4(profileSize);
|
| + dataPtr = SkTAddOffset<void>(dataPtr, sizeof(uint32_t));
|
| +
|
| + memcpy(dataPtr, as_CSB(this)->fProfileData->data(), profileSize);
|
| + memset(SkTAddOffset<void>(dataPtr, profileSize), 0, SkAlign4(profileSize) - profileSize);
|
| + return data;
|
| +}
|
| +
|
| +sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) {
|
| + if (length < sizeof(ColorSpaceHeader)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + ColorSpaceHeader header = *((const ColorSpaceHeader*) data);
|
| + data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader));
|
| + length -= sizeof(ColorSpaceHeader);
|
| + switch ((Named) header.fNamed) {
|
| + case kSRGB_Named:
|
| + case kAdobeRGB_Named:
|
| + return NewNamed((Named) header.fNamed);
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + switch ((GammaNamed) header.fGammaNamed) {
|
| + case kSRGB_GammaNamed:
|
| + case k2Dot2Curve_GammaNamed:
|
| + case kLinear_GammaNamed: {
|
| + if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 * sizeof(float)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
|
| + toXYZ.set4x3ColMajorf((const float*) data);
|
| + return NewRGB((GammaNamed) header.fGammaNamed, toXYZ);
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + if (ColorSpaceHeader::kICC_Flag != header.fFlags || length < sizeof(uint32_t)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + uint32_t profileSize = *((uint32_t*) data);
|
| + data = SkTAddOffset<const void>(data, sizeof(uint32_t));
|
| + length -= sizeof(uint32_t);
|
| + if (length < profileSize) {
|
| + return nullptr;
|
| + }
|
| +
|
| + return NewICC(data, profileSize);
|
| +}
|
|
|