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

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: PNG alpha & partial decode fixes. Created 4 years, 7 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 m_frames.grow(numFrames); 156 m_frames.grow(numFrames);
157 157
158 int deltaBytes = totalFrameBytes(); 158 int deltaBytes = totalFrameBytes();
159 159
160 // We are caching frame snapshots. This is OK even for partially decoded fr ames, 160 // We are caching frame snapshots. This is OK even for partially decoded fr ames,
161 // as they are cleared by dataChanged() when new data arrives. 161 // as they are cleared by dataChanged() when new data arrives.
162 m_frames[index].m_frame = m_source.createFrameAtIndex(index); 162 m_frames[index].m_frame = m_source.createFrameAtIndex(index);
163 163
164 m_frames[index].m_orientation = m_source.orientationAtIndex(index); 164 m_frames[index].m_orientation = m_source.orientationAtIndex(index);
165 m_frames[index].m_haveMetadata = true; 165 m_frames[index].m_haveMetadata = true;
166 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); 166 m_frames[index].m_isFullyReceived = m_source.frameIsFullyReceivedAtIndex(ind ex);
167 if (repetitionCount(false) != cAnimationNone) 167 if (repetitionCount(false) != cAnimationNone)
168 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); 168 m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
169 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); 169 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
170 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); 170 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index);
171 171
172 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); 172 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
173 if (frameSize != m_size) 173 if (frameSize != m_size)
174 m_hasUniformFrameSize = false; 174 m_hasUniformFrameSize = false;
175 175
176 // We need to check the total bytes before and after the decode call, not 176 // We need to check the total bytes before and after the decode call, not
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 // With ICOs, on the other hand, we may ask for arbitrary frames at 222 // With ICOs, on the other hand, we may ask for arbitrary frames at
223 // different times (e.g. because we're displaying a higher-resolution image 223 // different times (e.g. because we're displaying a higher-resolution image
224 // in the content area and using a lower-resolution one for the favicon), 224 // in the content area and using a lower-resolution one for the favicon),
225 // and the frames aren't even guaranteed to appear in the file in the same 225 // and the frames aren't even guaranteed to appear in the file in the same
226 // order as in the directory, so an arbitrary number of the frames might be 226 // order as in the directory, so an arbitrary number of the frames might be
227 // incomplete (if we ask for frames for which we've not yet reached the 227 // incomplete (if we ask for frames for which we've not yet reached the
228 // start of the frame data), and any or none of them might be the particular 228 // start of the frame data), and any or none of them might be the particular
229 // frame affected by appending new data here. Thus we have to clear all the 229 // frame affected by appending new data here. Thus we have to clear all the
230 // incomplete frames to be safe. 230 // incomplete frames to be safe.
231 for (size_t i = 0; i < m_frames.size(); ++i) { 231 for (size_t i = 0; i < m_frames.size(); ++i) {
232 // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to 232 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isFullyReceived)
233 // decode any uncached (i.e. never-decoded or
234 // cleared-on-a-previous-pass) frames!
235 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isComplete)
236 m_frames[i].clear(true); 233 m_frames[i].clear(true);
237 } 234 }
238 235
239 // Feed all the data we've seen so far to the image decoder. 236 // Feed all the data we've seen so far to the image decoder.
240 m_allDataReceived = allDataReceived; 237 m_allDataReceived = allDataReceived;
241 ASSERT(data()); 238 ASSERT(data());
242 m_source.setData(*data(), allDataReceived); 239 m_source.setData(*data(), allDataReceived);
243 240
244 m_haveFrameCount = false; 241 m_haveFrameCount = false;
245 m_hasUniformFrameSize = true; 242 m_hasUniformFrameSize = true;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 348 }
352 349
353 PassRefPtr<SkImage> BitmapImage::frameAtIndex(size_t index) 350 PassRefPtr<SkImage> BitmapImage::frameAtIndex(size_t index)
354 { 351 {
355 if (!ensureFrameIsCached(index)) 352 if (!ensureFrameIsCached(index))
356 return nullptr; 353 return nullptr;
357 354
358 return m_frames[index].m_frame; 355 return m_frames[index].m_frame;
359 } 356 }
360 357
361 bool BitmapImage::frameIsCompleteAtIndex(size_t index) 358 bool BitmapImage::frameIsFullyReceivedAtIndex(size_t index)
362 { 359 {
363 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in dex].m_isComplete) 360 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in dex].m_isFullyReceived)
364 return true; 361 return true;
365 362
366 return m_source.frameIsCompleteAtIndex(index); 363 return m_source.frameIsFullyReceivedAtIndex(index);
367 } 364 }
368 365
369 float BitmapImage::frameDurationAtIndex(size_t index) 366 float BitmapImage::frameDurationAtIndex(size_t index)
370 { 367 {
371 if (index < m_frames.size() && m_frames[index].m_haveMetadata) 368 if (index < m_frames.size() && m_frames[index].m_haveMetadata)
372 return m_frames[index].m_duration; 369 return m_frames[index].m_duration;
373 370
374 return m_source.frameDurationAtIndex(index); 371 return m_source.frameDurationAtIndex(index);
375 } 372 }
376 373
(...skipping 27 matching lines...) Expand all
404 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) 401 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode)
405 { 402 {
406 if (metadataMode == PreCacheMetadata) { 403 if (metadataMode == PreCacheMetadata) {
407 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the 404 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the
408 // chance of an accurate answer, pre-cache the current frame metadata. 405 // chance of an accurate answer, pre-cache the current frame metadata.
409 frameAtIndex(currentFrame()); 406 frameAtIndex(currentFrame());
410 } 407 }
411 return !frameHasAlphaAtIndex(currentFrame()); 408 return !frameHasAlphaAtIndex(currentFrame());
412 } 409 }
413 410
414 bool BitmapImage::currentFrameIsComplete() 411 bool BitmapImage::currentFrameIsFullyReceived()
415 { 412 {
416 return frameIsCompleteAtIndex(currentFrame()); 413 return frameIsFullyReceivedAtIndex(currentFrame());
417 } 414 }
418 415
419 bool BitmapImage::currentFrameIsLazyDecoded() 416 bool BitmapImage::currentFrameIsLazyDecoded()
420 { 417 {
421 RefPtr<SkImage> image = frameAtIndex(currentFrame()); 418 RefPtr<SkImage> image = frameAtIndex(currentFrame());
422 return image && image->isLazyGenerated(); 419 return image && image->isLazyGenerated();
423 } 420 }
424 421
425 ImageOrientation BitmapImage::currentFrameOrientation() 422 ImageOrientation BitmapImage::currentFrameOrientation()
426 { 423 {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) 461 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
465 return; 462 return;
466 463
467 // If we aren't already animating, set now as the animation start time. 464 // If we aren't already animating, set now as the animation start time.
468 const double time = monotonicallyIncreasingTime(); 465 const double time = monotonicallyIncreasingTime();
469 if (!m_desiredFrameStartTime) 466 if (!m_desiredFrameStartTime)
470 m_desiredFrameStartTime = time; 467 m_desiredFrameStartTime = time;
471 468
472 // Don't advance the animation to an incomplete frame. 469 // Don't advance the animation to an incomplete frame.
473 size_t nextFrame = (m_currentFrame + 1) % frameCount(); 470 size_t nextFrame = (m_currentFrame + 1) % frameCount();
474 if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) 471 if (!m_allDataReceived && !frameIsFullyReceivedAtIndex(nextFrame))
475 return; 472 return;
476 473
477 // Don't advance past the last frame if we haven't decoded the whole image 474 // Don't advance past the last frame if we haven't decoded the whole image
478 // yet and our repetition count is potentially unset. The repetition count 475 // yet and our repetition count is potentially unset. The repetition count
479 // in a GIF can potentially come after all the rest of the image data, so 476 // in a GIF can potentially come after all the rest of the image data, so
480 // wait on it. 477 // wait on it.
481 if (!m_allDataReceived 478 if (!m_allDataReceived
482 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy == ImageAnimationPolicyAnimateOnce) 479 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy == ImageAnimationPolicyAnimateOnce)
483 && m_currentFrame >= (frameCount() - 1)) 480 && m_currentFrame >= (frameCount() - 1))
484 return; 481 return;
(...skipping 26 matching lines...) Expand all
511 508
512 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) { 509 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) {
513 // Haven't yet reached time for next frame to start; delay until then. 510 // Haven't yet reached time for next frame to start; delay until then.
514 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan ceAnimation)); 511 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan ceAnimation));
515 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.), BLINK_FROM_HERE); 512 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.), BLINK_FROM_HERE);
516 } else { 513 } else {
517 // We've already reached or passed the time for the next frame to start. 514 // We've already reached or passed the time for the next frame to start.
518 // See if we've also passed the time for frames after that to start, in 515 // See if we've also passed the time for frames after that to start, in
519 // case we need to skip some frames entirely. Remember not to advance 516 // case we need to skip some frames entirely. Remember not to advance
520 // to an incomplete frame. 517 // to an incomplete frame.
521 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsComp leteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) { 518 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsFull yReceivedAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount( )) {
522 // Should we skip the next frame? 519 // Should we skip the next frame?
523 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura tionAtIndex(nextFrame); 520 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura tionAtIndex(nextFrame);
524 if (time < frameAfterNextStartTime) 521 if (time < frameAfterNextStartTime)
525 break; 522 break;
526 523
527 // Yes; skip over it without notifying our observers. 524 // Yes; skip over it without notifying our observers.
528 if (!internalAdvanceAnimation(true)) 525 if (!internalAdvanceAnimation(true))
529 return; 526 return;
530 m_desiredFrameStartTime = frameAfterNextStartTime; 527 m_desiredFrameStartTime = frameAfterNextStartTime;
531 nextFrame = frameAfterNext; 528 nextFrame = frameAfterNext;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 destroyDecodedDataIfNecessary(); 631 destroyDecodedDataIfNecessary();
635 632
636 // We need to draw this frame if we advanced to it while not skipping, or if 633 // 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. 634 // while trying to skip frames we hit the last frame and thus had to stop.
638 if (skippingFrames != advancedAnimation) 635 if (skippingFrames != advancedAnimation)
639 getImageObserver()->animationAdvanced(this); 636 getImageObserver()->animationAdvanced(this);
640 return advancedAnimation; 637 return advancedAnimation;
641 } 638 }
642 639
643 } // namespace blink 640 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698