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 // Clear all partially-decoded frames. For most image formats, there is only | 206 // Clear all partially-decoded frames. For most image formats, there is only |
241 // one frame, but at least GIF and ICO can have more. With GIFs, the frames | 207 // one frame, but at least GIF and ICO can have more. With GIFs, the frames |
242 // come in order and we ask to decode them in order, waiting to request a | 208 // come in order and we ask to decode them in order, waiting to request a |
243 // subsequent frame until the prior one is complete. Given that we clear | 209 // subsequent frame until the prior one is complete. Given that we clear |
244 // incomplete frames here, this means there is at most one incomplete frame | 210 // incomplete frames here, this means there is at most one incomplete frame |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 if (ImageObserver* observer = imageObserver()) | 294 if (ImageObserver* observer = imageObserver()) |
329 observer->didDraw(this); | 295 observer->didDraw(this); |
330 } | 296 } |
331 | 297 |
332 size_t BitmapImage::frameCount() | 298 size_t BitmapImage::frameCount() |
333 { | 299 { |
334 if (!m_haveFrameCount) { | 300 if (!m_haveFrameCount) { |
335 m_frameCount = m_source.frameCount(); | 301 m_frameCount = m_source.frameCount(); |
336 // If decoder is not initialized yet, m_source.frameCount() returns 0. | 302 // If decoder is not initialized yet, m_source.frameCount() returns 0. |
337 if (m_frameCount) { | 303 if (m_frameCount) { |
338 didDecodeProperties(); | |
339 m_haveFrameCount = true; | 304 m_haveFrameCount = true; |
340 } | 305 } |
341 } | 306 } |
342 return m_frameCount; | 307 return m_frameCount; |
343 } | 308 } |
344 | 309 |
345 bool BitmapImage::isSizeAvailable() | 310 bool BitmapImage::isSizeAvailable() |
346 { | 311 { |
347 if (m_sizeAvailable) | 312 if (m_sizeAvailable) |
348 return true; | 313 return true; |
349 | 314 |
350 m_sizeAvailable = m_source.isSizeAvailable(); | 315 m_sizeAvailable = m_source.isSizeAvailable(); |
351 didDecodeProperties(); | |
352 | 316 |
353 return m_sizeAvailable; | 317 return m_sizeAvailable; |
354 } | 318 } |
355 | 319 |
356 bool BitmapImage::ensureFrameIsCached(size_t index) | 320 bool BitmapImage::ensureFrameIsCached(size_t index) |
357 { | 321 { |
358 if (index >= frameCount()) | 322 if (index >= frameCount()) |
359 return false; | 323 return false; |
360 | 324 |
361 if (index >= m_frames.size() || !m_frames[index].m_frame) | 325 if (index >= m_frames.size() || !m_frames[index].m_frame) |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 | 395 |
432 | 396 |
433 int BitmapImage::repetitionCount(bool imageKnownToBeComplete) | 397 int BitmapImage::repetitionCount(bool imageKnownToBeComplete) |
434 { | 398 { |
435 if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Unc
ertain) && imageKnownToBeComplete)) { | 399 if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Unc
ertain) && imageKnownToBeComplete)) { |
436 // Snag the repetition count. If |imageKnownToBeComplete| is false, the | 400 // Snag the repetition count. If |imageKnownToBeComplete| is false, the |
437 // repetition count may not be accurate yet for GIFs; in this case the | 401 // repetition count may not be accurate yet for GIFs; in this case the |
438 // decoder will default to cAnimationLoopOnce, and we'll try and read | 402 // decoder will default to cAnimationLoopOnce, and we'll try and read |
439 // the count again once the whole image is decoded. | 403 // the count again once the whole image is decoded. |
440 m_repetitionCount = m_source.repetitionCount(); | 404 m_repetitionCount = m_source.repetitionCount(); |
441 didDecodeProperties(); | |
442 m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount =
= cAnimationNone) ? Certain : Uncertain; | 405 m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount =
= cAnimationNone) ? Certain : Uncertain; |
443 } | 406 } |
444 return m_repetitionCount; | 407 return m_repetitionCount; |
445 } | 408 } |
446 | 409 |
447 bool BitmapImage::shouldAnimate() | 410 bool BitmapImage::shouldAnimate() |
448 { | 411 { |
449 return (repetitionCount(false) != cAnimationNone && !m_animationFinished &&
imageObserver()); | 412 return (repetitionCount(false) != cAnimationNone && !m_animationFinished &&
imageObserver()); |
450 } | 413 } |
451 | 414 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 stopAnimation(); | 521 stopAnimation(); |
559 m_currentFrame = 0; | 522 m_currentFrame = 0; |
560 m_repetitionsComplete = 0; | 523 m_repetitionsComplete = 0; |
561 m_desiredFrameStartTime = 0; | 524 m_desiredFrameStartTime = 0; |
562 m_animationFinished = false; | 525 m_animationFinished = false; |
563 | 526 |
564 // For extremely large animations, when the animation is reset, we just thro
w everything away. | 527 // For extremely large animations, when the animation is reset, we just thro
w everything away. |
565 destroyDecodedDataIfNecessary(); | 528 destroyDecodedDataIfNecessary(); |
566 } | 529 } |
567 | 530 |
568 unsigned BitmapImage::decodedSize() const | |
569 { | |
570 return m_decodedSize; | |
571 } | |
572 | |
573 | |
574 | |
575 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) | 531 void BitmapImage::advanceAnimation(Timer<BitmapImage>*) |
576 { | 532 { |
577 internalAdvanceAnimation(false); | 533 internalAdvanceAnimation(false); |
578 // At this point the image region has been marked dirty, and if it's | 534 // At this point the image region has been marked dirty, and if it's |
579 // onscreen, we'll soon make a call to draw(), which will call | 535 // onscreen, we'll soon make a call to draw(), which will call |
580 // startAnimation() again to keep the animation moving. | 536 // startAnimation() again to keep the animation moving. |
581 } | 537 } |
582 | 538 |
583 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) | 539 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) |
584 { | 540 { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 } | 601 } |
646 return m_isSolidColor && !m_currentFrame; | 602 return m_isSolidColor && !m_currentFrame; |
647 } | 603 } |
648 | 604 |
649 Color BitmapImage::solidColor() const | 605 Color BitmapImage::solidColor() const |
650 { | 606 { |
651 return m_solidColor; | 607 return m_solidColor; |
652 } | 608 } |
653 | 609 |
654 } | 610 } |
OLD | NEW |