| Index: src/core/SkColorSpace.cpp
|
| diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
|
| index 66b980b8f969860b1e169bb3353d08d1ee9ef427..6c4b474b7696b6cc8a2710246c9cbf3494b12d7d 100644
|
| --- a/src/core/SkColorSpace.cpp
|
| +++ b/src/core/SkColorSpace.cpp
|
| @@ -11,10 +11,6 @@
|
| #include "SkOnce.h"
|
| #include "SkPoint3.h"
|
|
|
| -static inline bool is_zero_to_one(float v) {
|
| - return (0.0f <= v) && (v <= 1.0f);
|
| -}
|
| -
|
| bool SkColorSpacePrimaries::toXYZD50(SkMatrix44* toXYZ_D50) const {
|
| if (!is_zero_to_one(fRX) || !is_zero_to_one(fRY) ||
|
| !is_zero_to_one(fGX) || !is_zero_to_one(fGY) ||
|
| @@ -211,6 +207,37 @@ sk_sp<SkColorSpace> SkColorSpace::NewRGB(RenderTargetGamma gamma, const SkMatrix
|
| }
|
| }
|
|
|
| +sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkColorSpaceTransferFn& coeffs,
|
| + const SkMatrix44& toXYZD50) {
|
| + if (!is_valid_transfer_fn(coeffs)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (is_almost_srgb(coeffs)) {
|
| + return SkColorSpace::NewRGB(kSRGB_RenderTargetGamma, toXYZD50);
|
| + }
|
| +
|
| + if (is_almost_2dot2(coeffs)) {
|
| + return SkColorSpace_Base::NewRGB(k2Dot2Curve_SkGammaNamed, toXYZD50);
|
| + }
|
| +
|
| + void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
|
| + sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
|
| + SkColorSpaceTransferFn* fn = SkTAddOffset<SkColorSpaceTransferFn>(memory, sizeof(SkGammas));
|
| + *fn = coeffs;
|
| + gammas->fRedType = SkGammas::Type::kParam_Type;
|
| + gammas->fGreenType = SkGammas::Type::kParam_Type;
|
| + gammas->fBlueType = SkGammas::Type::kParam_Type;
|
| +
|
| + SkGammas::Data data;
|
| + data.fParamOffset = 0;
|
| + gammas->fRedData = data;
|
| + gammas->fGreenData = data;
|
| + gammas->fBlueData = data;
|
| + return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, kNonStandard_SkGammaNamed,
|
| + std::move(gammas), toXYZD50, nullptr));
|
| +}
|
| +
|
| static SkColorSpace* gAdobeRGB;
|
| static SkColorSpace* gSRGB;
|
| static SkColorSpace* gSRGBLinear;
|
| @@ -300,8 +327,12 @@ enum Version {
|
|
|
| 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.
|
| - * Should not be set at the same time as the kICC_Flag or kFloatGamma_Flag.
|
| */
|
| static constexpr uint8_t kMatrix_Flag = 1 << 0;
|
|
|
| @@ -309,7 +340,6 @@ struct ColorSpaceHeader {
|
| * 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 or kFloatGamma_Flag.
|
| */
|
| static constexpr uint8_t kICC_Flag = 1 << 1;
|
|
|
| @@ -317,10 +347,16 @@ struct ColorSpaceHeader {
|
| * If kFloatGamma_Flag is set, we will write 15 floats after the header.
|
| * The first three are the gamma values, and the next twelve are the
|
| * matrix.
|
| - * Should not be set at the same time as the kICC_Flag or kMatrix_Flag.
|
| */
|
| static constexpr uint8_t kFloatGamma_Flag = 1 << 2;
|
|
|
| + /**
|
| + * 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;
|
| @@ -334,7 +370,7 @@ struct ColorSpaceHeader {
|
| SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
|
| header.fGammaNamed = (uint8_t) gammaNamed;
|
|
|
| - SkASSERT(flags <= kFloatGamma_Flag);
|
| + SkASSERT(flags <= kTransferFn_Flag);
|
| header.fFlags = flags;
|
| return header;
|
| }
|
| @@ -388,26 +424,51 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
|
| return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
|
| }
|
| default:
|
| - // Otherwise, write the gamma values and the matrix.
|
| - if (memory) {
|
| - *((ColorSpaceHeader*) memory) =
|
| - ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
| - ColorSpaceHeader::kFloatGamma_Flag);
|
| - memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
| -
|
| - const SkGammas* gammas = as_CSB(this)->gammas();
|
| - SkASSERT(gammas);
|
| - SkASSERT(SkGammas::Type::kValue_Type == gammas->fRedType &&
|
| - SkGammas::Type::kValue_Type == gammas->fGreenType &&
|
| - SkGammas::Type::kValue_Type == gammas->fBlueType);
|
| - *(((float*) memory) + 0) = gammas->fRedData.fValue;
|
| - *(((float*) memory) + 1) = gammas->fGreenData.fValue;
|
| - *(((float*) memory) + 2) = gammas->fBlueData.fValue;
|
| - memory = SkTAddOffset<void>(memory, 3 * sizeof(float));
|
| -
|
| - as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
| + const SkGammas* gammas = as_CSB(this)->gammas();
|
| + SkASSERT(gammas);
|
| + if (gammas->isValue(0) && gammas->isValue(1) && gammas->isValue(2)) {
|
| + if (memory) {
|
| + *((ColorSpaceHeader*) memory) =
|
| + ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
| + ColorSpaceHeader::kFloatGamma_Flag);
|
| + memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
| +
|
| + *(((float*) memory) + 0) = gammas->fRedData.fValue;
|
| + *(((float*) memory) + 1) = gammas->fGreenData.fValue;
|
| + *(((float*) memory) + 2) = gammas->fBlueData.fValue;
|
| + memory = SkTAddOffset<void>(memory, 3 * sizeof(float));
|
| +
|
| + as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
| + }
|
| +
|
| + return sizeof(ColorSpaceHeader) + 15 * sizeof(float);
|
| + } else {
|
| + SkASSERT(gammas->isParametric(0));
|
| + SkASSERT(gammas->isParametric(1));
|
| + SkASSERT(gammas->isParametric(2));
|
| + SkASSERT(gammas->data(0) == gammas->data(1));
|
| + SkASSERT(gammas->data(0) == gammas->data(2));
|
| +
|
| + if (memory) {
|
| + *((ColorSpaceHeader*) memory) =
|
| + ColorSpaceHeader::Pack(k0_Version, 0, as_CSB(this)->fGammaNamed,
|
| + ColorSpaceHeader::kTransferFn_Flag);
|
| + memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
|
| +
|
| + *(((float*) memory) + 0) = gammas->params(0).fA;
|
| + *(((float*) memory) + 1) = gammas->params(0).fB;
|
| + *(((float*) memory) + 2) = gammas->params(0).fC;
|
| + *(((float*) memory) + 3) = gammas->params(0).fD;
|
| + *(((float*) memory) + 4) = gammas->params(0).fE;
|
| + *(((float*) memory) + 5) = gammas->params(0).fF;
|
| + *(((float*) memory) + 6) = gammas->params(0).fG;
|
| + memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
|
| +
|
| + as_CSB(this)->fToXYZD50.as3x4RowMajorf((float*) memory);
|
| + }
|
| +
|
| + return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
|
| }
|
| - return sizeof(ColorSpaceHeader) + 15 * sizeof(float);
|
| }
|
| }
|
|
|
| @@ -501,6 +562,25 @@ sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) {
|
| toXYZ.set3x4RowMajorf((const float*) data);
|
| return SkColorSpace_Base::NewRGB(gammas, toXYZ);
|
| }
|
| + 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));
|
| +
|
| + SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
|
| + toXYZ.set3x4RowMajorf((const float*) data);
|
| + return SkColorSpace::NewRGB(transferFn, toXYZ);
|
| + }
|
| default:
|
| return nullptr;
|
| }
|
|
|