bool toXYZD50(SkMatrix44* toXYZD50) const;
};
+/**
+ * Contains the coefficients for a common transfer function equation, specified as
+ * a transformation from a curved space to linear.
+ *
+ * LinearVal = E*InputVal + F , for 0.0f <= InputVal < D
+ * LinearVal = (A*InputVal + B)^G + C, for D <= InputVal <= 1.0f
+ *
+ * Function is undefined if InputVal is not in [ 0.0f, 1.0f ].
+ * Resulting LinearVals must be in [ 0.0f, 1.0f ].
+ * Function must be positive and increasing.
+ */
+struct SK_API SkColorSpaceTransferFn {
+ float fG;
+ float fA;
+ float fB;
+ float fC;
+ float fD;
+ float fE;
+ float fF;
+};
+
class SK_API SkColorSpace : public SkRefCnt {
public:
/**
* Create an SkColorSpace from a transfer function and a color gamut.
*
- * Transfer function is specified as linear or sRGB.
+ * Transfer function can be specified as a render target or as the coefficients to an equation.
* Gamut is specified using the matrix transformation to XYZ D50.
*/
static sk_sp<SkColorSpace> NewRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
+ static sk_sp<SkColorSpace> NewRGB(const SkColorSpaceTransferFn& coeffs,
+ const SkMatrix44& toXYZD50);
/**
* Create a common, named SkColorSpace.
#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) ||
}
}
+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;
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;
* 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;
* 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;
SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
header.fGammaNamed = (uint8_t) gammaNamed;
- SkASSERT(flags <= kFloatGamma_Flag);
+ SkASSERT(flags <= kTransferFn_Flag);
header.fFlags = flags;
return header;
}
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);
}
}
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;
}
#define SkColorSpacePrintf(...)
-inline bool color_space_almost_equal(float a, float b) {
+static inline bool color_space_almost_equal(float a, float b) {
return SkTAbs(a - b) < 0.01f;
}
+
+static inline bool is_zero_to_one(float v) {
+ return (0.0f <= v) && (v <= 1.0f);
+}
+
+static inline bool is_valid_transfer_fn(const SkColorSpaceTransferFn& coeffs) {
+ if (SkScalarIsNaN(coeffs.fA) || SkScalarIsNaN(coeffs.fB) ||
+ SkScalarIsNaN(coeffs.fC) || SkScalarIsNaN(coeffs.fD) ||
+ SkScalarIsNaN(coeffs.fE) || SkScalarIsNaN(coeffs.fF) ||
+ SkScalarIsNaN(coeffs.fG))
+ {
+ return false;
+ }
+
+ if (!is_zero_to_one(coeffs.fD)) {
+ return false;
+ }
+
+ if (coeffs.fD == 0.0f) {
+ // Y = (aX + b)^g + c for always
+ if (0.0f == coeffs.fA || 0.0f == coeffs.fG) {
+ SkColorSpacePrintf("A or G is zero, constant transfer function "
+ "is nonsense");
+ return false;
+ }
+ }
+
+ if (coeffs.fD == 1.0f) {
+ // Y = eX + f for always
+ if (0.0f == coeffs.fE) {
+ SkColorSpacePrintf("E is zero, constant transfer function is "
+ "nonsense");
+ return false;
+ }
+ }
+
+ if ((0.0f == coeffs.fA || 0.0f == coeffs.fG) && 0.0f == coeffs.fE) {
+ SkColorSpacePrintf("A or G, and E are zero, constant transfer function "
+ "is nonsense");
+ return false;
+ }
+
+ if (coeffs.fE < 0.0f) {
+ SkColorSpacePrintf("Transfer function must be increasing");
+ return false;
+ }
+
+ if (coeffs.fA < 0.0f || coeffs.fG < 0.0f) {
+ SkColorSpacePrintf("Transfer function must be positive or increasing");
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool is_almost_srgb(const SkColorSpaceTransferFn& coeffs) {
+ return color_space_almost_equal(0.9479f, coeffs.fA) &&
+ color_space_almost_equal(0.0521f, coeffs.fB) &&
+ color_space_almost_equal(0.0000f, coeffs.fC) &&
+ color_space_almost_equal(0.0405f, coeffs.fD) &&
+ color_space_almost_equal(0.0774f, coeffs.fE) &&
+ color_space_almost_equal(0.0000f, coeffs.fF) &&
+ color_space_almost_equal(2.4000f, coeffs.fG);
+}
+
+static inline bool is_almost_2dot2(const SkColorSpaceTransferFn& coeffs) {
+ return color_space_almost_equal(1.0f, coeffs.fA) &&
+ color_space_almost_equal(0.0f, coeffs.fB) &&
+ color_space_almost_equal(0.0f, coeffs.fC) &&
+ color_space_almost_equal(0.0f, coeffs.fD) &&
+ color_space_almost_equal(0.0f, coeffs.fE) &&
+ color_space_almost_equal(0.0f, coeffs.fF) &&
+ color_space_almost_equal(2.2f, coeffs.fG);
+}
outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
} else {
SkASSERT(gammas->isParametric(i));
- const SkGammas::Params& params = gammas->params(i);
+ const SkColorSpaceTransferFn& params = gammas->params(i);
(*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG,
params.fA, params.fB, params.fC, params.fD, params.fE,
params.fF);
}
};
- // Contains the parameters for a parametric curve.
- struct Params {
- // Y = (aX + b)^g + c for X >= d
- // Y = eX + f otherwise
- float fG;
- float fA;
- float fB;
- float fC;
- float fD;
- float fE;
- float fF;
- };
-
// Contains the actual gamma curve information. Should be interpreted
// based on the type of the gamma curve.
union Data {
Table fTable;
size_t fParamOffset;
- const Params& params(const SkGammas* base) const {
- return *SkTAddOffset<const Params>(base, sizeof(SkGammas) + fParamOffset);
+ const SkColorSpaceTransferFn& params(const SkGammas* base) const {
+ return *SkTAddOffset<const SkColorSpaceTransferFn>(
+ base, sizeof(SkGammas) + fParamOffset);
}
};
return this->data(i).fTable.table(this);
}
- const Params& params(int i) const {
+ const SkColorSpaceTransferFn& params(int i) const {
SkASSERT(isParametric(i));
return this->data(i).params(this);
}
*
* @return kNone_Type on failure, otherwise the type of the gamma tag.
*/
-static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkGammas::Params* outParams,
- size_t* outTagBytes, const uint8_t* src, size_t len) {
+static SkGammas::Type parse_gamma(SkGammas::Data* outData, SkColorSpaceTransferFn* outParams,
+ size_t* outTagBytes, const uint8_t* src, size_t len) {
if (len < 12) {
SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
return SkGammas::Type::kNone_Type;
return SkGammas::Type::kNone_Type;
}
- // Recognize and simplify a very common parametric representation of sRGB gamma.
- if (color_space_almost_equal(0.9479f, a) &&
- color_space_almost_equal(0.0521f, b) &&
- color_space_almost_equal(0.0000f, c) &&
- color_space_almost_equal(0.0405f, d) &&
- color_space_almost_equal(0.0774f, e) &&
- color_space_almost_equal(0.0000f, f) &&
- color_space_almost_equal(2.4000f, g)) {
- outData->fNamed = kSRGB_SkGammaNamed;
- return SkGammas::Type::kNamed_Type;
- }
+ outParams->fG = g;
+ outParams->fA = a;
+ outParams->fB = b;
+ outParams->fC = c;
+ outParams->fD = d;
+ outParams->fE = e;
+ outParams->fF = f;
- // Fail on invalid gammas.
- if (SkScalarIsNaN(d)) {
+ if (!is_valid_transfer_fn(*outParams)) {
return SkGammas::Type::kNone_Type;
}
- if (d <= 0.0f) {
- // Y = (aX + b)^g + c for always
- if (0.0f == a || 0.0f == g) {
- SkColorSpacePrintf("A or G is zero, constant gamma function "
- "is nonsense");
- return SkGammas::Type::kNone_Type;
- }
- }
-
- if (d >= 1.0f) {
- // Y = eX + f for always
- if (0.0f == e) {
- SkColorSpacePrintf("E is zero, constant gamma function is "
- "nonsense");
- return SkGammas::Type::kNone_Type;
- }
+ if (is_almost_srgb(*outParams)) {
+ outData->fNamed = kSRGB_SkGammaNamed;
+ return SkGammas::Type::kNamed_Type;
}
- if ((0.0f == a || 0.0f == g) && 0.0f == e) {
- SkColorSpacePrintf("A or G, and E are zero, constant gamma function "
- "is nonsense");
- return SkGammas::Type::kNone_Type;
+ if (is_almost_2dot2(*outParams)) {
+ outData->fNamed = k2Dot2Curve_SkGammaNamed;
+ return SkGammas::Type::kNamed_Type;
}
*outTagBytes = tagBytes;
-
- outParams->fG = g;
- outParams->fA = a;
- outParams->fB = b;
- outParams->fC = c;
- outParams->fD = d;
- outParams->fE = e;
- outParams->fF = f;
return SkGammas::Type::kParam_Type;
}
default:
case SkGammas::Type::kTable_Type:
return sizeof(float) * data.fTable.fSize;
case SkGammas::Type::kParam_Type:
- return sizeof(SkGammas::Params);
+ return sizeof(SkColorSpaceTransferFn);
default:
SkASSERT(false);
return 0;
* @return Additional bytes of memory that are being used by this gamma curve.
*/
static size_t load_gammas(void* memory, size_t offset, SkGammas::Type type,
- SkGammas::Data* data, const SkGammas::Params& params,
+ SkGammas::Data* data, const SkColorSpaceTransferFn& params,
const uint8_t* src) {
void* storage = SkTAddOffset<void>(memory, offset + sizeof(SkGammas));
}
case SkGammas::Type::kParam_Type:
data->fTable.fOffset = offset;
- memcpy(storage, ¶ms, sizeof(SkGammas::Params));
- return sizeof(SkGammas::Params);
+ memcpy(storage, ¶ms, sizeof(SkColorSpaceTransferFn));
+ return sizeof(SkColorSpaceTransferFn);
default:
SkASSERT(false);
return 0;
size_t tagLen = len - offsetToMCurves;
SkGammas::Data rData;
- SkGammas::Params rParams;
+ SkColorSpaceTransferFn rParams;
// On an invalid first gamma, tagBytes remains set as zero. This causes the two
// subsequent to be treated as identical (which is what we want).
const uint8_t* gTagPtr = rTagPtr + alignedTagBytes;
tagLen = tagLen > alignedTagBytes ? tagLen - alignedTagBytes : 0;
SkGammas::Data gData;
- SkGammas::Params gParams;
+ SkColorSpaceTransferFn gParams;
tagBytes = 0;
SkGammas::Type gType = parse_gamma(&gData, &gParams, &tagBytes, gTagPtr,
- tagLen);
+ tagLen);
handle_invalid_gamma(&gType, &gData);
alignedTagBytes = SkAlign4(tagBytes);
const uint8_t* bTagPtr = gTagPtr + alignedTagBytes;
tagLen = tagLen > alignedTagBytes ? tagLen - alignedTagBytes : 0;
SkGammas::Data bData;
- SkGammas::Params bParams;
+ SkColorSpaceTransferFn bParams;
SkGammas::Type bType = parse_gamma(&bData, &bParams, &tagBytes, bTagPtr,
tagLen);
handle_invalid_gamma(&bType, &bData);
if (r && g && b) {
if (tag_equals(r, g, base) && tag_equals(g, b, base)) {
SkGammas::Data data;
- SkGammas::Params params;
+ SkColorSpaceTransferFn params;
SkGammas::Type type =
parse_gamma(&data, ¶ms, &tagBytes, r->addr(base), r->fLength);
handle_invalid_gamma(&type, &data);
}
} else {
SkGammas::Data rData;
- SkGammas::Params rParams;
+ SkColorSpaceTransferFn rParams;
SkGammas::Type rType =
parse_gamma(&rData, &rParams, &tagBytes, r->addr(base), r->fLength);
handle_invalid_gamma(&rType, &rData);
SkGammas::Data gData;
- SkGammas::Params gParams;
+ SkColorSpaceTransferFn gParams;
SkGammas::Type gType =
parse_gamma(&gData, &gParams, &tagBytes, g->addr(base), g->fLength);
handle_invalid_gamma(&gType, &gData);
SkGammas::Data bData;
- SkGammas::Params bParams;
+ SkColorSpaceTransferFn bParams;
SkGammas::Type bType =
parse_gamma(&bData, &bParams, &tagBytes, b->addr(base), b->fLength);
handle_invalid_gamma(&bType, &bData);
const float gammas[] = { 1.1f, 1.2f, 1.7f, };
SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
test_serialize(r, SkColorSpace_Base::NewRGB(gammas, toXYZ).get(), false);
+
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 0.0f;
+ fn.fD = 0.5f;
+ fn.fE = 1.0f;
+ fn.fF = 0.0f;
+ fn.fG = 1.0f;
+ test_serialize(r, SkColorSpace::NewRGB(fn, toXYZ).get(), false);
}
DEF_TEST(ColorSpace_Equals, r) {
sk_sp<SkColorSpace> rgb2 = SkColorSpace_Base::NewRGB(gammas2, toXYZ);
sk_sp<SkColorSpace> rgb3 = SkColorSpace_Base::NewRGB(gammas1, toXYZ);
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 0.0f;
+ fn.fD = 0.5f;
+ fn.fE = 1.0f;
+ fn.fF = 0.0f;
+ fn.fG = 1.0f;
+ sk_sp<SkColorSpace> rgb4 = SkColorSpace::NewRGB(fn, toXYZ);
+
REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr));
REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get()));
REPORTER_ASSERT(r, SkColorSpace::Equals(adobe.get(), adobe.get()));
REPORTER_ASSERT(r, SkColorSpace::Equals(upperRight.get(), upperRight.get()));
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb1.get(), rgb1.get()));
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb1.get(), rgb3.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(rgb4.get(), rgb4.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr));
REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), upperRight.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(upperRight.get(), adobe.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(rgb1.get(), rgb2.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(rgb1.get(), rgb4.get()));
}
DEF_TEST(ColorSpace_Primaries, r) {
DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
// Parametric gamma curves
- void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkGammas::Params));
+ void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
gammas->fRedType = gammas->fGreenType = gammas->fBlueType = SkGammas::Type::kParam_Type;
gammas->fRedData.fParamOffset = gammas->fGreenData.fParamOffset =
gammas->fBlueData.fParamOffset = 0;
- SkGammas::Params* params = SkTAddOffset<SkGammas::Params>(memory, sizeof(SkGammas));
+ SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>
+ (memory, sizeof(SkGammas));
// Interval, switch xforms at 0.0031308f
params->fD = 0.04045f;
DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) {
constexpr size_t tableSize = 10;
void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(float) * tableSize +
- sizeof(SkGammas::Params));
+ sizeof(SkColorSpaceTransferFn));
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas());
float* table = SkTAddOffset<float>(memory, sizeof(SkGammas));
table[8] = 0.85f;
table[9] = 1.00f;
- SkGammas::Params* params = SkTAddOffset<SkGammas::Params>(memory, sizeof(SkGammas) +
- sizeof(float) * tableSize);
+ SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>(memory,
+ sizeof(SkGammas) + sizeof(float) * tableSize);
params->fA = 1.0f / 1.055f;
params->fB = 0.055f / 1.055f;
params->fC = 0.0f;