diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index 3a81d276a8..1652de37a8 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -427,6 +427,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // The table entry is the gamma (with a bias of 256). uint16_t value = read_big_endian_short((const uint8_t*) table); gammas[i].fValue = value / 256.0f; + if (0.0f == gammas[i].fValue) { + SkColorSpacePrintf("Cannot have zero gamma value"); + return false; + } SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue); break; } @@ -525,6 +529,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // Y = 0 otherwise g = SkFixedToFloat(read_big_endian_int(src + 12)); a = SkFixedToFloat(read_big_endian_int(src + 16)); + if (0.0f == a) { + return false; + } + b = SkFixedToFloat(read_big_endian_int(src + 20)); d = -b / a; break; @@ -540,6 +548,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // Y = c otherwise g = SkFixedToFloat(read_big_endian_int(src + 12)); a = SkFixedToFloat(read_big_endian_int(src + 16)); + if (0.0f == a) { + return false; + } + b = SkFixedToFloat(read_big_endian_int(src + 20)); c = SkFixedToFloat(read_big_endian_int(src + 24)); d = -b / a; @@ -594,6 +606,27 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s color_space_almost_equal(2.4000f, g)) { gammas[i].fValue = 2.2f; } else { + // Fail on invalid gammas. + 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 false; + } + } else if (d >= 1.0f) { + // Y = eX + f for always + if (0.0f == e) { + SkColorSpacePrintf("E is zero, constant gamma function is " + "nonsense"); + return false; + } + } else if ((0.0f == a || 0.0f == g) && 0.0f == e) { + SkColorSpacePrintf("A or G, and E are zero, constant gamma function " + "is nonsense"); + return false; + } + gammas[i].fG = g; gammas[i].fA = a; gammas[i].fB = b; @@ -611,6 +644,9 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s return false; } + // Ensure that we have successfully read a gamma representation. + SkASSERT(gammas[i].isValue() || gammas[i].isTable() || gammas[i].isParametric()); + // Adjust src and len if there is another gamma curve to load. if (i != numGammas - 1) { // Each curve is padded to 4-byte alignment. diff --git a/src/core/SkColorSpace_Base.h b/src/core/SkColorSpace_Base.h index b2d5818e84..68514d0ad6 100644 --- a/src/core/SkColorSpace_Base.h +++ b/src/core/SkColorSpace_Base.h @@ -16,20 +16,20 @@ struct SkGammaCurve { bool isValue() const { bool result = (0.0f != fValue); SkASSERT(!result || (0 == fTableSize)); - SkASSERT(!result || (0.0f == fG)); + SkASSERT(!result || (0.0f == fG && 0.0f == fE)); return result; } bool isTable() const { bool result = (0 != fTableSize); SkASSERT(!result || (0.0f == fValue)); - SkASSERT(!result || (0.0f == fG)); + SkASSERT(!result || (0.0f == fG && 0.0f == fE)); SkASSERT(!result || fTable); return result; } bool isParametric() const { - bool result = (0.0f != fG); + bool result = (0.0f != fG || 0.0f != fE); SkASSERT(!result || (0.0f == fValue)); SkASSERT(!result || (0 == fTableSize)); return result;