| 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |