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