| 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 |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * | 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 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/PlatformInstrumentation.h" |
| 30 #include "platform/Timer.h" | 31 #include "platform/Timer.h" |
| 31 #include "platform/TraceEvent.h" | 32 #include "platform/TraceEvent.h" |
| 32 #include "platform/geometry/FloatRect.h" | 33 #include "platform/geometry/FloatRect.h" |
| 34 #include "platform/graphics/DeferredImageDecoder.h" |
| 33 #include "platform/graphics/GraphicsContextStateSaver.h" | 35 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 34 #include "platform/graphics/ImageObserver.h" | 36 #include "platform/graphics/ImageObserver.h" |
| 35 #include "platform/graphics/skia/NativeImageSkia.h" | |
| 36 #include "platform/graphics/skia/SkiaUtils.h" | 37 #include "platform/graphics/skia/SkiaUtils.h" |
| 38 #include "third_party/skia/include/core/SkCanvas.h" |
| 37 #include "wtf/PassRefPtr.h" | 39 #include "wtf/PassRefPtr.h" |
| 38 #include "wtf/text/WTFString.h" | 40 #include "wtf/text/WTFString.h" |
| 39 | 41 |
| 40 namespace blink { | 42 namespace blink { |
| 41 | 43 |
| 42 PassRefPtr<BitmapImage> BitmapImage::create(PassRefPtr<NativeImageSkia> nativeIm
age, ImageObserver* observer) | 44 PassRefPtr<BitmapImage> BitmapImage::create(const SkBitmap& bitmap, ImageObserve
r* observer) |
| 43 { | 45 { |
| 44 if (!nativeImage) { | 46 if (bitmap.isNull()) { |
| 45 return BitmapImage::create(observer); | 47 return BitmapImage::create(observer); |
| 46 } | 48 } |
| 47 | 49 |
| 48 return adoptRef(new BitmapImage(nativeImage, observer)); | 50 return adoptRef(new BitmapImage(bitmap, observer)); |
| 49 } | 51 } |
| 50 | 52 |
| 51 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(PassRefPtr<
NativeImageSkia> nativeImage, ImageOrientation orientation) | 53 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBit
map& bitmap, ImageOrientation orientation) |
| 52 { | 54 { |
| 53 RefPtr<BitmapImage> result = create(nativeImage); | 55 RefPtr<BitmapImage> result = create(bitmap); |
| 54 result->m_frames[0].m_orientation = orientation; | 56 result->m_frames[0].m_orientation = orientation; |
| 55 if (orientation.usesWidthAsHeight()) | 57 if (orientation.usesWidthAsHeight()) |
| 56 result->m_sizeRespectingOrientation = IntSize(result->m_size.height(), r
esult->m_size.width()); | 58 result->m_sizeRespectingOrientation = IntSize(result->m_size.height(), r
esult->m_size.width()); |
| 57 return result.release(); | 59 return result.release(); |
| 58 } | 60 } |
| 59 | 61 |
| 60 BitmapImage::BitmapImage(ImageObserver* observer) | 62 BitmapImage::BitmapImage(ImageObserver* observer) |
| 61 : Image(observer) | 63 : Image(observer) |
| 62 , m_currentFrame(0) | 64 , m_currentFrame(0) |
| 63 , m_frames() | 65 , m_frames() |
| 64 , m_frameTimer(0) | 66 , m_frameTimer(0) |
| 65 , m_repetitionCount(cAnimationNone) | 67 , m_repetitionCount(cAnimationNone) |
| 66 , m_repetitionCountStatus(Unknown) | 68 , m_repetitionCountStatus(Unknown) |
| 67 , m_repetitionsComplete(0) | 69 , m_repetitionsComplete(0) |
| 68 , m_desiredFrameStartTime(0) | 70 , m_desiredFrameStartTime(0) |
| 69 , m_frameCount(0) | 71 , m_frameCount(0) |
| 70 , m_animationPolicy(ImageAnimationPolicyAllowed) | 72 , m_animationPolicy(ImageAnimationPolicyAllowed) |
| 71 , m_isSolidColor(false) | 73 , m_isSolidColor(false) |
| 72 , m_checkedForSolidColor(false) | 74 , m_checkedForSolidColor(false) |
| 73 , m_animationFinished(false) | 75 , m_animationFinished(false) |
| 74 , m_allDataReceived(false) | 76 , m_allDataReceived(false) |
| 75 , m_haveSize(false) | 77 , m_haveSize(false) |
| 76 , m_sizeAvailable(false) | 78 , m_sizeAvailable(false) |
| 77 , m_hasUniformFrameSize(true) | 79 , m_hasUniformFrameSize(true) |
| 78 , m_haveFrameCount(false) | 80 , m_haveFrameCount(false) |
| 79 { | 81 { |
| 80 } | 82 } |
| 81 | 83 |
| 82 BitmapImage::BitmapImage(PassRefPtr<NativeImageSkia> nativeImage, ImageObserver*
observer) | 84 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer) |
| 83 : Image(observer) | 85 : Image(observer) |
| 84 , m_size(nativeImage->bitmap().width(), nativeImage->bitmap().height()) | 86 , m_size(bitmap.width(), bitmap.height()) |
| 85 , m_currentFrame(0) | 87 , m_currentFrame(0) |
| 86 , m_frames(0) | 88 , m_frames(0) |
| 87 , m_frameTimer(0) | 89 , m_frameTimer(0) |
| 88 , m_repetitionCount(cAnimationNone) | 90 , m_repetitionCount(cAnimationNone) |
| 89 , m_repetitionCountStatus(Unknown) | 91 , m_repetitionCountStatus(Unknown) |
| 90 , m_repetitionsComplete(0) | 92 , m_repetitionsComplete(0) |
| 91 , m_frameCount(1) | 93 , m_frameCount(1) |
| 92 , m_animationPolicy(ImageAnimationPolicyAllowed) | 94 , m_animationPolicy(ImageAnimationPolicyAllowed) |
| 93 , m_isSolidColor(false) | 95 , m_isSolidColor(false) |
| 94 , m_checkedForSolidColor(false) | 96 , m_checkedForSolidColor(false) |
| 95 , m_animationFinished(true) | 97 , m_animationFinished(true) |
| 96 , m_allDataReceived(true) | 98 , m_allDataReceived(true) |
| 97 , m_haveSize(true) | 99 , m_haveSize(true) |
| 98 , m_sizeAvailable(true) | 100 , m_sizeAvailable(true) |
| 99 , m_haveFrameCount(true) | 101 , m_haveFrameCount(true) |
| 100 { | 102 { |
| 101 // Since we don't have a decoder, we can't figure out the image orientation. | 103 // 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. | 104 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. |
| 103 m_sizeRespectingOrientation = m_size; | 105 m_sizeRespectingOrientation = m_size; |
| 104 | 106 |
| 105 m_frames.grow(1); | 107 m_frames.grow(1); |
| 106 m_frames[0].m_hasAlpha = !nativeImage->bitmap().isOpaque(); | 108 m_frames[0].m_hasAlpha = !bitmap.isOpaque(); |
| 107 m_frames[0].m_frame = nativeImage; | 109 m_frames[0].m_frame = bitmap; |
| 108 m_frames[0].m_haveMetadata = true; | 110 m_frames[0].m_haveMetadata = true; |
| 109 | 111 |
| 110 checkForSolidColor(); | 112 checkForSolidColor(); |
| 111 } | 113 } |
| 112 | 114 |
| 113 BitmapImage::~BitmapImage() | 115 BitmapImage::~BitmapImage() |
| 114 { | 116 { |
| 115 stopAnimation(); | 117 stopAnimation(); |
| 116 } | 118 } |
| 117 | 119 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 if (frameBytesCleared && imageObserver()) | 161 if (frameBytesCleared && imageObserver()) |
| 160 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); | 162 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear
ed)); |
| 161 } | 163 } |
| 162 | 164 |
| 163 void BitmapImage::cacheFrame(size_t index) | 165 void BitmapImage::cacheFrame(size_t index) |
| 164 { | 166 { |
| 165 size_t numFrames = frameCount(); | 167 size_t numFrames = frameCount(); |
| 166 if (m_frames.size() < numFrames) | 168 if (m_frames.size() < numFrames) |
| 167 m_frames.grow(numFrames); | 169 m_frames.grow(numFrames); |
| 168 | 170 |
| 169 m_frames[index].m_frame = m_source.createFrameAtIndex(index); | 171 bool created = m_source.createFrameAtIndex(index, &m_frames[index].m_frame); |
| 170 if (numFrames == 1 && m_frames[index].m_frame) | 172 if (numFrames == 1 && created) |
| 171 checkForSolidColor(); | 173 checkForSolidColor(); |
| 172 | 174 |
| 173 m_frames[index].m_orientation = m_source.orientationAtIndex(index); | 175 m_frames[index].m_orientation = m_source.orientationAtIndex(index); |
| 174 m_frames[index].m_haveMetadata = true; | 176 m_frames[index].m_haveMetadata = true; |
| 175 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); | 177 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); |
| 176 if (repetitionCount(false) != cAnimationNone) | 178 if (repetitionCount(false) != cAnimationNone) |
| 177 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); | 179 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); |
| 178 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); | 180 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); |
| 179 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); | 181 m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index); |
| 180 | 182 |
| 181 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); | 183 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); |
| 182 if (frameSize != m_size) | 184 if (frameSize != m_size) |
| 183 m_hasUniformFrameSize = false; | 185 m_hasUniformFrameSize = false; |
| 184 | 186 |
| 185 if (m_frames[index].m_frame) { | 187 if (created) { |
| 186 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); | 188 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes); |
| 187 // The fully-decoded frame will subsume the partially decoded data used | 189 // The fully-decoded frame will subsume the partially decoded data used |
| 188 // to determine image properties. | 190 // to determine image properties. |
| 189 if (imageObserver()) | 191 if (imageObserver()) |
| 190 imageObserver()->decodedSizeChanged(this, deltaBytes); | 192 imageObserver()->decodedSizeChanged(this, deltaBytes); |
| 191 } | 193 } |
| 192 } | 194 } |
| 193 | 195 |
| 194 void BitmapImage::updateSize() const | 196 void BitmapImage::updateSize() const |
| 195 { | 197 { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 return m_source.hasColorProfile(); | 267 return m_source.hasColorProfile(); |
| 266 } | 268 } |
| 267 | 269 |
| 268 String BitmapImage::filenameExtension() const | 270 String BitmapImage::filenameExtension() const |
| 269 { | 271 { |
| 270 return m_source.filenameExtension(); | 272 return m_source.filenameExtension(); |
| 271 } | 273 } |
| 272 | 274 |
| 273 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum shou
ldRespectImageOrientation) | 275 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum shou
ldRespectImageOrientation) |
| 274 { | 276 { |
| 275 RefPtr<NativeImageSkia> image = nativeImageForCurrentFrame(); | 277 TRACE_EVENT0("skia", "BitmapImage::draw"); |
| 276 if (!image) | 278 |
| 279 SkBitmap bitmap; |
| 280 if (!bitmapForCurrentFrame(&bitmap)) |
| 277 return; // It's too early and we don't have an image yet. | 281 return; // It's too early and we don't have an image yet. |
| 278 | 282 |
| 279 FloatRect normDstRect = adjustForNegativeSize(dstRect); | 283 FloatRect normDstRect = adjustForNegativeSize(dstRect); |
| 280 FloatRect normSrcRect = adjustForNegativeSize(srcRect); | 284 FloatRect normSrcRect = adjustForNegativeSize(srcRect); |
| 281 normSrcRect.intersect(FloatRect(0, 0, image->bitmap().width(), image->bitmap
().height())); | 285 normSrcRect.intersect(FloatRect(0, 0, bitmap.width(), bitmap.height())); |
| 282 | 286 |
| 283 if (normSrcRect.isEmpty() || normDstRect.isEmpty()) | 287 if (normSrcRect.isEmpty() || normDstRect.isEmpty()) |
| 284 return; // Nothing to draw. | 288 return; // Nothing to draw. |
| 285 | 289 |
| 286 ImageOrientation orientation = DefaultImageOrientation; | 290 ImageOrientation orientation = DefaultImageOrientation; |
| 287 if (shouldRespectImageOrientation == RespectImageOrientation) | 291 if (shouldRespectImageOrientation == RespectImageOrientation) |
| 288 orientation = frameOrientationAtIndex(m_currentFrame); | 292 orientation = frameOrientationAtIndex(m_currentFrame); |
| 289 | 293 |
| 290 GraphicsContextStateSaver saveContext(*ctxt, false); | 294 GraphicsContextStateSaver saveContext(*ctxt, false); |
| 291 if (orientation != DefaultImageOrientation) { | 295 if (orientation != DefaultImageOrientation) { |
| 292 saveContext.save(); | 296 saveContext.save(); |
| 293 | 297 |
| 294 // ImageOrientation expects the origin to be at (0, 0) | 298 // ImageOrientation expects the origin to be at (0, 0) |
| 295 ctxt->translate(normDstRect.x(), normDstRect.y()); | 299 ctxt->translate(normDstRect.x(), normDstRect.y()); |
| 296 normDstRect.setLocation(FloatPoint()); | 300 normDstRect.setLocation(FloatPoint()); |
| 297 | 301 |
| 298 ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); | 302 ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); |
| 299 | 303 |
| 300 if (orientation.usesWidthAsHeight()) { | 304 if (orientation.usesWidthAsHeight()) { |
| 301 // The destination rect will have it's width and height already reve
rsed for the orientation of | 305 // 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. | 306 // 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()); | 307 normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRec
t.height(), normDstRect.width()); |
| 304 } | 308 } |
| 305 } | 309 } |
| 306 | 310 |
| 307 image->draw(ctxt, normSrcRect, normDstRect, compositeOp); | 311 bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap); |
| 312 bool isOpaque = bitmap.isOpaque(); |
| 313 |
| 314 { |
| 315 SkPaint paint; |
| 316 SkRect skSrcRect = normSrcRect; |
| 317 int initialSaveCount = ctxt->preparePaintForDrawRectToRect(&paint, skSrc
Rect, normDstRect, compositeOp, !isOpaque, isLazyDecoded, bitmap.isImmutable()); |
| 318 // We want to filter it if we decided to do interpolation above, or if |
| 319 // there is something interesting going on with the matrix (like a rotat
ion). |
| 320 // Note: for serialization, we will want to subset the bitmap first so w
e |
| 321 // don't send extra pixels. |
| 322 ctxt->drawBitmapRect(bitmap, &skSrcRect, normDstRect, &paint); |
| 323 ctxt->canvas()->restoreToCount(initialSaveCount); |
| 324 } |
| 325 |
| 326 if (isLazyDecoded) |
| 327 PlatformInstrumentation::didDrawLazyPixelRef(bitmap.getGenerationID()); |
| 308 | 328 |
| 309 if (ImageObserver* observer = imageObserver()) | 329 if (ImageObserver* observer = imageObserver()) |
| 310 observer->didDraw(this); | 330 observer->didDraw(this); |
| 311 | 331 |
| 312 startAnimation(); | 332 startAnimation(); |
| 313 } | 333 } |
| 314 | 334 |
| 315 size_t BitmapImage::frameCount() | 335 size_t BitmapImage::frameCount() |
| 316 { | 336 { |
| 317 if (!m_haveFrameCount) { | 337 if (!m_haveFrameCount) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 332 m_sizeAvailable = m_source.isSizeAvailable(); | 352 m_sizeAvailable = m_source.isSizeAvailable(); |
| 333 | 353 |
| 334 return m_sizeAvailable; | 354 return m_sizeAvailable; |
| 335 } | 355 } |
| 336 | 356 |
| 337 bool BitmapImage::ensureFrameIsCached(size_t index) | 357 bool BitmapImage::ensureFrameIsCached(size_t index) |
| 338 { | 358 { |
| 339 if (index >= frameCount()) | 359 if (index >= frameCount()) |
| 340 return false; | 360 return false; |
| 341 | 361 |
| 342 if (index >= m_frames.size() || !m_frames[index].m_frame) | 362 if (index >= m_frames.size() || m_frames[index].m_frame.isNull()) |
| 343 cacheFrame(index); | 363 cacheFrame(index); |
| 344 | 364 |
| 345 return true; | 365 return true; |
| 346 } | 366 } |
| 347 | 367 |
| 348 PassRefPtr<NativeImageSkia> BitmapImage::frameAtIndex(size_t index) | 368 bool BitmapImage::frameAtIndex(size_t index, SkBitmap* bitmap) |
| 349 { | 369 { |
| 350 if (!ensureFrameIsCached(index)) | 370 if (!ensureFrameIsCached(index)) |
| 351 return nullptr; | 371 return false; |
| 352 | 372 |
| 353 return m_frames[index].m_frame; | 373 *bitmap = m_frames[index].m_frame; |
| 374 return true; |
| 354 } | 375 } |
| 355 | 376 |
| 356 bool BitmapImage::frameIsCompleteAtIndex(size_t index) | 377 bool BitmapImage::frameIsCompleteAtIndex(size_t index) |
| 357 { | 378 { |
| 358 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isComplete) | 379 if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[in
dex].m_isComplete) |
| 359 return true; | 380 return true; |
| 360 | 381 |
| 361 return m_source.frameIsCompleteAtIndex(index); | 382 return m_source.frameIsCompleteAtIndex(index); |
| 362 } | 383 } |
| 363 | 384 |
| 364 float BitmapImage::frameDurationAtIndex(size_t index) | 385 float BitmapImage::frameDurationAtIndex(size_t index) |
| 365 { | 386 { |
| 366 if (index < m_frames.size() && m_frames[index].m_haveMetadata) | 387 if (index < m_frames.size() && m_frames[index].m_haveMetadata) |
| 367 return m_frames[index].m_duration; | 388 return m_frames[index].m_duration; |
| 368 | 389 |
| 369 return m_source.frameDurationAtIndex(index); | 390 return m_source.frameDurationAtIndex(index); |
| 370 } | 391 } |
| 371 | 392 |
| 372 PassRefPtr<NativeImageSkia> BitmapImage::nativeImageForCurrentFrame() | 393 bool BitmapImage::bitmapForCurrentFrame(SkBitmap* bitmap) |
| 373 { | 394 { |
| 374 return frameAtIndex(currentFrame()); | 395 return frameAtIndex(currentFrame(), bitmap); |
| 375 } | 396 } |
| 376 | 397 |
| 377 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() | 398 PassRefPtr<Image> BitmapImage::imageForDefaultFrame() |
| 378 { | 399 { |
| 379 if (frameCount() > 1 && frameAtIndex(0)) | 400 SkBitmap bitmap; |
| 380 return BitmapImage::create(frameAtIndex(0)); | 401 if (frameCount() > 1 && frameAtIndex(0, &bitmap)) |
| 402 return BitmapImage::create(bitmap); |
| 381 | 403 |
| 382 return Image::imageForDefaultFrame(); | 404 return Image::imageForDefaultFrame(); |
| 383 } | 405 } |
| 384 | 406 |
| 385 bool BitmapImage::frameHasAlphaAtIndex(size_t index) | 407 bool BitmapImage::frameHasAlphaAtIndex(size_t index) |
| 386 { | 408 { |
| 387 if (m_frames.size() <= index) | 409 if (m_frames.size() <= index) |
| 388 return true; | 410 return true; |
| 389 | 411 |
| 390 if (m_frames[index].m_haveMetadata) | 412 if (m_frames[index].m_haveMetadata) |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 } | 639 } |
| 618 | 640 |
| 619 void BitmapImage::checkForSolidColor() | 641 void BitmapImage::checkForSolidColor() |
| 620 { | 642 { |
| 621 m_isSolidColor = false; | 643 m_isSolidColor = false; |
| 622 m_checkedForSolidColor = true; | 644 m_checkedForSolidColor = true; |
| 623 | 645 |
| 624 if (frameCount() > 1) | 646 if (frameCount() > 1) |
| 625 return; | 647 return; |
| 626 | 648 |
| 627 RefPtr<NativeImageSkia> frame = frameAtIndex(0); | 649 SkBitmap bitmap; |
| 628 | 650 if (frameAtIndex(0, &bitmap) && size().width() == 1 && size().height() == 1)
{ |
| 629 if (frame && size().width() == 1 && size().height() == 1) { | 651 SkAutoLockPixels lock(bitmap); |
| 630 SkAutoLockPixels lock(frame->bitmap()); | 652 if (!bitmap.getPixels()) |
| 631 if (!frame->bitmap().getPixels()) | |
| 632 return; | 653 return; |
| 633 | 654 |
| 634 m_isSolidColor = true; | 655 m_isSolidColor = true; |
| 635 m_solidColor = Color(frame->bitmap().getColor(0, 0)); | 656 m_solidColor = Color(bitmap.getColor(0, 0)); |
| 636 } | 657 } |
| 637 } | 658 } |
| 638 | 659 |
| 639 bool BitmapImage::mayFillWithSolidColor() | 660 bool BitmapImage::mayFillWithSolidColor() |
| 640 { | 661 { |
| 641 if (!m_checkedForSolidColor && frameCount() > 0) { | 662 if (!m_checkedForSolidColor && frameCount() > 0) { |
| 642 checkForSolidColor(); | 663 checkForSolidColor(); |
| 643 ASSERT(m_checkedForSolidColor); | 664 ASSERT(m_checkedForSolidColor); |
| 644 } | 665 } |
| 645 | 666 |
| 646 return m_isSolidColor && !m_currentFrame; | 667 return m_isSolidColor && !m_currentFrame; |
| 647 } | 668 } |
| 648 | 669 |
| 649 Color BitmapImage::solidColor() const | 670 Color BitmapImage::solidColor() const |
| 650 { | 671 { |
| 651 return m_solidColor; | 672 return m_solidColor; |
| 652 } | 673 } |
| 653 | 674 |
| 654 } // namespace blink | 675 } // namespace blink |
| OLD | NEW |