OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. | 3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * | 13 * |
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "platform/graphics/BitmapImage.h" | 27 #include "platform/graphics/BitmapImage.h" |
28 | 28 |
29 #include "platform/PlatformInstrumentation.h" | 29 #include "platform/PlatformInstrumentation.h" |
| 30 #include "platform/RuntimeEnabledFeatures.h" |
30 #include "platform/Timer.h" | 31 #include "platform/Timer.h" |
31 #include "platform/geometry/FloatRect.h" | 32 #include "platform/geometry/FloatRect.h" |
32 #include "platform/graphics/BitmapImageMetrics.h" | 33 #include "platform/graphics/BitmapImageMetrics.h" |
33 #include "platform/graphics/DeferredImageDecoder.h" | 34 #include "platform/graphics/DeferredImageDecoder.h" |
34 #include "platform/graphics/ImageObserver.h" | 35 #include "platform/graphics/ImageObserver.h" |
35 #include "platform/graphics/StaticBitmapImage.h" | 36 #include "platform/graphics/StaticBitmapImage.h" |
36 #include "platform/graphics/skia/SkiaUtils.h" | 37 #include "platform/graphics/skia/SkiaUtils.h" |
37 #include "platform/tracing/TraceEvent.h" | 38 #include "platform/tracing/TraceEvent.h" |
38 #include "third_party/skia/include/core/SkCanvas.h" | 39 #include "third_party/skia/include/core/SkCanvas.h" |
39 #include "wtf/PassRefPtr.h" | 40 #include "wtf/PassRefPtr.h" |
40 #include "wtf/PtrUtil.h" | 41 #include "wtf/PtrUtil.h" |
41 #include "wtf/text/WTFString.h" | 42 #include "wtf/text/WTFString.h" |
42 | 43 |
43 namespace blink { | 44 namespace blink { |
44 | 45 |
| 46 namespace { |
| 47 |
| 48 ColorBehavior defaultColorBehavior() { |
| 49 // TODO(ccameron): ColorBehavior should be specified by the caller requesting |
| 50 // SkImages. |
| 51 // https://crbug.com/667420 |
| 52 if (RuntimeEnabledFeatures::trueColorRenderingEnabled()) |
| 53 return ColorBehavior::tag(); |
| 54 return ColorBehavior::transformToGlobalTarget(); |
| 55 } |
| 56 |
| 57 } // namespace |
| 58 |
45 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting( | 59 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting( |
46 const SkBitmap& bitmap, | 60 const SkBitmap& bitmap, |
47 ImageOrientation orientation) { | 61 ImageOrientation orientation) { |
48 if (bitmap.isNull()) { | 62 if (bitmap.isNull()) { |
49 return BitmapImage::create(); | 63 return BitmapImage::create(); |
50 } | 64 } |
51 | 65 |
52 RefPtr<BitmapImage> result = adoptRef(new BitmapImage(bitmap)); | 66 RefPtr<BitmapImage> result = adoptRef(new BitmapImage(bitmap)); |
53 result->m_frames[0].m_orientation = orientation; | 67 result->m_frames[0].m_orientation = orientation; |
54 if (orientation.usesWidthAsHeight()) | 68 if (orientation.usesWidthAsHeight()) |
55 result->m_sizeRespectingOrientation = result->m_size.transposedSize(); | 69 result->m_sizeRespectingOrientation = result->m_size.transposedSize(); |
56 return result.release(); | 70 return result.release(); |
57 } | 71 } |
58 | 72 |
59 BitmapImage::BitmapImage(ImageObserver* observer) | 73 BitmapImage::BitmapImage(ImageObserver* observer) |
60 : Image(observer), | 74 : Image(observer), |
61 m_currentFrame(0), | 75 m_currentFrame(0), |
62 m_cachedFrameIndex(0), | 76 m_cachedFrameIndex(0), |
| 77 m_cachedFrameColorBehavior(defaultColorBehavior()), |
63 m_repetitionCount(cAnimationNone), | 78 m_repetitionCount(cAnimationNone), |
64 m_repetitionCountStatus(Unknown), | 79 m_repetitionCountStatus(Unknown), |
65 m_repetitionsComplete(0), | 80 m_repetitionsComplete(0), |
66 m_desiredFrameStartTime(0), | 81 m_desiredFrameStartTime(0), |
67 m_frameCount(0), | 82 m_frameCount(0), |
68 m_animationPolicy(ImageAnimationPolicyAllowed), | 83 m_animationPolicy(ImageAnimationPolicyAllowed), |
69 m_animationFinished(false), | 84 m_animationFinished(false), |
70 m_allDataReceived(false), | 85 m_allDataReceived(false), |
71 m_haveSize(false), | 86 m_haveSize(false), |
72 m_sizeAvailable(false), | 87 m_sizeAvailable(false), |
73 m_haveFrameCount(false) {} | 88 m_haveFrameCount(false) {} |
74 | 89 |
75 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer) | 90 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer) |
76 : Image(observer), | 91 : Image(observer), |
77 m_size(bitmap.width(), bitmap.height()), | 92 m_size(bitmap.width(), bitmap.height()), |
78 m_currentFrame(0), | 93 m_currentFrame(0), |
79 m_cachedFrame(SkImage::MakeFromBitmap(bitmap)), | 94 m_cachedFrame(SkImage::MakeFromBitmap(bitmap)), |
80 m_cachedFrameIndex(0), | 95 m_cachedFrameIndex(0), |
| 96 m_cachedFrameColorBehavior(defaultColorBehavior()), |
81 m_repetitionCount(cAnimationNone), | 97 m_repetitionCount(cAnimationNone), |
82 m_repetitionCountStatus(Unknown), | 98 m_repetitionCountStatus(Unknown), |
83 m_repetitionsComplete(0), | 99 m_repetitionsComplete(0), |
84 m_frameCount(1), | 100 m_frameCount(1), |
85 m_animationPolicy(ImageAnimationPolicyAllowed), | 101 m_animationPolicy(ImageAnimationPolicyAllowed), |
86 m_animationFinished(true), | 102 m_animationFinished(true), |
87 m_allDataReceived(true), | 103 m_allDataReceived(true), |
88 m_haveSize(true), | 104 m_haveSize(true), |
89 m_sizeAvailable(true), | 105 m_sizeAvailable(true), |
90 m_haveFrameCount(true) { | 106 m_haveFrameCount(true) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 } | 139 } |
124 | 140 |
125 size_t BitmapImage::totalFrameBytes() { | 141 size_t BitmapImage::totalFrameBytes() { |
126 const size_t numFrames = frameCount(); | 142 const size_t numFrames = frameCount(); |
127 size_t totalBytes = 0; | 143 size_t totalBytes = 0; |
128 for (size_t i = 0; i < numFrames; ++i) | 144 for (size_t i = 0; i < numFrames; ++i) |
129 totalBytes += m_source.frameBytesAtIndex(i); | 145 totalBytes += m_source.frameBytesAtIndex(i); |
130 return totalBytes; | 146 return totalBytes; |
131 } | 147 } |
132 | 148 |
133 sk_sp<SkImage> BitmapImage::decodeAndCacheFrame(size_t index) { | 149 sk_sp<SkImage> BitmapImage::decodeAndCacheFrame( |
| 150 size_t index, |
| 151 const ColorBehavior& colorBehavior) { |
134 size_t numFrames = frameCount(); | 152 size_t numFrames = frameCount(); |
135 if (m_frames.size() < numFrames) | 153 if (m_frames.size() < numFrames) |
136 m_frames.grow(numFrames); | 154 m_frames.grow(numFrames); |
137 | 155 |
138 // We are caching frame snapshots. This is OK even for partially decoded | 156 // We are caching frame snapshots. This is OK even for partially decoded |
139 // frames, as they are cleared by dataChanged() when new data arrives. | 157 // frames, as they are cleared by dataChanged() when new data arrives. |
140 sk_sp<SkImage> image = m_source.createFrameAtIndex(index); | 158 sk_sp<SkImage> image = m_source.createFrameAtIndex(index, colorBehavior); |
141 m_cachedFrame = image; | 159 m_cachedFrame = image; |
142 m_cachedFrameIndex = index; | 160 m_cachedFrameIndex = index; |
| 161 m_cachedFrameColorBehavior = colorBehavior; |
143 | 162 |
144 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 163 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
145 m_frames[index].m_haveMetadata = true; | 164 m_frames[index].m_haveMetadata = true; |
146 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 165 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); |
147 if (repetitionCount(false) != cAnimationNone) | 166 if (repetitionCount(false) != cAnimationNone) |
148 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); | 167 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); |
149 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); | 168 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); |
150 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); | 169 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); |
151 | 170 |
152 notifyMemoryChanged(); | 171 notifyMemoryChanged(); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 if (m_sizeAvailable && hasVisibleImageSize(size())) { | 336 if (m_sizeAvailable && hasVisibleImageSize(size())) { |
318 BitmapImageMetrics::countDecodedImageType(m_source.filenameExtension()); | 337 BitmapImageMetrics::countDecodedImageType(m_source.filenameExtension()); |
319 if (m_source.filenameExtension() == "jpg") | 338 if (m_source.filenameExtension() == "jpg") |
320 BitmapImageMetrics::countImageOrientation( | 339 BitmapImageMetrics::countImageOrientation( |
321 m_source.orientationAtIndex(0).orientation()); | 340 m_source.orientationAtIndex(0).orientation()); |
322 } | 341 } |
323 | 342 |
324 return m_sizeAvailable; | 343 return m_sizeAvailable; |
325 } | 344 } |
326 | 345 |
327 sk_sp<SkImage> BitmapImage::frameAtIndex(size_t index) { | 346 sk_sp<SkImage> BitmapImage::frameAtIndex(size_t index, |
| 347 const ColorBehavior& colorBehavior) { |
328 if (index >= frameCount()) | 348 if (index >= frameCount()) |
329 return nullptr; | 349 return nullptr; |
330 | 350 |
331 if (index == m_cachedFrameIndex && m_cachedFrame) | 351 if (index == m_cachedFrameIndex && m_cachedFrame && |
| 352 m_cachedFrameColorBehavior == colorBehavior) |
332 return m_cachedFrame; | 353 return m_cachedFrame; |
333 | 354 |
334 return decodeAndCacheFrame(index); | 355 return decodeAndCacheFrame(index, colorBehavior); |
335 } | 356 } |
336 | 357 |
337 bool BitmapImage::frameIsCompleteAtIndex(size_t index) const { | 358 bool BitmapImage::frameIsCompleteAtIndex(size_t index) const { |
338 if (index < m_frames.size() && m_frames[index].m_haveMetadata && | 359 if (index < m_frames.size() && m_frames[index].m_haveMetadata && |
339 m_frames[index].m_isComplete) | 360 m_frames[index].m_isComplete) |
340 return true; | 361 return true; |
341 | 362 |
342 return m_source.frameIsCompleteAtIndex(index); | 363 return m_source.frameIsCompleteAtIndex(index); |
343 } | 364 } |
344 | 365 |
345 float BitmapImage::frameDurationAtIndex(size_t index) const { | 366 float BitmapImage::frameDurationAtIndex(size_t index) const { |
346 if (index < m_frames.size() && m_frames[index].m_haveMetadata) | 367 if (index < m_frames.size() && m_frames[index].m_haveMetadata) |
347 return m_frames[index].m_duration; | 368 return m_frames[index].m_duration; |
348 | 369 |
349 return m_source.frameDurationAtIndex(index); | 370 return m_source.frameDurationAtIndex(index); |
350 } | 371 } |
351 | 372 |
352 sk_sp<SkImage> BitmapImage::imageForCurrentFrame() { | 373 sk_sp<SkImage> BitmapImage::imageForCurrentFrame() { |
353 return frameAtIndex(currentFrame()); | 374 // TODO(ccameron): Allow the caller of imageForCurrentFrame to specify the |
| 375 // the desired ColorBehavior. |
| 376 // https://crbug.com/667420 |
| 377 const ColorBehavior& colorBehavior = m_cachedFrameColorBehavior; |
| 378 return frameAtIndex(currentFrame(), colorBehavior); |
354 } | 379 } |
355 | 380 |
356 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() { | 381 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() { |
| 382 // TODO(ccameron): Determine the appropriate ColorBehavior for this situation. |
| 383 // https://crbug.com/667420 |
| 384 const ColorBehavior& colorBehavior = m_cachedFrameColorBehavior; |
357 if (frameCount() > 1) { | 385 if (frameCount() > 1) { |
358 sk_sp<SkImage> firstFrame = frameAtIndex(0); | 386 sk_sp<SkImage> firstFrame = frameAtIndex(0, colorBehavior); |
359 if (firstFrame) | 387 if (firstFrame) |
360 return StaticBitmapImage::create(std::move(firstFrame)); | 388 return StaticBitmapImage::create(std::move(firstFrame)); |
361 } | 389 } |
362 | 390 |
363 return Image::imageForDefaultFrame(); | 391 return Image::imageForDefaultFrame(); |
364 } | 392 } |
365 | 393 |
366 bool BitmapImage::frameHasAlphaAtIndex(size_t index) { | 394 bool BitmapImage::frameHasAlphaAtIndex(size_t index) { |
367 if (m_frames.size() <= index) | 395 if (m_frames.size() <= index) |
368 return true; | 396 return true; |
369 | 397 |
370 if (m_frames[index].m_haveMetadata && !m_frames[index].m_hasAlpha) | 398 if (m_frames[index].m_haveMetadata && !m_frames[index].m_hasAlpha) |
371 return false; | 399 return false; |
372 | 400 |
373 // m_hasAlpha may change after m_haveMetadata is set to true, so always ask | 401 // m_hasAlpha may change after m_haveMetadata is set to true, so always ask |
374 // ImageSource for the value if the cached value is the default value. | 402 // ImageSource for the value if the cached value is the default value. |
375 bool hasAlpha = m_source.frameHasAlphaAtIndex(index); | 403 bool hasAlpha = m_source.frameHasAlphaAtIndex(index); |
376 | 404 |
377 if (m_frames[index].m_haveMetadata) | 405 if (m_frames[index].m_haveMetadata) |
378 m_frames[index].m_hasAlpha = hasAlpha; | 406 m_frames[index].m_hasAlpha = hasAlpha; |
379 | 407 |
380 return hasAlpha; | 408 return hasAlpha; |
381 } | 409 } |
382 | 410 |
383 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) { | 411 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) { |
384 if (metadataMode == PreCacheMetadata) { | 412 if (metadataMode == PreCacheMetadata) { |
385 // frameHasAlphaAtIndex() conservatively returns false for uncached frames. | 413 // frameHasAlphaAtIndex() conservatively returns false for uncached frames. |
386 // To increase the chance of an accurate answer, pre-cache the current frame | 414 // To increase the chance of an accurate answer, pre-cache the current frame |
387 // metadata. | 415 // metadata. Because ColorBehavior does not affect this result, use |
388 frameAtIndex(currentFrame()); | 416 // whatever ColorBehavior was last used (if any). |
| 417 frameAtIndex(currentFrame(), m_cachedFrameColorBehavior); |
389 } | 418 } |
390 return !frameHasAlphaAtIndex(currentFrame()); | 419 return !frameHasAlphaAtIndex(currentFrame()); |
391 } | 420 } |
392 | 421 |
393 bool BitmapImage::currentFrameIsComplete() { | 422 bool BitmapImage::currentFrameIsComplete() { |
394 return frameIsCompleteAtIndex(currentFrame()); | 423 return frameIsCompleteAtIndex(currentFrame()); |
395 } | 424 } |
396 | 425 |
397 bool BitmapImage::currentFrameIsLazyDecoded() { | 426 bool BitmapImage::currentFrameIsLazyDecoded() { |
398 sk_sp<SkImage> image = frameAtIndex(currentFrame()); | 427 // Because ColorBehavior does not affect this result, use whatever |
| 428 // ColorBehavior was last used (if any). |
| 429 sk_sp<SkImage> image = |
| 430 frameAtIndex(currentFrame(), m_cachedFrameColorBehavior); |
399 return image && image->isLazyGenerated(); | 431 return image && image->isLazyGenerated(); |
400 } | 432 } |
401 | 433 |
402 ImageOrientation BitmapImage::currentFrameOrientation() { | 434 ImageOrientation BitmapImage::currentFrameOrientation() { |
403 return frameOrientationAtIndex(currentFrame()); | 435 return frameOrientationAtIndex(currentFrame()); |
404 } | 436 } |
405 | 437 |
406 ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index) { | 438 ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index) { |
407 if (m_frames.size() <= index) | 439 if (m_frames.size() <= index) |
408 return DefaultImageOrientation; | 440 return DefaultImageOrientation; |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 getImageObserver()->animationAdvanced(this); | 653 getImageObserver()->animationAdvanced(this); |
622 | 654 |
623 return true; | 655 return true; |
624 } | 656 } |
625 | 657 |
626 void BitmapImage::notifyObserversOfAnimationAdvance(TimerBase*) { | 658 void BitmapImage::notifyObserversOfAnimationAdvance(TimerBase*) { |
627 getImageObserver()->animationAdvanced(this); | 659 getImageObserver()->animationAdvanced(this); |
628 } | 660 } |
629 | 661 |
630 } // namespace blink | 662 } // namespace blink |
OLD | NEW |