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 14 matching lines...) Expand all Loading... |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "platform/graphics/BitmapImage.h" | 28 #include "platform/graphics/BitmapImage.h" |
29 | 29 |
30 #include "platform/Timer.h" | 30 #include "platform/Timer.h" |
31 #include "platform/TraceEvent.h" | 31 #include "platform/TraceEvent.h" |
32 #include "platform/geometry/FloatRect.h" | 32 #include "platform/geometry/FloatRect.h" |
33 #include "platform/graphics/GraphicsContextStateSaver.h" | 33 #include "platform/graphics/GraphicsContextStateSaver.h" |
34 #include "platform/graphics/ImageObserver.h" | 34 #include "platform/graphics/ImageObserver.h" |
35 #include "platform/graphics/skia/NativeImageSkia.h" | |
36 #include "platform/graphics/skia/SkiaUtils.h" | 35 #include "platform/graphics/skia/SkiaUtils.h" |
37 #include "wtf/PassRefPtr.h" | 36 #include "wtf/PassRefPtr.h" |
38 #include "wtf/text/WTFString.h" | 37 #include "wtf/text/WTFString.h" |
39 | 38 |
40 namespace blink { | 39 namespace blink { |
41 | 40 |
42 PassRefPtr<BitmapImage> BitmapImage::create(PassRefPtr<NativeImageSkia> nativeIm
age, ImageObserver* observer) | 41 PassRefPtr<BitmapImage> BitmapImage::create(const SkBitmap& bitmap, ImageObserve
r* observer) |
43 { | 42 { |
44 if (!nativeImage) { | 43 if (bitmap.isNull()) { |
45 return BitmapImage::create(observer); | 44 return BitmapImage::create(observer); |
46 } | 45 } |
47 | 46 |
48 return adoptRef(new BitmapImage(nativeImage, observer)); | 47 return adoptRef(new BitmapImage(bitmap, observer)); |
49 } | 48 } |
50 | 49 |
51 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(PassRefPtr<
NativeImageSkia> nativeImage, ImageOrientation orientation) | 50 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBit
map& bitmap, ImageOrientation orientation) |
52 { | 51 { |
53 RefPtr<BitmapImage> result = create(nativeImage); | 52 RefPtr<BitmapImage> result = create(bitmap); |
54 result->m_frames[0].m_orientation = orientation; | 53 result->m_frames[0].m_orientation = orientation; |
55 if (orientation.usesWidthAsHeight()) | 54 if (orientation.usesWidthAsHeight()) |
56 result->m_sizeRespectingOrientation = IntSize(result->m_size.height(), r
esult->m_size.width()); | 55 result->m_sizeRespectingOrientation = IntSize(result->m_size.height(), r
esult->m_size.width()); |
57 return result.release(); | 56 return result.release(); |
58 } | 57 } |
59 | 58 |
60 BitmapImage::BitmapImage(ImageObserver* observer) | 59 BitmapImage::BitmapImage(ImageObserver* observer) |
61 : Image(observer) | 60 : Image(observer) |
62 , m_currentFrame(0) | 61 , m_currentFrame(0) |
63 , m_frames() | 62 , m_frames() |
64 , m_frameTimer(0) | 63 , m_frameTimer(0) |
65 , m_repetitionCount(cAnimationNone) | 64 , m_repetitionCount(cAnimationNone) |
66 , m_repetitionCountStatus(Unknown) | 65 , m_repetitionCountStatus(Unknown) |
67 , m_repetitionsComplete(0) | 66 , m_repetitionsComplete(0) |
68 , m_desiredFrameStartTime(0) | 67 , m_desiredFrameStartTime(0) |
69 , m_frameCount(0) | 68 , m_frameCount(0) |
70 , m_animationPolicy(ImageAnimationPolicyAllowed) | 69 , m_animationPolicy(ImageAnimationPolicyAllowed) |
71 , m_isSolidColor(false) | 70 , m_isSolidColor(false) |
72 , m_checkedForSolidColor(false) | 71 , m_checkedForSolidColor(false) |
73 , m_animationFinished(false) | 72 , m_animationFinished(false) |
74 , m_allDataReceived(false) | 73 , m_allDataReceived(false) |
75 , m_haveSize(false) | 74 , m_haveSize(false) |
76 , m_sizeAvailable(false) | 75 , m_sizeAvailable(false) |
77 , m_hasUniformFrameSize(true) | 76 , m_hasUniformFrameSize(true) |
78 , m_haveFrameCount(false) | 77 , m_haveFrameCount(false) |
79 { | 78 { |
80 } | 79 } |
81 | 80 |
82 BitmapImage::BitmapImage(PassRefPtr<NativeImageSkia> nativeImage, ImageObserver*
observer) | 81 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer) |
83 : Image(observer) | 82 : Image(observer) |
84 , m_size(nativeImage->bitmap().width(), nativeImage->bitmap().height()) | 83 , m_size(bitmap.width(), bitmap.height()) |
85 , m_currentFrame(0) | 84 , m_currentFrame(0) |
86 , m_frames(0) | 85 , m_frames(0) |
87 , m_frameTimer(0) | 86 , m_frameTimer(0) |
88 , m_repetitionCount(cAnimationNone) | 87 , m_repetitionCount(cAnimationNone) |
89 , m_repetitionCountStatus(Unknown) | 88 , m_repetitionCountStatus(Unknown) |
90 , m_repetitionsComplete(0) | 89 , m_repetitionsComplete(0) |
91 , m_frameCount(1) | 90 , m_frameCount(1) |
92 , m_animationPolicy(ImageAnimationPolicyAllowed) | 91 , m_animationPolicy(ImageAnimationPolicyAllowed) |
93 , m_isSolidColor(false) | 92 , m_isSolidColor(false) |
94 , m_checkedForSolidColor(false) | 93 , m_checkedForSolidColor(false) |
95 , m_animationFinished(true) | 94 , m_animationFinished(true) |
96 , m_allDataReceived(true) | 95 , m_allDataReceived(true) |
97 , m_haveSize(true) | 96 , m_haveSize(true) |
98 , m_sizeAvailable(true) | 97 , m_sizeAvailable(true) |
99 , m_haveFrameCount(true) | 98 , m_haveFrameCount(true) |
100 { | 99 { |
101 // Since we don't have a decoder, we can't figure out the image orientation. | 100 // Since we don't have a decoder, we can't figure out the image orientation. |
102 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. | 101 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. |
103 m_sizeRespectingOrientation = m_size; | 102 m_sizeRespectingOrientation = m_size; |
104 | 103 |
105 m_frames.grow(1); | 104 m_frames.grow(1); |
106 m_frames[0].m_hasAlpha = !nativeImage->bitmap().isOpaque(); | 105 m_frames[0].m_hasAlpha = !bitmap.isOpaque(); |
107 m_frames[0].m_frame = nativeImage; | 106 m_frames[0].m_frame = bitmap; |
108 m_frames[0].m_haveMetadata = true; | 107 m_frames[0].m_haveMetadata = true; |
109 | 108 |
110 checkForSolidColor(); | 109 checkForSolidColor(); |
111 } | 110 } |
112 | 111 |
113 BitmapImage::~BitmapImage() | 112 BitmapImage::~BitmapImage() |
114 { | 113 { |
115 stopAnimation(); | 114 stopAnimation(); |
116 } | 115 } |
117 | 116 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); | 159 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); |
161 } | 160 } |
162 | 161 |
163 void BitmapImage::cacheFrame(size_t index) | 162 void BitmapImage::cacheFrame(size_t index) |
164 { | 163 { |
165 size_t numFrames = frameCount(); | 164 size_t numFrames = frameCount(); |
166 if (m_frames.size() < numFrames) | 165 if (m_frames.size() < numFrames) |
167 m_frames.grow(numFrames); | 166 m_frames.grow(numFrames); |
168 | 167 |
169 m_frames[index].m_frame = m_source.createFrameAtIndex(index); | 168 m_frames[index].m_frame = m_source.createFrameAtIndex(index); |
170 if (numFrames == 1 && m_frames[index].m_frame) | 169 if (numFrames == 1 && !m_frames[index].m_frame.isNull()) |
171 checkForSolidColor(); | 170 checkForSolidColor(); |
172 | 171 |
173 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 172 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
174 m_frames[index].m_haveMetadata = true; | 173 m_frames[index].m_haveMetadata = true; |
175 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 174 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); |
176 if (repetitionCount(false) != cAnimationNone) | 175 if (repetitionCount(false) != cAnimationNone) |
177 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); | 176 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); |
178 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); | 177 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); |
179 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); | 178 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); |
180 | 179 |
181 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); | 180 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); |
182 if (frameSize != m_size) | 181 if (frameSize != m_size) |
183 m_hasUniformFrameSize = false; | 182 m_hasUniformFrameSize = false; |
184 | 183 |
185 if (m_frames[index].m_frame) { | 184 if (!m_frames[index].m_frame.isNull()) { |
186 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); | 185 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); |
187 // The fully-decoded frame will subsume the partially decoded data used | 186 // The fully-decoded frame will subsume the partially decoded data used |
188 // to determine image properties. | 187 // to determine image properties. |
189 if (imageObserver()) | 188 if (imageObserver()) |
190 imageObserver()->decodedSizeChanged(this, deltaBytes); | 189 imageObserver()->decodedSizeChanged(this, deltaBytes); |
191 } | 190 } |
192 } | 191 } |
193 | 192 |
194 void BitmapImage::updateSize() const | 193 void BitmapImage::updateSize() const |
195 { | 194 { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 return m_source.hasColorProfile(); | 264 return m_source.hasColorProfile(); |
266 } | 265 } |
267 | 266 |
268 String BitmapImage::filenameExtension() const | 267 String BitmapImage::filenameExtension() const |
269 { | 268 { |
270 return m_source.filenameExtension(); | 269 return m_source.filenameExtension(); |
271 } | 270 } |
272 | 271 |
273 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum shou
ldRespectImageOrientation) | 272 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum shou
ldRespectImageOrientation) |
274 { | 273 { |
275 RefPtr<NativeImageSkia> image = nativeImageForCurrentFrame(); | 274 SkBitmap bitmap = bitmapForCurrentFrame(); |
276 if (!image) | 275 if (bitmap.isNull()) |
277 return; // It's too early and we don't have an image yet. | 276 return; // It's too early and we don't have an image yet. |
278 | 277 |
279 FloatRect normDstRect = adjustForNegativeSize(dstRect); | 278 FloatRect normDstRect = adjustForNegativeSize(dstRect); |
280 FloatRect normSrcRect = adjustForNegativeSize(srcRect); | 279 FloatRect normSrcRect = adjustForNegativeSize(srcRect); |
281 normSrcRect.intersect(FloatRect(0, 0, image->bitmap().width(), image->bitmap
().height())); | 280 normSrcRect.intersect(FloatRect(0, 0, bitmap.width(), bitmap.height())); |
282 | 281 |
283 if (normSrcRect.isEmpty() || normDstRect.isEmpty()) | 282 if (normSrcRect.isEmpty() || normDstRect.isEmpty()) |
284 return; // Nothing to draw. | 283 return; // Nothing to draw. |
285 | 284 |
286 ImageOrientation orientation = DefaultImageOrientation; | 285 ImageOrientation orientation = DefaultImageOrientation; |
287 if (shouldRespectImageOrientation == RespectImageOrientation) | 286 if (shouldRespectImageOrientation == RespectImageOrientation) |
288 orientation = frameOrientationAtIndex(m_currentFrame); | 287 orientation = frameOrientationAtIndex(m_currentFrame); |
289 | 288 |
290 GraphicsContextStateSaver saveContext(*ctxt, false); | 289 GraphicsContextStateSaver saveContext(*ctxt, false); |
291 if (orientation != DefaultImageOrientation) { | 290 if (orientation != DefaultImageOrientation) { |
292 saveContext.save(); | 291 saveContext.save(); |
293 | 292 |
294 // ImageOrientation expects the origin to be at (0, 0) | 293 // ImageOrientation expects the origin to be at (0, 0) |
295 ctxt->translate(normDstRect.x(), normDstRect.y()); | 294 ctxt->translate(normDstRect.x(), normDstRect.y()); |
296 normDstRect.setLocation(FloatPoint()); | 295 normDstRect.setLocation(FloatPoint()); |
297 | 296 |
298 ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); | 297 ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); |
299 | 298 |
300 if (orientation.usesWidthAsHeight()) { | 299 if (orientation.usesWidthAsHeight()) { |
301 // The destination rect will have it's width and height already reve
rsed for the orientation of | 300 // The destination rect will have it's width and height already reve
rsed for the orientation of |
302 // the image, as it was needed for page layout, so we need to revers
e it back here. | 301 // the image, as it was needed for page layout, so we need to revers
e it back here. |
303 normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRec
t.height(), normDstRect.width()); | 302 normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRec
t.height(), normDstRect.width()); |
304 } | 303 } |
305 } | 304 } |
306 | 305 |
307 image->draw(ctxt, normSrcRect, normDstRect, compositeOp); | 306 drawBitmap(ctxt, bitmap, normSrcRect, normDstRect, compositeOp); |
308 | 307 |
309 if (ImageObserver* observer = imageObserver()) | 308 if (ImageObserver* observer = imageObserver()) |
310 observer->didDraw(this); | 309 observer->didDraw(this); |
311 | 310 |
312 startAnimation(); | 311 startAnimation(); |
313 } | 312 } |
314 | 313 |
315 size_t BitmapImage::frameCount() | 314 size_t BitmapImage::frameCount() |
316 { | 315 { |
317 if (!m_haveFrameCount) { | 316 if (!m_haveFrameCount) { |
(...skipping 14 matching lines...) Expand all Loading... |
332 m_sizeAvailable = m_source.isSizeAvailable(); | 331 m_sizeAvailable = m_source.isSizeAvailable(); |
333 | 332 |
334 return m_sizeAvailable; | 333 return m_sizeAvailable; |
335 } | 334 } |
336 | 335 |
337 bool BitmapImage::ensureFrameIsCached(size_t index) | 336 bool BitmapImage::ensureFrameIsCached(size_t index) |
338 { | 337 { |
339 if (index >= frameCount()) | 338 if (index >= frameCount()) |
340 return false; | 339 return false; |
341 | 340 |
342 if (index >= m_frames.size() || !m_frames[index].m_frame) | 341 if (index >= m_frames.size() || m_frames[index].m_frame.isNull()) |
343 cacheFrame(index); | 342 cacheFrame(index); |
344 | 343 |
345 return true; | 344 return true; |
346 } | 345 } |
347 | 346 |
348 PassRefPtr<NativeImageSkia> BitmapImage::frameAtIndex(size_t index) | 347 SkBitmap BitmapImage::frameAtIndex(size_t index) |
349 { | 348 { |
350 if (!ensureFrameIsCached(index)) | 349 if (!ensureFrameIsCached(index)) |
351 return nullptr; | 350 return SkBitmap(); |
352 | 351 |
353 return m_frames[index].m_frame; | 352 return m_frames[index].m_frame; |
354 } | 353 } |
355 | 354 |
356 bool BitmapImage::frameIsCompleteAtIndex(size_t index) | 355 bool BitmapImage::frameIsCompleteAtIndex(size_t index) |
357 { | 356 { |
358 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isComplete) | 357 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isComplete) |
359 return true; | 358 return true; |
360 | 359 |
361 return m_source.frameIsCompleteAtIndex(index); | 360 return m_source.frameIsCompleteAtIndex(index); |
362 } | 361 } |
363 | 362 |
364 float BitmapImage::frameDurationAtIndex(size_t index) | 363 float BitmapImage::frameDurationAtIndex(size_t index) |
365 { | 364 { |
366 if (index < m_frames.size() && m_frames[index].m_haveMetadata) | 365 if (index < m_frames.size() && m_frames[index].m_haveMetadata) |
367 return m_frames[index].m_duration; | 366 return m_frames[index].m_duration; |
368 | 367 |
369 return m_source.frameDurationAtIndex(index); | 368 return m_source.frameDurationAtIndex(index); |
370 } | 369 } |
371 | 370 |
372 PassRefPtr<NativeImageSkia> BitmapImage::nativeImageForCurrentFrame() | 371 SkBitmap BitmapImage::bitmapForCurrentFrame() |
373 { | 372 { |
374 return frameAtIndex(currentFrame()); | 373 return frameAtIndex(currentFrame()); |
375 } | 374 } |
376 | 375 |
377 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() | 376 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() |
378 { | 377 { |
379 if (frameCount() > 1 && frameAtIndex(0)) | 378 if (frameCount() > 1 && !frameAtIndex(0).isNull()) |
380 return BitmapImage::create(frameAtIndex(0)); | 379 return BitmapImage::create(frameAtIndex(0)); |
381 | 380 |
382 return Image::imageForDefaultFrame(); | 381 return Image::imageForDefaultFrame(); |
383 } | 382 } |
384 | 383 |
385 bool BitmapImage::frameHasAlphaAtIndex(size_t index) | 384 bool BitmapImage::frameHasAlphaAtIndex(size_t index) |
386 { | 385 { |
387 if (m_frames.size() <= index) | 386 if (m_frames.size() <= index) |
388 return true; | 387 return true; |
389 | 388 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 } | 616 } |
618 | 617 |
619 void BitmapImage::checkForSolidColor() | 618 void BitmapImage::checkForSolidColor() |
620 { | 619 { |
621 m_isSolidColor = false; | 620 m_isSolidColor = false; |
622 m_checkedForSolidColor = true; | 621 m_checkedForSolidColor = true; |
623 | 622 |
624 if (frameCount() > 1) | 623 if (frameCount() > 1) |
625 return; | 624 return; |
626 | 625 |
627 RefPtr<NativeImageSkia> frame = frameAtIndex(0); | 626 SkBitmap bitmap = frameAtIndex(0); |
628 | 627 |
629 if (frame && size().width() == 1 && size().height() == 1) { | 628 if (!bitmap.isNull() && size().width() == 1 && size().height() == 1) { |
630 SkAutoLockPixels lock(frame->bitmap()); | 629 SkAutoLockPixels lock(bitmap); |
631 if (!frame->bitmap().getPixels()) | 630 if (!bitmap.getPixels()) |
632 return; | 631 return; |
633 | 632 |
634 m_isSolidColor = true; | 633 m_isSolidColor = true; |
635 m_solidColor = Color(frame->bitmap().getColor(0, 0)); | 634 m_solidColor = Color(bitmap.getColor(0, 0)); |
636 } | 635 } |
637 } | 636 } |
638 | 637 |
639 bool BitmapImage::mayFillWithSolidColor() | 638 bool BitmapImage::mayFillWithSolidColor() |
640 { | 639 { |
641 if (!m_checkedForSolidColor && frameCount() > 0) { | 640 if (!m_checkedForSolidColor && frameCount() > 0) { |
642 checkForSolidColor(); | 641 checkForSolidColor(); |
643 ASSERT(m_checkedForSolidColor); | 642 ASSERT(m_checkedForSolidColor); |
644 } | 643 } |
645 | 644 |
646 return m_isSolidColor && !m_currentFrame; | 645 return m_isSolidColor && !m_currentFrame; |
647 } | 646 } |
648 | 647 |
649 Color BitmapImage::solidColor() const | 648 Color BitmapImage::solidColor() const |
650 { | 649 { |
651 return m_solidColor; | 650 return m_solidColor; |
652 } | 651 } |
653 | 652 |
654 } // namespace blink | 653 } // namespace blink |
OLD | NEW |