| 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 13 matching lines...) Expand all Loading... |
| 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 "platform/graphics/BitmapImage.h" | 27 #include "platform/graphics/BitmapImage.h" |
| 28 | 28 |
| 29 #include "platform/PlatformInstrumentation.h" | 29 #include "platform/PlatformInstrumentation.h" |
| 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/BitmapImageMetrics.h" | 33 #include "platform/graphics/BitmapImageMetrics.h" |
| 34 #include "platform/graphics/ColorSpaceFilter.h" |
| 35 #include "platform/graphics/ColorSpaceProfile.h" |
| 34 #include "platform/graphics/DeferredImageDecoder.h" | 36 #include "platform/graphics/DeferredImageDecoder.h" |
| 37 #include "platform/graphics/GraphicsContext.h" |
| 38 #include "platform/graphics/GraphicsScreen.h" |
| 39 #include "platform/graphics/ImageBuffer.h" |
| 35 #include "platform/graphics/ImageObserver.h" | 40 #include "platform/graphics/ImageObserver.h" |
| 36 #include "platform/graphics/StaticBitmapImage.h" | 41 #include "platform/graphics/StaticBitmapImage.h" |
| 37 #include "platform/graphics/skia/SkiaUtils.h" | 42 #include "platform/graphics/skia/SkiaUtils.h" |
| 38 #include "third_party/skia/include/core/SkCanvas.h" | 43 #include "third_party/skia/include/core/SkCanvas.h" |
| 44 #include "third_party/skia/include/core/SkColorFilter.h" |
| 45 #include "third_party/skia/include/core/SkImageGenerator.h" |
| 39 #include "wtf/PassRefPtr.h" | 46 #include "wtf/PassRefPtr.h" |
| 47 #include "wtf/RefPtr.h" |
| 40 #include "wtf/text/WTFString.h" | 48 #include "wtf/text/WTFString.h" |
| 41 | 49 |
| 42 namespace blink { | 50 namespace blink { |
| 43 | 51 |
| 44 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBit
map& bitmap, ImageOrientation orientation) | 52 PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBit
map& bitmap, ImageOrientation orientation) |
| 45 { | 53 { |
| 46 if (bitmap.isNull()) { | 54 if (bitmap.isNull()) { |
| 47 return BitmapImage::create(); | 55 return BitmapImage::create(); |
| 48 } | 56 } |
| 49 | 57 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 m_frames[0].m_hasAlpha = !bitmap.isOpaque(); | 103 m_frames[0].m_hasAlpha = !bitmap.isOpaque(); |
| 96 m_frames[0].m_frame = adoptRef(SkImage::NewFromBitmap(bitmap)); | 104 m_frames[0].m_frame = adoptRef(SkImage::NewFromBitmap(bitmap)); |
| 97 m_frames[0].m_haveMetadata = true; | 105 m_frames[0].m_haveMetadata = true; |
| 98 } | 106 } |
| 99 | 107 |
| 100 BitmapImage::~BitmapImage() | 108 BitmapImage::~BitmapImage() |
| 101 { | 109 { |
| 102 stopAnimation(); | 110 stopAnimation(); |
| 103 } | 111 } |
| 104 | 112 |
| 105 bool BitmapImage::isBitmapImage() const | |
| 106 { | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 bool BitmapImage::currentFrameHasSingleSecurityOrigin() const | 113 bool BitmapImage::currentFrameHasSingleSecurityOrigin() const |
| 111 { | 114 { |
| 112 return true; | 115 return true; |
| 113 } | 116 } |
| 114 | 117 |
| 115 int BitmapImage::totalFrameBytes() | 118 int BitmapImage::totalFrameBytes() |
| 116 { | 119 { |
| 117 const size_t numFrames = frameCount(); | 120 const size_t numFrames = frameCount(); |
| 118 size_t totalBytes = 0; | 121 size_t totalBytes = 0; |
| 119 for (size_t i = 0; i < numFrames; ++i) | 122 for (size_t i = 0; i < numFrames; ++i) |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 bool BitmapImage::hasColorProfile() const | 261 bool BitmapImage::hasColorProfile() const |
| 259 { | 262 { |
| 260 return m_source.hasColorProfile(); | 263 return m_source.hasColorProfile(); |
| 261 } | 264 } |
| 262 | 265 |
| 263 String BitmapImage::filenameExtension() const | 266 String BitmapImage::filenameExtension() const |
| 264 { | 267 { |
| 265 return m_source.filenameExtension(); | 268 return m_source.filenameExtension(); |
| 266 } | 269 } |
| 267 | 270 |
| 271 PassRefPtr<SkImage> BitmapImage::pictureForCurrentFrame() |
| 272 { |
| 273 RELEASE_ASSERT(currentFrame() < m_frames.size() && m_frames[currentFrame()].
m_frame); |
| 274 |
| 275 FrameData& frame = m_frames[currentFrame()]; |
| 276 |
| 277 RELEASE_ASSERT(currentScreenId()); // There should be an active graphics scr
een. |
| 278 |
| 279 RefPtr<SkColorFilter> colorTransform; |
| 280 if (imageColorProfilesEnabled()) { |
| 281 RefPtr<ColorSpaceProfile> source = colorProfile(); |
| 282 if (!source) |
| 283 source = screenColorProfile(ScreenDevice::sRGB); |
| 284 colorTransform = createColorSpaceFilter(source.get(), screenColorProfile
(currentScreenId()).get()); |
| 285 } |
| 286 |
| 287 if (!colorTransform) |
| 288 return frame.m_frame; |
| 289 |
| 290 RefPtr<SkImage> cachedImage = frame.find(colorTransform.get()); |
| 291 if (cachedImage) |
| 292 return cachedImage; |
| 293 |
| 294 RefPtr<SkImage> skImage = frame.m_frame; |
| 295 SkPictureRecorder recorder; |
| 296 SkRect bounds = SkRect::MakeIWH(skImage->width(), skImage->height()); |
| 297 SkCanvas* canvas = recorder.beginRecording(bounds, nullptr, 0); |
| 298 SkPaint paint; |
| 299 paint.setColorFilter(colorTransform.get()); |
| 300 canvas->drawImage(skImage.get(), 0, 0, &paint); |
| 301 |
| 302 RefPtr<SkPicture> picture = adoptRef(recorder.endRecording()); |
| 303 if (!picture) |
| 304 return skImage; |
| 305 |
| 306 SkISize skISize = SkISize::Make(skImage->width(), skImage->height()); |
| 307 skImage = adoptRef(SkImage::NewFromPicture(picture.get(), skISize, nullptr,
nullptr)); |
| 308 |
| 309 // FIXME: Should we not cache if (currentScreenId() == ScreenDevice::sRGBCan
vas)? |
| 310 frame.cache(colorTransform.get(), skImage.get()); |
| 311 return skImage; |
| 312 } |
| 313 |
| 268 void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect&
dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImag
eOrientation, ImageClampingMode clampMode) | 314 void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect&
dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImag
eOrientation, ImageClampingMode clampMode) |
| 269 { | 315 { |
| 270 TRACE_EVENT0("skia", "BitmapImage::draw"); | 316 TRACE_EVENT0("skia", "BitmapImage::draw"); |
| 271 | 317 |
| 272 RefPtr<SkImage> image = imageForCurrentFrame(); | 318 RefPtr<SkImage> skImage = imageForCurrentFrame(); |
| 273 if (!image) | 319 if (!skImage) |
| 274 return; // It's too early and we don't have an image yet. | 320 return; // Bail: we don't have an image yet. |
| 321 |
| 322 skImage = pictureForCurrentFrame(); |
| 323 if (!skImage) |
| 324 return; |
| 275 | 325 |
| 276 FloatRect adjustedSrcRect = srcRect; | 326 FloatRect adjustedSrcRect = srcRect; |
| 277 adjustedSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); | 327 adjustedSrcRect.intersect(FloatRect(0, 0, skImage->width(), skImage->height(
))); |
| 278 | |
| 279 if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) | 328 if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) |
| 280 return; // Nothing to draw. | 329 return; // Nothing to draw. |
| 330 FloatRect adjustedDstRect = dstRect; |
| 281 | 331 |
| 282 ImageOrientation orientation = DefaultImageOrientation; | 332 ImageOrientation orientation = DefaultImageOrientation; |
| 283 if (shouldRespectImageOrientation == RespectImageOrientation) | 333 if (shouldRespectImageOrientation == RespectImageOrientation) |
| 284 orientation = frameOrientationAtIndex(m_currentFrame); | 334 orientation = frameOrientationAtIndex(m_currentFrame); |
| 285 | 335 |
| 336 SkCanvas::SrcRectConstraint srcRectConstraint = WebCoreClampingModeToSkiaRec
tConstraint(clampMode); |
| 337 |
| 286 int initialSaveCount = canvas->getSaveCount(); | 338 int initialSaveCount = canvas->getSaveCount(); |
| 287 FloatRect adjustedDstRect = dstRect; | 339 |
| 288 if (orientation != DefaultImageOrientation) { | 340 if (orientation != DefaultImageOrientation) { |
| 289 canvas->save(); | 341 canvas->save(); |
| 290 | 342 |
| 291 // ImageOrientation expects the origin to be at (0, 0) | 343 // ImageOrientation expects the origin to be at (0, 0) |
| 292 canvas->translate(adjustedDstRect.x(), adjustedDstRect.y()); | 344 canvas->translate(adjustedDstRect.x(), adjustedDstRect.y()); |
| 293 adjustedDstRect.setLocation(FloatPoint()); | 345 adjustedDstRect.setLocation(FloatPoint()); |
| 294 | 346 |
| 295 canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefaul
t(adjustedDstRect.size()))); | 347 canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefaul
t(adjustedDstRect.size()))); |
| 296 | 348 |
| 297 if (orientation.usesWidthAsHeight()) { | 349 if (orientation.usesWidthAsHeight()) { |
| 298 // The destination rect will have it's width and height already reve
rsed for the orientation of | 350 // The destination rect will have it's width and height already reve
rsed for the orientation of |
| 299 // the image, as it was needed for page layout, so we need to revers
e it back here. | 351 // the image, as it was needed for page layout, so we need to revers
e it back here. |
| 300 adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y()
, adjustedDstRect.height(), adjustedDstRect.width()); | 352 adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y()
, adjustedDstRect.height(), adjustedDstRect.width()); |
| 301 } | 353 } |
| 302 } | 354 } |
| 303 | 355 |
| 304 SkRect skSrcRect = adjustedSrcRect; | 356 canvas->drawImageRect(skImage.get(), adjustedSrcRect, adjustedDstRect, &pain
t, srcRectConstraint); |
| 305 canvas->drawImageRect(image.get(), skSrcRect, adjustedDstRect, &paint, | 357 |
| 306 WebCoreClampingModeToSkiaRectConstraint(clampMode)); | |
| 307 canvas->restoreToCount(initialSaveCount); | 358 canvas->restoreToCount(initialSaveCount); |
| 308 | 359 if (skImage->isLazyGenerated()) |
| 309 if (currentFrameIsLazyDecoded()) | 360 PlatformInstrumentation::didDrawLazyPixelRef(skImage->uniqueID()); |
| 310 PlatformInstrumentation::didDrawLazyPixelRef(image->uniqueID()); | |
| 311 | 361 |
| 312 if (ImageObserver* observer = imageObserver()) | 362 if (ImageObserver* observer = imageObserver()) |
| 313 observer->didDraw(this); | 363 observer->didDraw(this); |
| 314 | 364 |
| 315 startAnimation(); | 365 startAnimation(); |
| 316 } | 366 } |
| 317 | 367 |
| 318 size_t BitmapImage::frameCount() | 368 size_t BitmapImage::frameCount() |
| 319 { | 369 { |
| 320 if (!m_haveFrameCount) { | 370 if (!m_haveFrameCount) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 { | 442 { |
| 393 if (frameCount() > 1) { | 443 if (frameCount() > 1) { |
| 394 RefPtr<SkImage> firstFrame = frameAtIndex(0); | 444 RefPtr<SkImage> firstFrame = frameAtIndex(0); |
| 395 if (firstFrame) | 445 if (firstFrame) |
| 396 return StaticBitmapImage::create(firstFrame); | 446 return StaticBitmapImage::create(firstFrame); |
| 397 } | 447 } |
| 398 | 448 |
| 399 return Image::imageForDefaultFrame(); | 449 return Image::imageForDefaultFrame(); |
| 400 } | 450 } |
| 401 | 451 |
| 452 PassRefPtr<SkColorFilter> BitmapImage::imageColorTransform() |
| 453 { |
| 454 return createColorSpaceFilter(colorProfile().get(), screenColorProfile(curre
ntScreenId()).get()); |
| 455 } |
| 456 |
| 402 bool BitmapImage::frameHasAlphaAtIndex(size_t index) | 457 bool BitmapImage::frameHasAlphaAtIndex(size_t index) |
| 403 { | 458 { |
| 404 if (m_frames.size() <= index) | 459 if (m_frames.size() <= index) |
| 405 return true; | 460 return true; |
| 406 | 461 |
| 407 if (m_frames[index].m_haveMetadata) | 462 if (m_frames[index].m_haveMetadata) |
| 408 return m_frames[index].m_hasAlpha; | 463 return m_frames[index].m_hasAlpha; |
| 409 | 464 |
| 410 return m_source.frameHasAlphaAtIndex(index); | 465 return m_source.frameHasAlphaAtIndex(index); |
| 411 } | 466 } |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 destroyDecodedDataIfNecessary(); | 698 destroyDecodedDataIfNecessary(); |
| 644 | 699 |
| 645 // We need to draw this frame if we advanced to it while not skipping, or if | 700 // We need to draw this frame if we advanced to it while not skipping, or if |
| 646 // while trying to skip frames we hit the last frame and thus had to stop. | 701 // while trying to skip frames we hit the last frame and thus had to stop. |
| 647 if (skippingFrames != advancedAnimation) | 702 if (skippingFrames != advancedAnimation) |
| 648 imageObserver()->animationAdvanced(this); | 703 imageObserver()->animationAdvanced(this); |
| 649 return advancedAnimation; | 704 return advancedAnimation; |
| 650 } | 705 } |
| 651 | 706 |
| 652 } // namespace blink | 707 } // namespace blink |
| OLD | NEW |