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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/BitmapImage.cpp

Issue 1962563002: Fix ImageDecoder::frameIsCompleteAtIndex - fully received instead of decoded. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 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
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 m_frames.grow(numFrames); 139 m_frames.grow(numFrames);
140 140
141 // We are caching frame snapshots. This is OK even for partially decoded fr ames, 141 // We are caching frame snapshots. This is OK even for partially decoded fr ames,
142 // as they are cleared by dataChanged() when new data arrives. 142 // as they are cleared by dataChanged() when new data arrives.
143 RefPtr<SkImage> image = m_source.createFrameAtIndex(index); 143 RefPtr<SkImage> image = m_source.createFrameAtIndex(index);
144 m_cachedFrame = image; 144 m_cachedFrame = image;
145 m_cachedFrameIndex = index; 145 m_cachedFrameIndex = index;
146 146
147 m_frames[index].m_orientation = m_source.orientationAtIndex(index); 147 m_frames[index].m_orientation = m_source.orientationAtIndex(index);
148 m_frames[index].m_haveMetadata = true; 148 m_frames[index].m_haveMetadata = true;
149 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); 149 m_frames[index].m_isFullyReceived = m_source.frameIsFullyReceivedAtIndex(ind ex);
150 if (repetitionCount(false) != cAnimationNone) 150 if (repetitionCount(false) != cAnimationNone)
151 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); 151 m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
152 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); 152 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
153 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); 153 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index);
154 154
155 notifyMemoryChanged(); 155 notifyMemoryChanged();
156 return image.release(); 156 return image.release();
157 } 157 }
158 158
159 void BitmapImage::updateSize() const 159 void BitmapImage::updateSize() const
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 // With ICOs, on the other hand, we may ask for arbitrary frames at 198 // With ICOs, on the other hand, we may ask for arbitrary frames at
199 // different times (e.g. because we're displaying a higher-resolution image 199 // different times (e.g. because we're displaying a higher-resolution image
200 // in the content area and using a lower-resolution one for the favicon), 200 // in the content area and using a lower-resolution one for the favicon),
201 // and the frames aren't even guaranteed to appear in the file in the same 201 // and the frames aren't even guaranteed to appear in the file in the same
202 // order as in the directory, so an arbitrary number of the frames might be 202 // order as in the directory, so an arbitrary number of the frames might be
203 // incomplete (if we ask for frames for which we've not yet reached the 203 // incomplete (if we ask for frames for which we've not yet reached the
204 // start of the frame data), and any or none of them might be the particular 204 // start of the frame data), and any or none of them might be the particular
205 // frame affected by appending new data here. Thus we have to clear all the 205 // frame affected by appending new data here. Thus we have to clear all the
206 // incomplete frames to be safe. 206 // incomplete frames to be safe.
207 for (size_t i = 0; i < m_frames.size(); ++i) { 207 for (size_t i = 0; i < m_frames.size(); ++i) {
208 // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to 208 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isFullyReceived) {
209 // decode any uncached (i.e. never-decoded or
210 // cleared-on-a-previous-pass) frames!
211 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isComplete) {
212 m_frames[i].clear(true); 209 m_frames[i].clear(true);
213 if (i == m_cachedFrameIndex) 210 if (i == m_cachedFrameIndex)
214 m_cachedFrame.clear(); 211 m_cachedFrame.clear();
215 } 212 }
216 } 213 }
217 214
218 // Feed all the data we've seen so far to the image decoder. 215 // Feed all the data we've seen so far to the image decoder.
219 m_allDataReceived = allDataReceived; 216 m_allDataReceived = allDataReceived;
220 ASSERT(data()); 217 ASSERT(data());
221 m_source.setData(*data(), allDataReceived); 218 m_source.setData(*data(), allDataReceived);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 { 316 {
320 if (index >= frameCount()) 317 if (index >= frameCount())
321 return nullptr; 318 return nullptr;
322 319
323 if (index == m_cachedFrameIndex && m_cachedFrame) 320 if (index == m_cachedFrameIndex && m_cachedFrame)
324 return m_cachedFrame; 321 return m_cachedFrame;
325 322
326 return decodeAndCacheFrame(index); 323 return decodeAndCacheFrame(index);
327 } 324 }
328 325
329 bool BitmapImage::frameIsCompleteAtIndex(size_t index) 326 bool BitmapImage::frameIsFullyReceivedAtIndex(size_t index)
330 { 327 {
331 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in dex].m_isComplete) 328 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in dex].m_isFullyReceived)
332 return true; 329 return true;
333 330
334 return m_source.frameIsCompleteAtIndex(index); 331 return m_source.frameIsFullyReceivedAtIndex(index);
335 } 332 }
336 333
337 float BitmapImage::frameDurationAtIndex(size_t index) 334 float BitmapImage::frameDurationAtIndex(size_t index)
338 { 335 {
339 if (index < m_frames.size() && m_frames[index].m_haveMetadata) 336 if (index < m_frames.size() && m_frames[index].m_haveMetadata)
340 return m_frames[index].m_duration; 337 return m_frames[index].m_duration;
341 338
342 return m_source.frameDurationAtIndex(index); 339 return m_source.frameDurationAtIndex(index);
343 } 340 }
344 341
(...skipping 27 matching lines...) Expand all
372 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) 369 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode)
373 { 370 {
374 if (metadataMode == PreCacheMetadata) { 371 if (metadataMode == PreCacheMetadata) {
375 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the 372 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the
376 // chance of an accurate answer, pre-cache the current frame metadata. 373 // chance of an accurate answer, pre-cache the current frame metadata.
377 frameAtIndex(currentFrame()); 374 frameAtIndex(currentFrame());
378 } 375 }
379 return !frameHasAlphaAtIndex(currentFrame()); 376 return !frameHasAlphaAtIndex(currentFrame());
380 } 377 }
381 378
382 bool BitmapImage::currentFrameIsComplete() 379 bool BitmapImage::currentFrameIsFullyReceived()
383 { 380 {
384 return frameIsCompleteAtIndex(currentFrame()); 381 return frameIsFullyReceivedAtIndex(currentFrame());
385 } 382 }
386 383
387 bool BitmapImage::currentFrameIsLazyDecoded() 384 bool BitmapImage::currentFrameIsLazyDecoded()
388 { 385 {
389 RefPtr<SkImage> image = frameAtIndex(currentFrame()); 386 RefPtr<SkImage> image = frameAtIndex(currentFrame());
390 return image && image->isLazyGenerated(); 387 return image && image->isLazyGenerated();
391 } 388 }
392 389
393 ImageOrientation BitmapImage::currentFrameOrientation() 390 ImageOrientation BitmapImage::currentFrameOrientation()
394 { 391 {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) 429 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
433 return; 430 return;
434 431
435 // If we aren't already animating, set now as the animation start time. 432 // If we aren't already animating, set now as the animation start time.
436 const double time = monotonicallyIncreasingTime(); 433 const double time = monotonicallyIncreasingTime();
437 if (!m_desiredFrameStartTime) 434 if (!m_desiredFrameStartTime)
438 m_desiredFrameStartTime = time; 435 m_desiredFrameStartTime = time;
439 436
440 // Don't advance the animation to an incomplete frame. 437 // Don't advance the animation to an incomplete frame.
441 size_t nextFrame = (m_currentFrame + 1) % frameCount(); 438 size_t nextFrame = (m_currentFrame + 1) % frameCount();
442 if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) 439 if (!m_allDataReceived && !frameIsFullyReceivedAtIndex(nextFrame))
443 return; 440 return;
444 441
445 // Don't advance past the last frame if we haven't decoded the whole image 442 // Don't advance past the last frame if we haven't decoded the whole image
446 // yet and our repetition count is potentially unset. The repetition count 443 // yet and our repetition count is potentially unset. The repetition count
447 // in a GIF can potentially come after all the rest of the image data, so 444 // in a GIF can potentially come after all the rest of the image data, so
448 // wait on it. 445 // wait on it.
449 if (!m_allDataReceived 446 if (!m_allDataReceived
450 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy == ImageAnimationPolicyAnimateOnce) 447 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy == ImageAnimationPolicyAnimateOnce)
451 && m_currentFrame >= (frameCount() - 1)) 448 && m_currentFrame >= (frameCount() - 1))
452 return; 449 return;
(...skipping 26 matching lines...) Expand all
479 476
480 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) { 477 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) {
481 // Haven't yet reached time for next frame to start; delay until then. 478 // Haven't yet reached time for next frame to start; delay until then.
482 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan ceAnimation)); 479 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan ceAnimation));
483 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.), BLINK_FROM_HERE); 480 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.), BLINK_FROM_HERE);
484 } else { 481 } else {
485 // We've already reached or passed the time for the next frame to start. 482 // We've already reached or passed the time for the next frame to start.
486 // See if we've also passed the time for frames after that to start, in 483 // See if we've also passed the time for frames after that to start, in
487 // case we need to skip some frames entirely. Remember not to advance 484 // case we need to skip some frames entirely. Remember not to advance
488 // to an incomplete frame. 485 // to an incomplete frame.
489 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsComp leteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) { 486 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsFull yReceivedAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount( )) {
490 // Should we skip the next frame? 487 // Should we skip the next frame?
491 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura tionAtIndex(nextFrame); 488 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura tionAtIndex(nextFrame);
492 if (time < frameAfterNextStartTime) 489 if (time < frameAfterNextStartTime)
493 break; 490 break;
494 491
495 // Yes; skip over it without notifying our observers. 492 // Yes; skip over it without notifying our observers.
496 if (!internalAdvanceAnimation(true)) 493 if (!internalAdvanceAnimation(true))
497 return; 494 return;
498 m_desiredFrameStartTime = frameAfterNextStartTime; 495 m_desiredFrameStartTime = frameAfterNextStartTime;
499 nextFrame = frameAfterNext; 496 nextFrame = frameAfterNext;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 586
590 // We need to draw this frame if we advanced to it while not skipping, or if 587 // We need to draw this frame if we advanced to it while not skipping, or if
591 // while trying to skip frames we hit the last frame and thus had to stop. 588 // while trying to skip frames we hit the last frame and thus had to stop.
592 if (skippingFrames != advancedAnimation) 589 if (skippingFrames != advancedAnimation)
593 getImageObserver()->animationAdvanced(this); 590 getImageObserver()->animationAdvanced(this);
594 591
595 return advancedAnimation; 592 return advancedAnimation;
596 } 593 }
597 594
598 } // namespace blink 595 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698