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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 size_t numFrames = frameCount(); | 153 size_t numFrames = frameCount(); |
154 if (m_frames.size() < numFrames) | 154 if (m_frames.size() < numFrames) |
155 m_frames.grow(numFrames); | 155 m_frames.grow(numFrames); |
156 | 156 |
157 // We are caching frame snapshots. This is OK even for partially decoded fr
ames, | 157 // We are caching frame snapshots. This is OK even for partially decoded fr
ames, |
158 // as they are cleared by dataChanged() when new data arrives. | 158 // as they are cleared by dataChanged() when new data arrives. |
159 m_frames[index].m_frame = m_source.createFrameAtIndex(index); | 159 m_frames[index].m_frame = m_source.createFrameAtIndex(index); |
160 | 160 |
161 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 161 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
162 m_frames[index].m_haveMetadata = true; | 162 m_frames[index].m_haveMetadata = true; |
163 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 163 m_frames[index].m_isFullyReceived = m_source.frameIsFullyReceivedAtIndex(ind
ex); |
164 if (repetitionCount(false) != cAnimationNone) | 164 if (repetitionCount(false) != cAnimationNone) |
165 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); | 165 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); |
166 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); | 166 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); |
167 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); | 167 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); |
168 | 168 |
169 notifyMemoryChanged(); | 169 notifyMemoryChanged(); |
170 } | 170 } |
171 | 171 |
172 void BitmapImage::updateSize() const | 172 void BitmapImage::updateSize() const |
173 { | 173 { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 // With ICOs, on the other hand, we may ask for arbitrary frames at | 211 // With ICOs, on the other hand, we may ask for arbitrary frames at |
212 // different times (e.g. because we're displaying a higher-resolution image | 212 // different times (e.g. because we're displaying a higher-resolution image |
213 // in the content area and using a lower-resolution one for the favicon), | 213 // in the content area and using a lower-resolution one for the favicon), |
214 // and the frames aren't even guaranteed to appear in the file in the same | 214 // and the frames aren't even guaranteed to appear in the file in the same |
215 // order as in the directory, so an arbitrary number of the frames might be | 215 // order as in the directory, so an arbitrary number of the frames might be |
216 // incomplete (if we ask for frames for which we've not yet reached the | 216 // incomplete (if we ask for frames for which we've not yet reached the |
217 // start of the frame data), and any or none of them might be the particular | 217 // start of the frame data), and any or none of them might be the particular |
218 // frame affected by appending new data here. Thus we have to clear all the | 218 // frame affected by appending new data here. Thus we have to clear all the |
219 // incomplete frames to be safe. | 219 // incomplete frames to be safe. |
220 for (size_t i = 0; i < m_frames.size(); ++i) { | 220 for (size_t i = 0; i < m_frames.size(); ++i) { |
221 // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to | 221 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isFullyReceived) |
222 // decode any uncached (i.e. never-decoded or | |
223 // cleared-on-a-previous-pass) frames! | |
224 if (m_frames[i].m_haveMetadata && !m_frames[i].m_isComplete) | |
225 m_frames[i].clear(true); | 222 m_frames[i].clear(true); |
226 } | 223 } |
227 | 224 |
228 // Feed all the data we've seen so far to the image decoder. | 225 // Feed all the data we've seen so far to the image decoder. |
229 m_allDataReceived = allDataReceived; | 226 m_allDataReceived = allDataReceived; |
230 ASSERT(data()); | 227 ASSERT(data()); |
231 m_source.setData(*data(), allDataReceived); | 228 m_source.setData(*data(), allDataReceived); |
232 | 229 |
233 m_haveFrameCount = false; | 230 m_haveFrameCount = false; |
234 return isSizeAvailable(); | 231 return isSizeAvailable(); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 } | 334 } |
338 | 335 |
339 PassRefPtr<SkImage> BitmapImage::frameAtIndex(size_t index) | 336 PassRefPtr<SkImage> BitmapImage::frameAtIndex(size_t index) |
340 { | 337 { |
341 if (!ensureFrameIsCached(index)) | 338 if (!ensureFrameIsCached(index)) |
342 return nullptr; | 339 return nullptr; |
343 | 340 |
344 return m_frames[index].m_frame; | 341 return m_frames[index].m_frame; |
345 } | 342 } |
346 | 343 |
347 bool BitmapImage::frameIsCompleteAtIndex(size_t index) | 344 bool BitmapImage::frameIsFullyReceivedAtIndex(size_t index) |
348 { | 345 { |
349 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isComplete) | 346 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isFullyReceived) |
350 return true; | 347 return true; |
351 | 348 |
352 return m_source.frameIsCompleteAtIndex(index); | 349 return m_source.frameIsFullyReceivedAtIndex(index); |
353 } | 350 } |
354 | 351 |
355 float BitmapImage::frameDurationAtIndex(size_t index) | 352 float BitmapImage::frameDurationAtIndex(size_t index) |
356 { | 353 { |
357 if (index < m_frames.size() && m_frames[index].m_haveMetadata) | 354 if (index < m_frames.size() && m_frames[index].m_haveMetadata) |
358 return m_frames[index].m_duration; | 355 return m_frames[index].m_duration; |
359 | 356 |
360 return m_source.frameDurationAtIndex(index); | 357 return m_source.frameDurationAtIndex(index); |
361 } | 358 } |
362 | 359 |
(...skipping 27 matching lines...) Expand all Loading... |
390 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) | 387 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) |
391 { | 388 { |
392 if (metadataMode == PreCacheMetadata) { | 389 if (metadataMode == PreCacheMetadata) { |
393 // frameHasAlphaAtIndex() conservatively returns false for uncached fram
es. To increase the | 390 // frameHasAlphaAtIndex() conservatively returns false for uncached fram
es. To increase the |
394 // chance of an accurate answer, pre-cache the current frame metadata. | 391 // chance of an accurate answer, pre-cache the current frame metadata. |
395 frameAtIndex(currentFrame()); | 392 frameAtIndex(currentFrame()); |
396 } | 393 } |
397 return !frameHasAlphaAtIndex(currentFrame()); | 394 return !frameHasAlphaAtIndex(currentFrame()); |
398 } | 395 } |
399 | 396 |
400 bool BitmapImage::currentFrameIsComplete() | 397 bool BitmapImage::currentFrameIsFullyReceived() |
401 { | 398 { |
402 return frameIsCompleteAtIndex(currentFrame()); | 399 return frameIsFullyReceivedAtIndex(currentFrame()); |
403 } | 400 } |
404 | 401 |
405 bool BitmapImage::currentFrameIsLazyDecoded() | 402 bool BitmapImage::currentFrameIsLazyDecoded() |
406 { | 403 { |
407 RefPtr<SkImage> image = frameAtIndex(currentFrame()); | 404 RefPtr<SkImage> image = frameAtIndex(currentFrame()); |
408 return image && image->isLazyGenerated(); | 405 return image && image->isLazyGenerated(); |
409 } | 406 } |
410 | 407 |
411 ImageOrientation BitmapImage::currentFrameOrientation() | 408 ImageOrientation BitmapImage::currentFrameOrientation() |
412 { | 409 { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) | 447 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) |
451 return; | 448 return; |
452 | 449 |
453 // If we aren't already animating, set now as the animation start time. | 450 // If we aren't already animating, set now as the animation start time. |
454 const double time = monotonicallyIncreasingTime(); | 451 const double time = monotonicallyIncreasingTime(); |
455 if (!m_desiredFrameStartTime) | 452 if (!m_desiredFrameStartTime) |
456 m_desiredFrameStartTime = time; | 453 m_desiredFrameStartTime = time; |
457 | 454 |
458 // Don't advance the animation to an incomplete frame. | 455 // Don't advance the animation to an incomplete frame. |
459 size_t nextFrame = (m_currentFrame + 1) % frameCount(); | 456 size_t nextFrame = (m_currentFrame + 1) % frameCount(); |
460 if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) | 457 if (!m_allDataReceived && !frameIsFullyReceivedAtIndex(nextFrame)) |
461 return; | 458 return; |
462 | 459 |
463 // Don't advance past the last frame if we haven't decoded the whole image | 460 // Don't advance past the last frame if we haven't decoded the whole image |
464 // yet and our repetition count is potentially unset. The repetition count | 461 // yet and our repetition count is potentially unset. The repetition count |
465 // in a GIF can potentially come after all the rest of the image data, so | 462 // in a GIF can potentially come after all the rest of the image data, so |
466 // wait on it. | 463 // wait on it. |
467 if (!m_allDataReceived | 464 if (!m_allDataReceived |
468 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy ==
ImageAnimationPolicyAnimateOnce) | 465 && (repetitionCount(false) == cAnimationLoopOnce || m_animationPolicy ==
ImageAnimationPolicyAnimateOnce) |
469 && m_currentFrame >= (frameCount() - 1)) | 466 && m_currentFrame >= (frameCount() - 1)) |
470 return; | 467 return; |
(...skipping 26 matching lines...) Expand all Loading... |
497 | 494 |
498 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) { | 495 if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) { |
499 // Haven't yet reached time for next frame to start; delay until then. | 496 // Haven't yet reached time for next frame to start; delay until then. |
500 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan
ceAnimation)); | 497 m_frameTimer = adoptPtr(new Timer<BitmapImage>(this, &BitmapImage::advan
ceAnimation)); |
501 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.),
BLINK_FROM_HERE); | 498 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.),
BLINK_FROM_HERE); |
502 } else { | 499 } else { |
503 // We've already reached or passed the time for the next frame to start. | 500 // We've already reached or passed the time for the next frame to start. |
504 // See if we've also passed the time for frames after that to start, in | 501 // See if we've also passed the time for frames after that to start, in |
505 // case we need to skip some frames entirely. Remember not to advance | 502 // case we need to skip some frames entirely. Remember not to advance |
506 // to an incomplete frame. | 503 // to an incomplete frame. |
507 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsComp
leteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) { | 504 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsFull
yReceivedAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount(
)) { |
508 // Should we skip the next frame? | 505 // Should we skip the next frame? |
509 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura
tionAtIndex(nextFrame); | 506 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDura
tionAtIndex(nextFrame); |
510 if (time < frameAfterNextStartTime) | 507 if (time < frameAfterNextStartTime) |
511 break; | 508 break; |
512 | 509 |
513 // Yes; skip over it without notifying our observers. | 510 // Yes; skip over it without notifying our observers. |
514 if (!internalAdvanceAnimation(true)) | 511 if (!internalAdvanceAnimation(true)) |
515 return; | 512 return; |
516 m_desiredFrameStartTime = frameAfterNextStartTime; | 513 m_desiredFrameStartTime = frameAfterNextStartTime; |
517 nextFrame = frameAfterNext; | 514 nextFrame = frameAfterNext; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 destroyDecodedDataIfNecessary(); | 617 destroyDecodedDataIfNecessary(); |
621 | 618 |
622 // We need to draw this frame if we advanced to it while not skipping, or if | 619 // We need to draw this frame if we advanced to it while not skipping, or if |
623 // while trying to skip frames we hit the last frame and thus had to stop. | 620 // while trying to skip frames we hit the last frame and thus had to stop. |
624 if (skippingFrames != advancedAnimation) | 621 if (skippingFrames != advancedAnimation) |
625 getImageObserver()->animationAdvanced(this); | 622 getImageObserver()->animationAdvanced(this); |
626 return advancedAnimation; | 623 return advancedAnimation; |
627 } | 624 } |
628 | 625 |
629 } // namespace blink | 626 } // namespace blink |
OLD | NEW |