Index: src/core/SkColorSpace.cpp |
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp |
index 59013fe7cb0be04cad45c7194ffab0ea1741c8f9..52e4ced85de270dc2c1d06a2c7feb550c017a2dc 100644 |
--- a/src/core/SkColorSpace.cpp |
+++ b/src/core/SkColorSpace.cpp |
@@ -362,7 +362,7 @@ bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const ui |
// a count of 0. |
gammas[i].fValue = 1.0f; |
break; |
- } else if (len < 12 + 2 * count) { |
+ } else if (len < tagBytes) { |
SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
return false; |
} |
@@ -429,27 +429,93 @@ bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const ui |
break; |
} |
case kTAG_ParaCurveType: |
- // Guess 2.2f. |
- // FIXME (msarett): Handle parametric curves. |
- SkColorSpacePrintf("parametric curve\n"); |
- gammas[i].fValue = 2.2f; |
- |
- // Determine the size of the parametric curve tag. |
+ // Determine the format of the parametric curve tag. |
switch(read_big_endian_short(src + 8)) { |
- case 0: |
+ case 0: { |
tagBytes = 12 + 4; |
+ if (len < tagBytes) { |
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
+ return false; |
+ } |
+ |
+ // Y = X^g |
+ int32_t g = read_big_endian_int(src + 12); |
+ gammas[i].fValue = SkFixedToFloat(g); |
break; |
- case 1: |
+ } |
+ |
+ // Here's where the real parametric gammas start. There are many |
+ // permutations of the same equations. |
+ // |
+ // Y = (aX + b)^g + c for X >= d |
+ // Y = eX + f otherwise |
+ // |
+ // We will fill in with zeros as necessary to always match the above form. |
+ // Note that there is no need to actually write zero, since the struct is |
+ // zero initialized. |
+ case 1: { |
tagBytes = 12 + 12; |
+ if (len < tagBytes) { |
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
+ return false; |
+ } |
+ |
+ // Y = (aX + b)^g for X >= -b/a |
+ // Y = 0 otherwise |
+ gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); |
+ gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); |
+ gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); |
+ gammas[i].fD = -gammas[i].fB / gammas[i].fA; |
break; |
+ } |
case 2: |
tagBytes = 12 + 16; |
+ if (len < tagBytes) { |
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
+ return false; |
+ } |
+ |
+ // Y = (aX + b)^g + c for X >= -b/a |
+ // Y = c otherwise |
+ gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); |
+ gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); |
+ gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); |
+ gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24)); |
+ gammas[i].fD = -gammas[i].fB / gammas[i].fA; |
+ gammas[i].fF = gammas[i].fC; |
break; |
case 3: |
tagBytes = 12 + 20; |
+ if (len < tagBytes) { |
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
+ return false; |
+ } |
+ |
+ // Y = (aX + b)^g for X >= d |
+ // Y = cX otherwise |
+ gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); |
+ gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); |
+ gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); |
+ gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28)); |
+ gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 24)); |
break; |
case 4: |
tagBytes = 12 + 28; |
+ if (len < tagBytes) { |
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
+ return false; |
+ } |
+ |
+ // Y = (aX + b)^g + c for X >= d |
+ // Y = eX + f otherwise |
+ // NOTE: The ICC spec writes "cX" instead of "eX" but I think it's a typo. |
+ gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); |
+ gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); |
+ gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); |
+ gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24)); |
+ gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28)); |
+ gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 32)); |
+ gammas[i].fF = SkFixedToFloat(read_big_endian_int(src + 36)); |
break; |
default: |
SkColorSpacePrintf("Invalid parametric curve type\n"); |