| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
| 9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
| 10 #include "SkEndian.h" | 10 #include "SkEndian.h" |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && | 307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1
]), 1.00000f) && |
| 308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), | 308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2
]), 0.82491f), |
| 309 "Illuminant must be D50"); | 309 "Illuminant must be D50"); |
| 310 | 310 |
| 311 return_if_false(fTagCount <= 100, "Too many tags"); | 311 return_if_false(fTagCount <= 100, "Too many tags"); |
| 312 | 312 |
| 313 return true; | 313 return true; |
| 314 } | 314 } |
| 315 }; | 315 }; |
| 316 | 316 |
| 317 template <class T> |
| 318 static bool safe_add(T arg1, T arg2, size_t* result) { |
| 319 SkASSERT(arg1 >= 0); |
| 320 SkASSERT(arg2 >= 0); |
| 321 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { |
| 322 T sum = arg1 + arg2; |
| 323 if (sum <= std::numeric_limits<size_t>::max()) { |
| 324 *result = static_cast<size_t>(sum); |
| 325 return true; |
| 326 } |
| 327 } |
| 328 return false; |
| 329 } |
| 330 |
| 317 struct ICCTag { | 331 struct ICCTag { |
| 318 uint32_t fSignature; | 332 uint32_t fSignature; |
| 319 uint32_t fOffset; | 333 uint32_t fOffset; |
| 320 uint32_t fLength; | 334 uint32_t fLength; |
| 321 | 335 |
| 322 const uint8_t* init(const uint8_t* src) { | 336 const uint8_t* init(const uint8_t* src) { |
| 323 fSignature = read_big_endian_uint(src); | 337 fSignature = read_big_endian_uint(src); |
| 324 fOffset = read_big_endian_uint(src + 4); | 338 fOffset = read_big_endian_uint(src + 4); |
| 325 fLength = read_big_endian_uint(src + 8); | 339 fLength = read_big_endian_uint(src + 8); |
| 326 return src + 12; | 340 return src + 12; |
| 327 } | 341 } |
| 328 | 342 |
| 329 bool valid(size_t len) { | 343 bool valid(size_t len) { |
| 330 return_if_false(fOffset + fLength <= len, "Tag too large for ICC profile
"); | 344 size_t tagEnd; |
| 345 return_if_false(safe_add(fOffset, fLength, &tagEnd), |
| 346 "Tag too large, overflows integer addition"); |
| 347 return_if_false(tagEnd <= len, "Tag too large for ICC profile"); |
| 331 return true; | 348 return true; |
| 332 } | 349 } |
| 333 | 350 |
| 334 const uint8_t* addr(const uint8_t* src) const { | 351 const uint8_t* addr(const uint8_t* src) const { |
| 335 return src + fOffset; | 352 return src + fOffset; |
| 336 } | 353 } |
| 337 | 354 |
| 338 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature
) { | 355 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature
) { |
| 339 for (int i = 0; i < count; ++i) { | 356 for (int i = 0; i < count; ++i) { |
| 340 if (tags[i].fSignature == signature) { | 357 if (tags[i].fSignature == signature) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 359 return false; | 376 return false; |
| 360 } | 377 } |
| 361 | 378 |
| 362 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 379 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); |
| 363 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 380 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); |
| 364 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 381 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); |
| 365 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 382 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); |
| 366 return true; | 383 return true; |
| 367 } | 384 } |
| 368 | 385 |
| 369 template <class T> | |
| 370 static bool safe_add(T arg1, T arg2, size_t* result) { | |
| 371 SkASSERT(arg1 >= 0); | |
| 372 SkASSERT(arg2 >= 0); | |
| 373 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { | |
| 374 T sum = arg1 + arg2; | |
| 375 if (sum <= std::numeric_limits<size_t>::max()) { | |
| 376 *result = static_cast<size_t>(sum); | |
| 377 return true; | |
| 378 } | |
| 379 } | |
| 380 return false; | |
| 381 } | |
| 382 | |
| 383 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); | 386 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', '
v'); |
| 384 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); | 387 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
a'); |
| 385 | 388 |
| 386 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { | 389 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { |
| 387 for (uint32_t i = 0; i < numGammas; i++) { | 390 for (uint32_t i = 0; i < numGammas; i++) { |
| 388 if (len < 12) { | 391 if (len < 12) { |
| 389 // FIXME (msarett): | 392 // FIXME (msarett): |
| 390 // We could potentially return false here after correctly parsing *s
ome* of the | 393 // We could potentially return false here after correctly parsing *s
ome* of the |
| 391 // gammas correctly. Should we somehow try to indicate a partial su
ccess? | 394 // gammas correctly. Should we somehow try to indicate a partial su
ccess? |
| 392 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 395 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 if (0 != offsetToMatrix && offsetToMatrix < len) { | 804 if (0 != offsetToMatrix && offsetToMatrix < len) { |
| 802 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { | 805 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { |
| 803 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 806 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
| 804 } | 807 } |
| 805 } | 808 } |
| 806 | 809 |
| 807 return true; | 810 return true; |
| 808 } | 811 } |
| 809 | 812 |
| 810 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { | 813 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { |
| 811 if (len < kICCHeaderSize) { | 814 if (!input || len < kICCHeaderSize) { |
| 812 return_null("Data is not large enough to contain an ICC profile"); | 815 return_null("Data is null or not large enough to contain an ICC profile"
); |
| 813 } | 816 } |
| 814 | 817 |
| 815 // Create our own copy of the input. | 818 // Create our own copy of the input. |
| 816 void* memory = sk_malloc_throw(len); | 819 void* memory = sk_malloc_throw(len); |
| 817 memcpy(memory, input, len); | 820 memcpy(memory, input, len); |
| 818 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); | 821 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); |
| 819 const void* base = data->data(); | 822 const void* base = data->data(); |
| 820 const uint8_t* ptr = (const uint8_t*) base; | 823 const uint8_t* ptr = (const uint8_t*) base; |
| 821 | 824 |
| 822 // Read the ICC profile header and check to make sure that it is valid. | 825 // Read the ICC profile header and check to make sure that it is valid. |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1141 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
| 1139 ptr += kTAG_XYZ_Bytes; | 1142 ptr += kTAG_XYZ_Bytes; |
| 1140 | 1143 |
| 1141 // Write copyright tag | 1144 // Write copyright tag |
| 1142 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1145 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
| 1143 | 1146 |
| 1144 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1147 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
| 1145 // the client calls again? | 1148 // the client calls again? |
| 1146 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1149 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
| 1147 } | 1150 } |
| OLD | NEW |