| 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 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 { | 105 { |
| 106 return true; | 106 return true; |
| 107 } | 107 } |
| 108 | 108 |
| 109 bool BitmapImage::hasSingleSecurityOrigin() const | 109 bool BitmapImage::hasSingleSecurityOrigin() const |
| 110 { | 110 { |
| 111 return true; | 111 return true; |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 void BitmapImage::destroyDecodedData(bool destroyAll) | 115 void BitmapImage::destroyDecodedData() |
| 116 { | 116 { |
| 117 unsigned frameBytesCleared = 0; | 117 for (size_t i = 0; i < m_frames.size(); ++i) { |
| 118 const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFram
e; | |
| 119 | |
| 120 // Because we can advance frames without always needing to decode the actual | |
| 121 // bitmap data, |m_currentFrame| may be larger than m_frames.size(); | |
| 122 // make sure not to walk off the end of the container in this case. | |
| 123 for (size_t i = 0; i < std::min(clearBeforeFrame, m_frames.size()); ++i) { | |
| 124 // The underlying frame isn't actually changing (we're just trying to | 118 // The underlying frame isn't actually changing (we're just trying to |
| 125 // save the memory for the framebuffer data), so we don't need to clear | 119 // save the memory for the framebuffer data), so we don't need to clear |
| 126 // the metadata. | 120 // the metadata. |
| 127 unsigned frameBytes = m_frames[i].m_frameBytes; | 121 m_frames[i].clear(false); |
| 128 if (m_frames[i].clear(false)) | |
| 129 frameBytesCleared += frameBytes; | |
| 130 } | 122 } |
| 131 | 123 |
| 132 destroyMetadataAndNotify(frameBytesCleared); | 124 destroyMetadataAndNotify(m_source.clearCacheExceptFrame(m_currentFrame)); |
| 133 | |
| 134 m_source.clear(destroyAll, clearBeforeFrame, data(), m_allDataReceived); | |
| 135 return; | |
| 136 } | 125 } |
| 137 | 126 |
| 138 void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll) | 127 void BitmapImage::destroyDecodedDataIfNecessary() |
| 139 { | 128 { |
| 140 // Animated images >5MB are considered large enough that we'll only hang on | 129 // Animated images >5MB are considered large enough that we'll only hang on |
| 141 // to one frame at a time. | 130 // to one frame at a time. |
| 142 static const unsigned cLargeAnimationCutoff = 5242880; | 131 static const size_t cLargeAnimationCutoff = 5242880; |
| 143 unsigned allFrameBytes = 0; | 132 size_t allFrameBytes = 0; |
| 144 for (size_t i = 0; i < m_frames.size(); ++i) | 133 for (size_t i = 0; i < m_frames.size(); ++i) |
| 145 allFrameBytes += m_frames[i].m_frameBytes; | 134 allFrameBytes += m_frames[i].m_frameBytes; |
| 146 | 135 |
| 147 if (allFrameBytes > cLargeAnimationCutoff) | 136 if (allFrameBytes > cLargeAnimationCutoff) |
| 148 destroyDecodedData(destroyAll); | 137 destroyDecodedData(); |
| 149 } | 138 } |
| 150 | 139 |
| 151 void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared) | 140 void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared) |
| 152 { | 141 { |
| 153 m_isSolidColor = false; | 142 m_isSolidColor = false; |
| 154 m_checkedForSolidColor = false; | 143 m_checkedForSolidColor = false; |
| 155 | 144 |
| 156 ASSERT(m_decodedSize >= frameBytesCleared); | 145 ASSERT(m_decodedSize >= frameBytesCleared); |
| 157 m_decodedSize -= frameBytesCleared; | 146 m_decodedSize -= frameBytesCleared; |
| 158 if (frameBytesCleared > 0) { | 147 if (frameBytesCleared > 0) { |
| 159 frameBytesCleared += m_decodedPropertiesSize; | 148 frameBytesCleared += m_decodedPropertiesSize; |
| 160 m_decodedPropertiesSize = 0; | 149 m_decodedPropertiesSize = 0; |
| 161 } | 150 } |
| 162 if (frameBytesCleared && imageObserver()) | 151 if (frameBytesCleared && imageObserver()) |
| 163 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); | 152 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); |
| 164 } | 153 } |
| 165 | 154 |
| 166 void BitmapImage::cacheFrame(size_t index) | 155 void BitmapImage::cacheFrame(size_t index) |
| 167 { | 156 { |
| 168 size_t numFrames = frameCount(); | 157 size_t numFrames = frameCount(); |
| 169 ASSERT(m_decodedSize == 0 || numFrames > 1); | |
| 170 | |
| 171 if (m_frames.size() < numFrames) | 158 if (m_frames.size() < numFrames) |
| 172 m_frames.grow(numFrames); | 159 m_frames.grow(numFrames); |
| 173 | 160 |
| 174 m_frames[index].m_frame = m_source.createFrameAtIndex(index); | 161 m_frames[index].m_frame = m_source.createFrameAtIndex(index); |
| 175 if (numFrames == 1 && m_frames[index].m_frame) | 162 if (numFrames == 1 && m_frames[index].m_frame) |
| 176 checkForSolidColor(); | 163 checkForSolidColor(); |
| 177 | 164 |
| 178 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 165 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
| 179 m_frames[index].m_haveMetadata = true; | 166 m_frames[index].m_haveMetadata = true; |
| 180 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 167 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 | 562 |
| 576 void BitmapImage::resetAnimation() | 563 void BitmapImage::resetAnimation() |
| 577 { | 564 { |
| 578 stopAnimation(); | 565 stopAnimation(); |
| 579 m_currentFrame = 0; | 566 m_currentFrame = 0; |
| 580 m_repetitionsComplete = 0; | 567 m_repetitionsComplete = 0; |
| 581 m_desiredFrameStartTime = 0; | 568 m_desiredFrameStartTime = 0; |
| 582 m_animationFinished = false; | 569 m_animationFinished = false; |
| 583 | 570 |
| 584 // For extremely large animations, when the animation is reset, we just thro
w everything away. | 571 // For extremely large animations, when the animation is reset, we just thro
w everything away. |
| 585 destroyDecodedDataIfNecessary(true); | 572 destroyDecodedDataIfNecessary(); |
| 586 } | 573 } |
| 587 | 574 |
| 588 unsigned BitmapImage::decodedSize() const | 575 unsigned BitmapImage::decodedSize() const |
| 589 { | 576 { |
| 590 return m_decodedSize; | 577 return m_decodedSize; |
| 591 } | 578 } |
| 592 | 579 |
| 593 | 580 |
| 594 | 581 |
| 595 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) | 582 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) |
| 596 { | 583 { |
| 597 internalAdvanceAnimation(false); | 584 internalAdvanceAnimation(false); |
| 598 // At this point the image region has been marked dirty, and if it's | 585 // At this point the image region has been marked dirty, and if it's |
| 599 // onscreen, we'll soon make a call to draw(), which will call | 586 // onscreen, we'll soon make a call to draw(), which will call |
| 600 // startAnimation() again to keep the animation moving. | 587 // startAnimation() again to keep the animation moving. |
| 601 } | 588 } |
| 602 | 589 |
| 603 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) | 590 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) |
| 604 { | 591 { |
| 605 // Stop the animation. | 592 // Stop the animation. |
| 606 stopAnimation(); | 593 stopAnimation(); |
| 607 | 594 |
| 608 // See if anyone is still paying attention to this animation. If not, we do
n't | 595 // See if anyone is still paying attention to this animation. If not, we do
n't |
| 609 // advance and will remain suspended at the current frame until the animatio
n is resumed. | 596 // advance and will remain suspended at the current frame until the animatio
n is resumed. |
| 610 if (!skippingFrames && imageObserver()->shouldPauseAnimation(this)) | 597 if (!skippingFrames && imageObserver()->shouldPauseAnimation(this)) |
| 611 return false; | 598 return false; |
| 612 | 599 |
| 613 ++m_currentFrame; | 600 ++m_currentFrame; |
| 614 bool advancedAnimation = true; | 601 bool advancedAnimation = true; |
| 615 bool destroyAll = false; | |
| 616 if (m_currentFrame >= frameCount()) { | 602 if (m_currentFrame >= frameCount()) { |
| 617 ++m_repetitionsComplete; | 603 ++m_repetitionsComplete; |
| 618 | 604 |
| 619 // Get the repetition count again. If we weren't able to get a | 605 // Get the repetition count again. If we weren't able to get a |
| 620 // repetition count before, we should have decoded the whole image by | 606 // repetition count before, we should have decoded the whole image by |
| 621 // now, so it should now be available. | 607 // now, so it should now be available. |
| 622 // Note that we don't need to special-case cAnimationLoopOnce here | 608 // Note that we don't need to special-case cAnimationLoopOnce here |
| 623 // because it is 0 (see comments on its declaration in ImageSource.h). | 609 // because it is 0 (see comments on its declaration in ImageSource.h). |
| 624 if (repetitionCount(true) != cAnimationLoopInfinite && m_repetitionsComp
lete > m_repetitionCount) { | 610 if (repetitionCount(true) != cAnimationLoopInfinite && m_repetitionsComp
lete > m_repetitionCount) { |
| 625 m_animationFinished = true; | 611 m_animationFinished = true; |
| 626 m_desiredFrameStartTime = 0; | 612 m_desiredFrameStartTime = 0; |
| 627 --m_currentFrame; | 613 --m_currentFrame; |
| 628 advancedAnimation = false; | 614 advancedAnimation = false; |
| 629 } else { | 615 } else |
| 630 m_currentFrame = 0; | 616 m_currentFrame = 0; |
| 631 destroyAll = true; | |
| 632 } | |
| 633 } | 617 } |
| 634 destroyDecodedDataIfNecessary(destroyAll); | 618 destroyDecodedDataIfNecessary(); |
| 635 | 619 |
| 636 // We need to draw this frame if we advanced to it while not skipping, or if | 620 // We need to draw this frame if we advanced to it while not skipping, or if |
| 637 // while trying to skip frames we hit the last frame and thus had to stop. | 621 // while trying to skip frames we hit the last frame and thus had to stop. |
| 638 if (skippingFrames != advancedAnimation) | 622 if (skippingFrames != advancedAnimation) |
| 639 imageObserver()->animationAdvanced(this); | 623 imageObserver()->animationAdvanced(this); |
| 640 return advancedAnimation; | 624 return advancedAnimation; |
| 641 } | 625 } |
| 642 | 626 |
| 643 void BitmapImage::checkForSolidColor() | 627 void BitmapImage::checkForSolidColor() |
| 644 { | 628 { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 } | 669 } |
| 686 | 670 |
| 687 void FrameData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | 671 void FrameData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
| 688 { | 672 { |
| 689 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); | 673 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); |
| 690 memoryObjectInfo->setClassName("FrameData"); | 674 memoryObjectInfo->setClassName("FrameData"); |
| 691 info.addMember(m_frame, "frame", WTF::RetainingPointer); | 675 info.addMember(m_frame, "frame", WTF::RetainingPointer); |
| 692 } | 676 } |
| 693 | 677 |
| 694 } | 678 } |
| OLD | NEW |