Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: Source/core/platform/graphics/BitmapImage.cpp

Issue 15969015: Reland again "Decode GIF image frames on demand". (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: For landing Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698