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 |