| 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 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 | 416 |
| 415 namespace { | 417 namespace { |
| 416 | 418 |
| 417 // The output device color space is global and shared across multiple threads. | 419 // The output device color space is global and shared across multiple threads. |
| 418 SpinLock gTargetColorSpaceLock; | 420 SpinLock gTargetColorSpaceLock; |
| 419 SkColorSpace* gTargetColorSpace = nullptr; | 421 SkColorSpace* gTargetColorSpace = nullptr; |
| 420 | 422 |
| 421 } // namespace | 423 } // namespace |
| 422 | 424 |
| 423 // static | 425 // static |
| 424 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 426 void ImageDecoder::setGlobalTargetColorProfile(const WebVector<char>& profile) { |
| 425 if (profile.isEmpty()) | 427 if (profile.isEmpty()) |
| 426 return; | 428 return; |
| 427 | 429 |
| 428 // Take a lock around initializing and accessing the global device color | 430 // Take a lock around initializing and accessing the global device color |
| 429 // profile. | 431 // profile. |
| 430 SpinLock::Guard guard(gTargetColorSpaceLock); | 432 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 431 | 433 |
| 432 // Layout tests expect that only the first call will take effect. | 434 // Layout tests expect that only the first call will take effect. |
| 433 if (gTargetColorSpace) | 435 if (gTargetColorSpace) |
| 434 return; | 436 return; |
| 435 | 437 |
| 436 gTargetColorSpace = | 438 gTargetColorSpace = |
| 437 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); | 439 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); |
| 438 | 440 |
| 439 // UMA statistics. | 441 // UMA statistics. |
| 440 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); | 442 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); |
| 441 } | 443 } |
| 442 | 444 |
| 445 // static |
| 446 sk_sp<SkColorSpace> ImageDecoder::globalTargetColorSpace() { |
| 447 // Take a lock around initializing and accessing the global device color |
| 448 // profile. |
| 449 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 450 |
| 451 // Initialize the output device profile to sRGB if it has not yet been |
| 452 // initialized. |
| 453 if (!gTargetColorSpace) { |
| 454 gTargetColorSpace = |
| 455 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); |
| 456 } |
| 457 |
| 458 gTargetColorSpace->ref(); |
| 459 return sk_sp<SkColorSpace>(gTargetColorSpace); |
| 460 } |
| 461 |
| 443 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { | 462 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { |
| 444 // TODO(ccameron): This should always return a non-null SkColorSpace. This is | 463 // TODO(ccameron): This should always return a non-null SkColorSpace. This is |
| 445 // disabled for now because specifying a non-renderable color space results in | 464 // disabled for now because specifying a non-renderable color space results in |
| 446 // errors. | 465 // errors. |
| 447 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 | 466 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 |
| 448 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 467 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| 449 return nullptr; | 468 return nullptr; |
| 450 | 469 |
| 451 if (m_embeddedColorSpace) | 470 if (m_embeddedColorSpace) |
| 452 return m_embeddedColorSpace; | 471 return m_embeddedColorSpace; |
| 453 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 472 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
| 454 } | 473 } |
| 455 | 474 |
| 456 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 475 void ImageDecoder::setEmbeddedColorProfile(const char* iccData, |
| 457 unsigned iccLength) { | 476 unsigned iccLength) { |
| 458 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); | 477 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); |
| 459 if (!colorSpace) | 478 if (!colorSpace) |
| 460 DLOG(ERROR) << "Failed to parse image ICC profile"; | 479 DLOG(ERROR) << "Failed to parse image ICC profile"; |
| 461 setColorSpaceAndComputeTransform(std::move(colorSpace)); | 480 setEmbeddedColorSpace(std::move(colorSpace)); |
| 462 } | 481 } |
| 463 | 482 |
| 464 void ImageDecoder::setColorSpaceAndComputeTransform( | 483 void ImageDecoder::setEmbeddedColorSpace(sk_sp<SkColorSpace> colorSpace) { |
| 465 sk_sp<SkColorSpace> colorSpace) { | |
| 466 DCHECK(!m_ignoreColorSpace); | 484 DCHECK(!m_ignoreColorSpace); |
| 467 DCHECK(!m_hasHistogrammedColorSpace); | 485 DCHECK(!m_hasHistogrammedColorSpace); |
| 468 | 486 |
| 469 m_embeddedColorSpace = colorSpace; | 487 m_embeddedColorSpace = colorSpace; |
| 488 m_sourceToTargetColorTransformNeedsUpdate = true; |
| 489 } |
| 470 | 490 |
| 471 m_sourceToOutputDeviceColorTransform = nullptr; | 491 SkColorSpaceXform* ImageDecoder::colorTransform() { |
| 492 if (!m_sourceToTargetColorTransformNeedsUpdate) |
| 493 return m_sourceToTargetColorTransform.get(); |
| 494 m_sourceToTargetColorTransformNeedsUpdate = false; |
| 495 m_sourceToTargetColorTransform = nullptr; |
| 472 | 496 |
| 473 // With color correct rendering, we do not transform to the output color space | 497 // With color correct rendering, we do not transform to the output color space |
| 474 // at decode time. Instead, we tag the raw image pixels and pass the tagged | 498 // at decode time. Instead, we tag the raw image pixels and pass the tagged |
| 475 // SkImage to Skia. | 499 // SkImage to Skia. |
| 476 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 500 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| 477 return; | 501 return nullptr; |
| 478 | 502 |
| 479 if (!m_embeddedColorSpace) | 503 if (!m_embeddedColorSpace) |
| 480 return; | 504 return nullptr; |
| 481 | 505 |
| 482 // Take a lock around initializing and accessing the global device color | 506 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), |
| 483 // profile. | 507 m_targetColorSpace.get())) { |
| 484 SpinLock::Guard guard(gTargetColorSpaceLock); | 508 return nullptr; |
| 485 | |
| 486 // Initialize the output device profile to sRGB if it has not yet been | |
| 487 // initialized. | |
| 488 if (!gTargetColorSpace) { | |
| 489 gTargetColorSpace = | |
| 490 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); | |
| 491 } | 509 } |
| 492 | 510 |
| 493 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), gTargetColorSpace)) { | 511 m_sourceToTargetColorTransform = SkColorSpaceXform::New( |
| 494 return; | 512 m_embeddedColorSpace.get(), m_targetColorSpace.get()); |
| 495 } | 513 return m_sourceToTargetColorTransform.get(); |
| 496 | |
| 497 m_sourceToOutputDeviceColorTransform = | |
| 498 SkColorSpaceXform::New(m_embeddedColorSpace.get(), gTargetColorSpace); | |
| 499 } | 514 } |
| 500 | 515 |
| 501 } // namespace blink | 516 } // namespace blink |
| OLD | NEW |