Index: src/core/SkColorSpace.cpp |
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp |
index cb5c8695ee0c02a5c1c3df77ec6dd522b08bbaf2..3a5d9c196a6e522637cd480fe16b6468df7beea2 100644 |
--- a/src/core/SkColorSpace.cpp |
+++ b/src/core/SkColorSpace.cpp |
@@ -68,7 +68,7 @@ static bool xyz_almost_equal(const SkMatrix44& toXYZD50, const float* standard) |
color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); |
} |
-sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44& toXYZD50) { |
+sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(const float values[3], const SkMatrix44& toXYZD50) { |
if (0.0f > values[0] || 0.0f > values[1] || 0.0f > values[2]) { |
return nullptr; |
} |
@@ -164,17 +164,25 @@ enum Version { |
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. |
+ * Should not be set at the same time as the kICC_Flag or kFloatGamma_Flag. |
*/ |
- static constexpr uint8_t kMatrix_Flag = 1 << 0; |
+ 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. |
+ * Should not be set at the same time as the kMatrix_Flag or kFloatGamma_Flag. |
*/ |
- static constexpr uint8_t kICC_Flag = 1 << 1; |
+ 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; |
static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named, |
SkColorSpace::GammaNamed gammaNamed, uint8_t flags) { |
@@ -189,7 +197,7 @@ struct ColorSpaceHeader { |
SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); |
header.fGammaNamed = (uint8_t) gammaNamed; |
- SkASSERT(flags <= kICC_Flag); |
+ SkASSERT(flags <= kFloatGamma_Flag); |
header.fFlags = flags; |
return header; |
} |
@@ -233,8 +241,26 @@ size_t SkColorSpace::writeToMemory(void* memory) const { |
return sizeof(ColorSpaceHeader) + 12 * sizeof(float); |
} |
default: |
- SkASSERT(false); |
- return 0; |
+ // Otherwise, write the gamma values and the matrix. |
+ if (memory) { |
+ *((ColorSpaceHeader*) memory) = |
+ ColorSpaceHeader::Pack(k0_Version, fNamed, 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)); |
+ |
+ fToXYZD50.as4x3ColMajorf((float*) memory); |
+ } |
+ return sizeof(ColorSpaceHeader) + 15 * sizeof(float); |
} |
} |
@@ -302,18 +328,39 @@ sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) { |
break; |
} |
- if (ColorSpaceHeader::kICC_Flag != header.fFlags || length < sizeof(uint32_t)) { |
- return nullptr; |
- } |
+ switch (header.fFlags) { |
+ case ColorSpaceHeader::kICC_Flag: { |
+ if (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; |
- } |
+ 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); |
+ } |
+ case ColorSpaceHeader::kFloatGamma_Flag: { |
+ if (length < 15 * sizeof(float)) { |
+ return nullptr; |
+ } |
- return NewICC(data, profileSize); |
+ float gammas[3]; |
+ gammas[0] = *(((const float*) data) + 0); |
+ gammas[1] = *(((const float*) data) + 1); |
+ gammas[2] = *(((const float*) data) + 2); |
+ data = SkTAddOffset<const void>(data, 3 * sizeof(float)); |
+ |
+ SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
+ toXYZ.set4x3ColMajorf((const float*) data); |
+ return SkColorSpace_Base::NewRGB(gammas, toXYZ); |
+ } |
+ default: |
+ return nullptr; |
+ } |
} |
bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { |
@@ -355,11 +402,15 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { |
case kLinear_GammaNamed: |
return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 == dst->fToXYZD50); |
default: |
- // If |src| does not have a named gamma, fProfileData should be non-null. |
- // FIXME (msarett): We may hit this case on pngs that specify float gammas. |
- // Gamma can be non-standard, but we don't have a profile |
- // to fall back on. What do we do? |
- return false; |
+ if (src->fGammaNamed != dst->fGammaNamed) { |
+ return false; |
+ } |
+ |
+ // It is unlikely that we will reach this case. |
+ sk_sp<SkData> srcData = src->serialize(); |
+ sk_sp<SkData> dstData = dst->serialize(); |
+ return srcData->size() == dstData->size() && |
+ 0 == memcmp(srcData->data(), dstData->data(), srcData->size()); |
} |
} |