| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 BitmapImage::BitmapImage(ImageObserver* observer) | 43 BitmapImage::BitmapImage(ImageObserver* observer) |
| 44 : Image(observer) | 44 : Image(observer) |
| 45 , m_currentFrame(0) | 45 , m_currentFrame(0) |
| 46 , m_frames(0) | 46 , m_frames(0) |
| 47 , m_frameTimer(0) | 47 , m_frameTimer(0) |
| 48 , m_repetitionCount(cAnimationNone) | 48 , m_repetitionCount(cAnimationNone) |
| 49 , m_repetitionCountStatus(Unknown) | 49 , m_repetitionCountStatus(Unknown) |
| 50 , m_repetitionsComplete(0) | 50 , m_repetitionsComplete(0) |
| 51 , m_desiredFrameStartTime(0) | 51 , m_desiredFrameStartTime(0) |
| 52 , m_decodedSize(0) | |
| 53 , m_decodedPropertiesSize(0) | |
| 54 , m_frameCount(0) | 52 , m_frameCount(0) |
| 55 , m_isSolidColor(false) | 53 , m_isSolidColor(false) |
| 56 , m_checkedForSolidColor(false) | 54 , m_checkedForSolidColor(false) |
| 57 , m_animationFinished(false) | 55 , m_animationFinished(false) |
| 58 , m_allDataReceived(false) | 56 , m_allDataReceived(false) |
| 59 , m_haveSize(false) | 57 , m_haveSize(false) |
| 60 , m_sizeAvailable(false) | 58 , m_sizeAvailable(false) |
| 61 , m_hasUniformFrameSize(true) | 59 , m_hasUniformFrameSize(true) |
| 62 , m_haveFrameCount(false) | 60 , m_haveFrameCount(false) |
| 63 { | 61 { |
| 64 } | 62 } |
| 65 | 63 |
| 66 BitmapImage::BitmapImage(PassRefPtr<NativeImageSkia> nativeImage, ImageObserver*
observer) | 64 BitmapImage::BitmapImage(PassRefPtr<NativeImageSkia> nativeImage, ImageObserver*
observer) |
| 67 : Image(observer) | 65 : Image(observer) |
| 68 , m_size(nativeImage->bitmap().width(), nativeImage->bitmap().height()) | 66 , m_size(nativeImage->bitmap().width(), nativeImage->bitmap().height()) |
| 69 , m_currentFrame(0) | 67 , m_currentFrame(0) |
| 70 , m_frames(0) | 68 , m_frames(0) |
| 71 , m_frameTimer(0) | 69 , m_frameTimer(0) |
| 72 , m_repetitionCount(cAnimationNone) | 70 , m_repetitionCount(cAnimationNone) |
| 73 , m_repetitionCountStatus(Unknown) | 71 , m_repetitionCountStatus(Unknown) |
| 74 , m_repetitionsComplete(0) | 72 , m_repetitionsComplete(0) |
| 75 , m_decodedSize(nativeImage->decodedSize()) | |
| 76 , m_decodedPropertiesSize(0) | |
| 77 , m_frameCount(1) | 73 , m_frameCount(1) |
| 78 , m_isSolidColor(false) | 74 , m_isSolidColor(false) |
| 79 , m_checkedForSolidColor(false) | 75 , m_checkedForSolidColor(false) |
| 80 , m_animationFinished(true) | 76 , m_animationFinished(true) |
| 81 , m_allDataReceived(true) | 77 , m_allDataReceived(true) |
| 82 , m_haveSize(true) | 78 , m_haveSize(true) |
| 83 , m_sizeAvailable(true) | 79 , m_sizeAvailable(true) |
| 84 , m_haveFrameCount(true) | 80 , m_haveFrameCount(true) |
| 85 { | 81 { |
| 86 // Since we don't have a decoder, we can't figure out the image orientation. | 82 // Since we don't have a decoder, we can't figure out the image orientation. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 | 124 |
| 129 if (allFrameBytes > cLargeAnimationCutoff) | 125 if (allFrameBytes > cLargeAnimationCutoff) |
| 130 destroyDecodedData(false); | 126 destroyDecodedData(false); |
| 131 } | 127 } |
| 132 | 128 |
| 133 void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared) | 129 void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared) |
| 134 { | 130 { |
| 135 m_isSolidColor = false; | 131 m_isSolidColor = false; |
| 136 m_checkedForSolidColor = false; | 132 m_checkedForSolidColor = false; |
| 137 | 133 |
| 138 ASSERT(m_decodedSize >= frameBytesCleared); | |
| 139 m_decodedSize -= frameBytesCleared; | |
| 140 if (frameBytesCleared > 0) { | |
| 141 frameBytesCleared += m_decodedPropertiesSize; | |
| 142 m_decodedPropertiesSize = 0; | |
| 143 } | |
| 144 if (frameBytesCleared && imageObserver()) | 134 if (frameBytesCleared && imageObserver()) |
| 145 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); | 135 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); |
| 146 } | 136 } |
| 147 | 137 |
| 148 void BitmapImage::cacheFrame(size_t index) | 138 void BitmapImage::cacheFrame(size_t index) |
| 149 { | 139 { |
| 150 size_t numFrames = frameCount(); | 140 size_t numFrames = frameCount(); |
| 151 if (m_frames.size() < numFrames) | 141 if (m_frames.size() < numFrames) |
| 152 m_frames.grow(numFrames); | 142 m_frames.grow(numFrames); |
| 153 | 143 |
| 154 m_frames[index].m_frame = m_source.createFrameAtIndex(index); | 144 m_frames[index].m_frame = m_source.createFrameAtIndex(index); |
| 155 if (numFrames == 1 && m_frames[index].m_frame) | 145 if (numFrames == 1 && m_frames[index].m_frame) |
| 156 checkForSolidColor(); | 146 checkForSolidColor(); |
| 157 | 147 |
| 158 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 148 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
| 159 m_frames[index].m_haveMetadata = true; | 149 m_frames[index].m_haveMetadata = true; |
| 160 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 150 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); |
| 161 if (repetitionCount(false) != cAnimationNone) | 151 if (repetitionCount(false) != cAnimationNone) |
| 162 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); | 152 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); |
| 163 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); | 153 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); |
| 164 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); | 154 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); |
| 165 | 155 |
| 166 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); | 156 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); |
| 167 if (frameSize != m_size) | 157 if (frameSize != m_size) |
| 168 m_hasUniformFrameSize = false; | 158 m_hasUniformFrameSize = false; |
| 169 if (m_frames[index].m_frame) { | 159 if (m_frames[index].m_frame) { |
| 170 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); | 160 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); |
| 171 m_decodedSize += deltaBytes; | |
| 172 // The fully-decoded frame will subsume the partially decoded data used | 161 // The fully-decoded frame will subsume the partially decoded data used |
| 173 // to determine image properties. | 162 // to determine image properties. |
| 174 deltaBytes -= m_decodedPropertiesSize; | |
| 175 m_decodedPropertiesSize = 0; | |
| 176 if (imageObserver()) | 163 if (imageObserver()) |
| 177 imageObserver()->decodedSizeChanged(this, deltaBytes); | 164 imageObserver()->decodedSizeChanged(this, deltaBytes); |
| 178 } | 165 } |
| 179 } | 166 } |
| 180 | 167 |
| 181 void BitmapImage::didDecodeProperties() const | |
| 182 { | |
| 183 if (m_decodedSize) | |
| 184 return; | |
| 185 size_t updatedSize = m_source.bytesDecodedToDetermineProperties(); | |
| 186 if (m_decodedPropertiesSize == updatedSize) | |
| 187 return; | |
| 188 int deltaBytes = updatedSize - m_decodedPropertiesSize; | |
| 189 #if !ASSERT_DISABLED | |
| 190 bool overflow = updatedSize > m_decodedPropertiesSize && deltaBytes < 0; | |
| 191 bool underflow = updatedSize < m_decodedPropertiesSize && deltaBytes > 0; | |
| 192 ASSERT(!overflow && !underflow); | |
| 193 #endif | |
| 194 m_decodedPropertiesSize = updatedSize; | |
| 195 if (imageObserver()) | |
| 196 imageObserver()->decodedSizeChanged(this, deltaBytes); | |
| 197 } | |
| 198 | |
| 199 void BitmapImage::updateSize() const | 168 void BitmapImage::updateSize() const |
| 200 { | 169 { |
| 201 if (!m_sizeAvailable || m_haveSize) | 170 if (!m_sizeAvailable || m_haveSize) |
| 202 return; | 171 return; |
| 203 | 172 |
| 204 m_size = m_source.size(); | 173 m_size = m_source.size(); |
| 205 m_sizeRespectingOrientation = m_source.size(RespectImageOrientation); | 174 m_sizeRespectingOrientation = m_source.size(RespectImageOrientation); |
| 206 m_haveSize = true; | 175 m_haveSize = true; |
| 207 didDecodeProperties(); | |
| 208 } | 176 } |
| 209 | 177 |
| 210 IntSize BitmapImage::size() const | 178 IntSize BitmapImage::size() const |
| 211 { | 179 { |
| 212 updateSize(); | 180 updateSize(); |
| 213 return m_size; | 181 return m_size; |
| 214 } | 182 } |
| 215 | 183 |
| 216 IntSize BitmapImage::sizeRespectingOrientation() const | 184 IntSize BitmapImage::sizeRespectingOrientation() const |
| 217 { | 185 { |
| 218 updateSize(); | 186 updateSize(); |
| 219 return m_sizeRespectingOrientation; | 187 return m_sizeRespectingOrientation; |
| 220 } | 188 } |
| 221 | 189 |
| 222 IntSize BitmapImage::currentFrameSize() const | 190 IntSize BitmapImage::currentFrameSize() const |
| 223 { | 191 { |
| 224 if (!m_currentFrame || m_hasUniformFrameSize) | 192 if (!m_currentFrame || m_hasUniformFrameSize) |
| 225 return size(); | 193 return size(); |
| 226 IntSize frameSize = m_source.frameSizeAtIndex(m_currentFrame); | 194 IntSize frameSize = m_source.frameSizeAtIndex(m_currentFrame); |
| 227 didDecodeProperties(); | |
| 228 return frameSize; | 195 return frameSize; |
| 229 } | 196 } |
| 230 | 197 |
| 231 bool BitmapImage::getHotSpot(IntPoint& hotSpot) const | 198 bool BitmapImage::getHotSpot(IntPoint& hotSpot) const |
| 232 { | 199 { |
| 233 bool result = m_source.getHotSpot(hotSpot); | 200 bool result = m_source.getHotSpot(hotSpot); |
| 234 didDecodeProperties(); | |
| 235 return result; | 201 return result; |
| 236 } | 202 } |
| 237 | 203 |
| 238 bool BitmapImage::dataChanged(bool allDataReceived) | 204 bool BitmapImage::dataChanged(bool allDataReceived) |
| 239 { | 205 { |
| 240 TRACE_EVENT0("webkit", "BitmapImage::dataChanged"); | 206 TRACE_EVENT0("webkit", "BitmapImage::dataChanged"); |
| 241 | 207 |
| 242 // Clear all partially-decoded frames. For most image formats, there is only | 208 // Clear all partially-decoded frames. For most image formats, there is only |
| 243 // one frame, but at least GIF and ICO can have more. With GIFs, the frames | 209 // one frame, but at least GIF and ICO can have more. With GIFs, the frames |
| 244 // come in order and we ask to decode them in order, waiting to request a | 210 // come in order and we ask to decode them in order, waiting to request a |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 if (ImageObserver* observer = imageObserver()) | 296 if (ImageObserver* observer = imageObserver()) |
| 331 observer->didDraw(this); | 297 observer->didDraw(this); |
| 332 } | 298 } |
| 333 | 299 |
| 334 size_t BitmapImage::frameCount() | 300 size_t BitmapImage::frameCount() |
| 335 { | 301 { |
| 336 if (!m_haveFrameCount) { | 302 if (!m_haveFrameCount) { |
| 337 m_frameCount = m_source.frameCount(); | 303 m_frameCount = m_source.frameCount(); |
| 338 // If decoder is not initialized yet, m_source.frameCount() returns 0. | 304 // If decoder is not initialized yet, m_source.frameCount() returns 0. |
| 339 if (m_frameCount) { | 305 if (m_frameCount) { |
| 340 didDecodeProperties(); | |
| 341 m_haveFrameCount = true; | 306 m_haveFrameCount = true; |
| 342 } | 307 } |
| 343 } | 308 } |
| 344 return m_frameCount; | 309 return m_frameCount; |
| 345 } | 310 } |
| 346 | 311 |
| 347 bool BitmapImage::isSizeAvailable() | 312 bool BitmapImage::isSizeAvailable() |
| 348 { | 313 { |
| 349 if (m_sizeAvailable) | 314 if (m_sizeAvailable) |
| 350 return true; | 315 return true; |
| 351 | 316 |
| 352 m_sizeAvailable = m_source.isSizeAvailable(); | 317 m_sizeAvailable = m_source.isSizeAvailable(); |
| 353 didDecodeProperties(); | |
| 354 | 318 |
| 355 return m_sizeAvailable; | 319 return m_sizeAvailable; |
| 356 } | 320 } |
| 357 | 321 |
| 358 bool BitmapImage::ensureFrameIsCached(size_t index) | 322 bool BitmapImage::ensureFrameIsCached(size_t index) |
| 359 { | 323 { |
| 360 if (index >= frameCount()) | 324 if (index >= frameCount()) |
| 361 return false; | 325 return false; |
| 362 | 326 |
| 363 if (index >= m_frames.size() || !m_frames[index].m_frame) | 327 if (index >= m_frames.size() || !m_frames[index].m_frame) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 | 397 |
| 434 | 398 |
| 435 int BitmapImage::repetitionCount(bool imageKnownToBeComplete) | 399 int BitmapImage::repetitionCount(bool imageKnownToBeComplete) |
| 436 { | 400 { |
| 437 if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Unc
ertain) && imageKnownToBeComplete)) { | 401 if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Unc
ertain) && imageKnownToBeComplete)) { |
| 438 // Snag the repetition count. If |imageKnownToBeComplete| is false, the | 402 // Snag the repetition count. If |imageKnownToBeComplete| is false, the |
| 439 // repetition count may not be accurate yet for GIFs; in this case the | 403 // repetition count may not be accurate yet for GIFs; in this case the |
| 440 // decoder will default to cAnimationLoopOnce, and we'll try and read | 404 // decoder will default to cAnimationLoopOnce, and we'll try and read |
| 441 // the count again once the whole image is decoded. | 405 // the count again once the whole image is decoded. |
| 442 m_repetitionCount = m_source.repetitionCount(); | 406 m_repetitionCount = m_source.repetitionCount(); |
| 443 didDecodeProperties(); | |
| 444 m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount =
= cAnimationNone) ? Certain : Uncertain; | 407 m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount =
= cAnimationNone) ? Certain : Uncertain; |
| 445 } | 408 } |
| 446 return m_repetitionCount; | 409 return m_repetitionCount; |
| 447 } | 410 } |
| 448 | 411 |
| 449 bool BitmapImage::shouldAnimate() | 412 bool BitmapImage::shouldAnimate() |
| 450 { | 413 { |
| 451 return (repetitionCount(false) != cAnimationNone && !m_animationFinished &&
imageObserver()); | 414 return (repetitionCount(false) != cAnimationNone && !m_animationFinished &&
imageObserver()); |
| 452 } | 415 } |
| 453 | 416 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 stopAnimation(); | 523 stopAnimation(); |
| 561 m_currentFrame = 0; | 524 m_currentFrame = 0; |
| 562 m_repetitionsComplete = 0; | 525 m_repetitionsComplete = 0; |
| 563 m_desiredFrameStartTime = 0; | 526 m_desiredFrameStartTime = 0; |
| 564 m_animationFinished = false; | 527 m_animationFinished = false; |
| 565 | 528 |
| 566 // For extremely large animations, when the animation is reset, we just thro
w everything away. | 529 // For extremely large animations, when the animation is reset, we just thro
w everything away. |
| 567 destroyDecodedDataIfNecessary(); | 530 destroyDecodedDataIfNecessary(); |
| 568 } | 531 } |
| 569 | 532 |
| 570 unsigned BitmapImage::decodedSize() const | |
| 571 { | |
| 572 return m_decodedSize; | |
| 573 } | |
| 574 | |
| 575 | |
| 576 | |
| 577 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) | 533 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) |
| 578 { | 534 { |
| 579 internalAdvanceAnimation(false); | 535 internalAdvanceAnimation(false); |
| 580 // At this point the image region has been marked dirty, and if it's | 536 // At this point the image region has been marked dirty, and if it's |
| 581 // onscreen, we'll soon make a call to draw(), which will call | 537 // onscreen, we'll soon make a call to draw(), which will call |
| 582 // startAnimation() again to keep the animation moving. | 538 // startAnimation() again to keep the animation moving. |
| 583 } | 539 } |
| 584 | 540 |
| 585 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) | 541 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) |
| 586 { | 542 { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 } | 603 } |
| 648 return m_isSolidColor && !m_currentFrame; | 604 return m_isSolidColor && !m_currentFrame; |
| 649 } | 605 } |
| 650 | 606 |
| 651 Color BitmapImage::solidColor() const | 607 Color BitmapImage::solidColor() const |
| 652 { | 608 { |
| 653 return m_solidColor; | 609 return m_solidColor; |
| 654 } | 610 } |
| 655 | 611 |
| 656 } | 612 } |
| OLD | NEW |