| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 new ICOImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); | 114 new ICOImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); |
| 115 break; | 115 break; |
| 116 case SniffResult::BMP: | 116 case SniffResult::BMP: |
| 117 decoder.reset( | 117 decoder.reset( |
| 118 new BMPImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); | 118 new BMPImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); |
| 119 break; | 119 break; |
| 120 case SniffResult::Invalid: | 120 case SniffResult::Invalid: |
| 121 break; | 121 break; |
| 122 } | 122 } |
| 123 | 123 |
| 124 if (decoder) | 124 if (decoder) { |
| 125 decoder->setData(data.release(), dataComplete); | 125 decoder->setData(data.release(), dataComplete); |
| 126 decoder->m_targetColorSpace = globalTargetColorSpace(); |
| 127 } |
| 126 | 128 |
| 127 return decoder; | 129 return decoder; |
| 128 } | 130 } |
| 129 | 131 |
| 130 bool ImageDecoder::hasSufficientDataToSniffImageType(const SharedBuffer& data) { | 132 bool ImageDecoder::hasSufficientDataToSniffImageType(const SharedBuffer& data) { |
| 131 return data.size() >= kLongestSignatureLength; | 133 return data.size() >= kLongestSignatureLength; |
| 132 } | 134 } |
| 133 | 135 |
| 134 ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, | 136 ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, |
| 135 size_t length) { | 137 size_t length) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 | 369 |
| 368 namespace { | 370 namespace { |
| 369 | 371 |
| 370 // The output device color space is global and shared across multiple threads. | 372 // The output device color space is global and shared across multiple threads. |
| 371 SpinLock gTargetColorSpaceLock; | 373 SpinLock gTargetColorSpaceLock; |
| 372 SkColorSpace* gTargetColorSpace = nullptr; | 374 SkColorSpace* gTargetColorSpace = nullptr; |
| 373 | 375 |
| 374 } // namespace | 376 } // namespace |
| 375 | 377 |
| 376 // static | 378 // static |
| 377 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 379 void ImageDecoder::setGlobalTargetColorProfile(const WebVector<char>& profile) { |
| 378 if (profile.isEmpty()) | 380 if (profile.isEmpty()) |
| 379 return; | 381 return; |
| 380 | 382 |
| 381 // Take a lock around initializing and accessing the global device color | 383 // Take a lock around initializing and accessing the global device color |
| 382 // profile. | 384 // profile. |
| 383 SpinLock::Guard guard(gTargetColorSpaceLock); | 385 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 384 | 386 |
| 385 // Layout tests expect that only the first call will take effect. | 387 // Layout tests expect that only the first call will take effect. |
| 386 if (gTargetColorSpace) | 388 if (gTargetColorSpace) |
| 387 return; | 389 return; |
| 388 | 390 |
| 389 gTargetColorSpace = | 391 gTargetColorSpace = |
| 390 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); | 392 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); |
| 391 | 393 |
| 392 // UMA statistics. | 394 // UMA statistics. |
| 393 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); | 395 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); |
| 394 } | 396 } |
| 395 | 397 |
| 398 // static |
| 399 sk_sp<SkColorSpace> ImageDecoder::globalTargetColorSpace() { |
| 400 // Take a lock around initializing and accessing the global device color |
| 401 // profile. |
| 402 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 403 |
| 404 // Initialize the output device profile to sRGB if it has not yet been |
| 405 // initialized. |
| 406 if (!gTargetColorSpace) { |
| 407 gTargetColorSpace = |
| 408 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); |
| 409 } |
| 410 |
| 411 gTargetColorSpace->ref(); |
| 412 return sk_sp<SkColorSpace>(gTargetColorSpace); |
| 413 } |
| 414 |
| 396 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { | 415 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { |
| 397 // TODO(ccameron): This should always return a non-null SkColorSpace. This is | 416 // TODO(ccameron): This should always return a non-null SkColorSpace. This is |
| 398 // disabled for now because specifying a non-renderable color space results in | 417 // disabled for now because specifying a non-renderable color space results in |
| 399 // errors. | 418 // errors. |
| 400 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 | 419 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 |
| 401 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 420 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| 402 return nullptr; | 421 return nullptr; |
| 403 | 422 |
| 404 if (m_embeddedColorSpace) | 423 if (m_embeddedColorSpace) |
| 405 return m_embeddedColorSpace; | 424 return m_embeddedColorSpace; |
| 406 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 425 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
| 407 } | 426 } |
| 408 | 427 |
| 409 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 428 void ImageDecoder::setEmbeddedColorProfile(const char* iccData, |
| 410 unsigned iccLength) { | 429 unsigned iccLength) { |
| 411 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); | 430 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); |
| 412 if (!colorSpace) | 431 if (!colorSpace) |
| 413 DLOG(ERROR) << "Failed to parse image ICC profile"; | 432 DLOG(ERROR) << "Failed to parse image ICC profile"; |
| 414 setColorSpaceAndComputeTransform(std::move(colorSpace)); | 433 setEmbeddedColorSpace(std::move(colorSpace)); |
| 415 } | 434 } |
| 416 | 435 |
| 417 void ImageDecoder::setColorSpaceAndComputeTransform( | 436 void ImageDecoder::setEmbeddedColorSpace(sk_sp<SkColorSpace> colorSpace) { |
| 418 sk_sp<SkColorSpace> colorSpace) { | |
| 419 DCHECK(!m_ignoreColorSpace); | 437 DCHECK(!m_ignoreColorSpace); |
| 420 DCHECK(!m_hasHistogrammedColorSpace); | 438 DCHECK(!m_hasHistogrammedColorSpace); |
| 421 | 439 |
| 422 m_embeddedColorSpace = colorSpace; | 440 m_embeddedColorSpace = colorSpace; |
| 441 m_sourceToTargetColorTransformNeedsUpdate = true; |
| 442 } |
| 423 | 443 |
| 424 m_sourceToOutputDeviceColorTransform = nullptr; | 444 SkColorSpaceXform* ImageDecoder::colorTransform() { |
| 445 if (!m_sourceToTargetColorTransformNeedsUpdate) |
| 446 return m_sourceToTargetColorTransform.get(); |
| 447 m_sourceToTargetColorTransformNeedsUpdate = false; |
| 448 m_sourceToTargetColorTransform = nullptr; |
| 425 | 449 |
| 426 // With color correct rendering, we do not transform to the output color space | 450 // With color correct rendering, we do not transform to the output color space |
| 427 // at decode time. Instead, we tag the raw image pixels and pass the tagged | 451 // at decode time. Instead, we tag the raw image pixels and pass the tagged |
| 428 // SkImage to Skia. | 452 // SkImage to Skia. |
| 429 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 453 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| 430 return; | 454 return nullptr; |
| 431 | 455 |
| 432 if (!m_embeddedColorSpace) | 456 if (!m_embeddedColorSpace) |
| 433 return; | 457 return nullptr; |
| 434 | 458 |
| 435 // Take a lock around initializing and accessing the global device color | 459 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), |
| 436 // profile. | 460 m_targetColorSpace.get())) { |
| 437 SpinLock::Guard guard(gTargetColorSpaceLock); | 461 return nullptr; |
| 438 | |
| 439 // Initialize the output device profile to sRGB if it has not yet been | |
| 440 // initialized. | |
| 441 if (!gTargetColorSpace) { | |
| 442 gTargetColorSpace = | |
| 443 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); | |
| 444 } | 462 } |
| 445 | 463 |
| 446 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), gTargetColorSpace)) { | 464 m_sourceToTargetColorTransform = SkColorSpaceXform::New( |
| 447 return; | 465 m_embeddedColorSpace.get(), m_targetColorSpace.get()); |
| 448 } | 466 return m_sourceToTargetColorTransform.get(); |
| 449 | |
| 450 m_sourceToOutputDeviceColorTransform = | |
| 451 SkColorSpaceXform::New(m_embeddedColorSpace.get(), gTargetColorSpace); | |
| 452 } | 467 } |
| 453 | 468 |
| 454 } // namespace blink | 469 } // namespace blink |
| OLD | NEW |