Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/BitmapImage.cpp

Issue 1331533002: [poc] curve-filter Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Ensure screen device profiles are matrix Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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/effects/SkColorFilterImageFilter.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 }
49 56
50 RefPtr<BitmapImage> result = adoptRef(new BitmapImage(bitmap)); 57 RefPtr<BitmapImage> result = adoptRef(new BitmapImage(bitmap));
51 result->m_frames[0].m_orientation = orientation; 58 result->m_frames[0].m_orientation = orientation;
52 if (orientation.usesWidthAsHeight()) 59 if (orientation.usesWidthAsHeight())
53 result->m_sizeRespectingOrientation = result->m_size.transposedSize(); 60 result->m_sizeRespectingOrientation = result->m_size.transposedSize();
54 return result.release(); 61 return result.release();
55 } 62 }
56 63
57 BitmapImage::BitmapImage(ImageObserver* observer) 64 BitmapImage::BitmapImage(ImageObserver* observer)
58 : Image(observer) 65 : Image(observer)
59 , m_currentFrame(0) 66 , m_currentFrame(0)
60 , m_repetitionCount(cAnimationNone) 67 , m_repetitionCount(cAnimationNone)
61 , m_repetitionCountStatus(Unknown) 68 , m_repetitionCountStatus(Unknown)
62 , m_repetitionsComplete(0) 69 , m_repetitionsComplete(0)
63 , m_desiredFrameStartTime(0) 70 , m_desiredFrameStartTime(0)
64 , m_frameCount(0) 71 , m_frameCount(0)
65 , m_animationPolicy(ImageAnimationPolicyAllowed) 72 , m_animationPolicy(ImageAnimationPolicyAllowed)
66 , m_animationFinished(false) 73 , m_animationFinished(false)
67 , m_allDataReceived(false) 74 , m_allDataReceived(false)
68 , m_haveSize(false) 75 , m_haveSize(false)
69 , m_sizeAvailable(false) 76 , m_sizeAvailable(false)
70 , m_hasUniformFrameSize(true) 77 , m_hasUniformFrameSize(true)
71 , m_haveFrameCount(false) 78 , m_haveFrameCount(false)
79 , m_drawingToCanvasElement(false)
72 { 80 {
73 } 81 }
74 82
75 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer) 83 BitmapImage::BitmapImage(const SkBitmap& bitmap, ImageObserver* observer)
76 : Image(observer) 84 : Image(observer)
77 , m_size(bitmap.width(), bitmap.height()) 85 , m_size(bitmap.width(), bitmap.height())
78 , m_currentFrame(0) 86 , m_currentFrame(0)
79 , m_repetitionCount(cAnimationNone) 87 , m_repetitionCount(cAnimationNone)
80 , m_repetitionCountStatus(Unknown) 88 , m_repetitionCountStatus(Unknown)
81 , m_repetitionsComplete(0) 89 , m_repetitionsComplete(0)
82 , m_frameCount(1) 90 , m_frameCount(1)
83 , m_animationPolicy(ImageAnimationPolicyAllowed) 91 , m_animationPolicy(ImageAnimationPolicyAllowed)
84 , m_animationFinished(true) 92 , m_animationFinished(true)
85 , m_allDataReceived(true) 93 , m_allDataReceived(true)
86 , m_haveSize(true) 94 , m_haveSize(true)
87 , m_sizeAvailable(true) 95 , m_sizeAvailable(true)
88 , m_haveFrameCount(true) 96 , m_haveFrameCount(true)
97 , m_drawingToCanvasElement(false)
89 { 98 {
90 // Since we don't have a decoder, we can't figure out the image orientation. 99 // Since we don't have a decoder, we can't figure out the image orientation.
91 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. 100 // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0.
92 m_sizeRespectingOrientation = m_size; 101 m_sizeRespectingOrientation = m_size;
93 102
94 m_frames.grow(1); 103 m_frames.grow(1);
95 m_frames[0].m_hasAlpha = !bitmap.isOpaque(); 104 m_frames[0].m_hasAlpha = !bitmap.isOpaque();
96 m_frames[0].m_frame = adoptRef(SkImage::NewFromBitmap(bitmap)); 105 m_frames[0].m_frame = adoptRef(SkImage::NewFromBitmap(bitmap));
97 m_frames[0].m_haveMetadata = true; 106 m_frames[0].m_haveMetadata = true;
98 } 107 }
99 108
100 BitmapImage::~BitmapImage() 109 BitmapImage::~BitmapImage()
101 { 110 {
102 stopAnimation(); 111 stopAnimation();
103 } 112 }
104 113
105 bool BitmapImage::isBitmapImage() const
106 {
107 return true;
108 }
109
110 bool BitmapImage::currentFrameHasSingleSecurityOrigin() const
111 {
112 return true;
113 }
114
115 int BitmapImage::totalFrameBytes() 114 int BitmapImage::totalFrameBytes()
116 { 115 {
117 const size_t numFrames = frameCount(); 116 const size_t numFrames = frameCount();
118 size_t totalBytes = 0; 117 size_t totalBytes = 0;
119 for (size_t i = 0; i < numFrames; ++i) 118 for (size_t i = 0; i < numFrames; ++i)
120 totalBytes += m_source.frameBytesAtIndex(i); 119 totalBytes += m_source.frameBytesAtIndex(i);
121 return safeCast<int>(totalBytes); 120 return safeCast<int>(totalBytes);
122 } 121 }
123 122
124 void BitmapImage::destroyDecodedData(bool destroyAll) 123 void BitmapImage::destroyDecodedData(bool destroyAll)
(...skipping 10 matching lines...) Expand all
135 134
136 void BitmapImage::destroyDecodedDataIfNecessary() 135 void BitmapImage::destroyDecodedDataIfNecessary()
137 { 136 {
138 // Animated images >5MB are considered large enough that we'll only hang on 137 // Animated images >5MB are considered large enough that we'll only hang on
139 // to one frame at a time. 138 // to one frame at a time.
140 static const size_t cLargeAnimationCutoff = 5242880; 139 static const size_t cLargeAnimationCutoff = 5242880;
141 size_t allFrameBytes = 0; 140 size_t allFrameBytes = 0;
142 for (size_t i = 0; i < m_frames.size(); ++i) 141 for (size_t i = 0; i < m_frames.size(); ++i)
143 allFrameBytes += m_frames[i].m_frameBytes; 142 allFrameBytes += m_frames[i].m_frameBytes;
144 143
145 if (allFrameBytes > cLargeAnimationCutoff) { 144 if (allFrameBytes > cLargeAnimationCutoff)
146 destroyDecodedData(false); 145 destroyDecodedData(false);
147 }
148 } 146 }
149 147
150 void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared) 148 void BitmapImage::destroyMetadataAndNotify(size_t frameBytesCleared)
151 { 149 {
152 if (frameBytesCleared && imageObserver()) 150 if (frameBytesCleared && imageObserver())
153 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear ed)); 151 imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesClear ed));
154 } 152 }
155 153
156 void BitmapImage::cacheFrame(size_t index) 154 void BitmapImage::cacheFrame(size_t index)
157 { 155 {
158 size_t numFrames = frameCount(); 156 size_t numFrames = frameCount();
159 if (m_frames.size() < numFrames) 157 if (m_frames.size() < numFrames)
160 m_frames.grow(numFrames); 158 m_frames.grow(numFrames);
161 159
162 int deltaBytes = totalFrameBytes(); 160 int deltaBytes = totalFrameBytes();
163 161
164
165 // We are caching frame snapshots. This is OK even for partially decoded fr ames, 162 // We are caching frame snapshots. This is OK even for partially decoded fr ames,
166 // as they are cleared by dataChanged() when new data arrives. 163 // as they are cleared by dataChanged() when new data arrives.
167 m_frames[index].m_frame = m_source.createFrameAtIndex(index); 164 m_frames[index].m_frame = m_source.createFrameAtIndex(index);
168 165
169 m_frames[index].m_orientation = m_source.orientationAtIndex(index); 166 m_frames[index].m_orientation = m_source.orientationAtIndex(index);
170 m_frames[index].m_haveMetadata = true; 167 m_frames[index].m_haveMetadata = true;
171 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); 168 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);
172 if (repetitionCount(false) != cAnimationNone) 169 if (repetitionCount(false) != cAnimationNone)
173 m_frames[index].m_duration = m_source.frameDurationAtIndex(index); 170 m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
174 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); 171 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 259
263 String BitmapImage::filenameExtension() const 260 String BitmapImage::filenameExtension() const
264 { 261 {
265 return m_source.filenameExtension(); 262 return m_source.filenameExtension();
266 } 263 }
267 264
268 void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImag eOrientation, ImageClampingMode clampMode) 265 void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImag eOrientation, ImageClampingMode clampMode)
269 { 266 {
270 TRACE_EVENT0("skia", "BitmapImage::draw"); 267 TRACE_EVENT0("skia", "BitmapImage::draw");
271 268
272 RefPtr<SkImage> image = imageForCurrentFrame(); 269 RefPtr<SkImage> skImage = imageForCurrentFrame();
273 if (!image) 270 if (!skImage)
274 return; // It's too early and we don't have an image yet. 271 return; // Bail: we don't have an image yet.
275 272
276 FloatRect adjustedSrcRect = srcRect; 273 FloatRect adjustedSrcRect = srcRect;
277 adjustedSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); 274 adjustedSrcRect.intersect(FloatRect(0, 0, skImage->width(), skImage->height( )));
278
279 if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) 275 if (adjustedSrcRect.isEmpty() || dstRect.isEmpty())
280 return; // Nothing to draw. 276 return; // Nothing to draw.
277 FloatRect adjustedDstRect = dstRect;
281 278
282 ImageOrientation orientation = DefaultImageOrientation; 279 ImageOrientation orientation = DefaultImageOrientation;
283 if (shouldRespectImageOrientation == RespectImageOrientation) 280 if (shouldRespectImageOrientation == RespectImageOrientation)
284 orientation = frameOrientationAtIndex(m_currentFrame); 281 orientation = frameOrientationAtIndex(m_currentFrame);
285 282
283 SkCanvas::SrcRectConstraint srcRectConstraint = WebCoreClampingModeToSkiaRec tConstraint(clampMode);
284
286 int initialSaveCount = canvas->getSaveCount(); 285 int initialSaveCount = canvas->getSaveCount();
287 FloatRect adjustedDstRect = dstRect; 286
288 if (orientation != DefaultImageOrientation) { 287 if (orientation != DefaultImageOrientation) {
289 canvas->save(); 288 canvas->save();
290 289
291 // ImageOrientation expects the origin to be at (0, 0) 290 // ImageOrientation expects the origin to be at (0, 0)
292 canvas->translate(adjustedDstRect.x(), adjustedDstRect.y()); 291 canvas->translate(adjustedDstRect.x(), adjustedDstRect.y());
293 adjustedDstRect.setLocation(FloatPoint()); 292 adjustedDstRect.setLocation(FloatPoint());
294 293
295 canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefaul t(adjustedDstRect.size()))); 294 canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefaul t(adjustedDstRect.size())));
296 295
297 if (orientation.usesWidthAsHeight()) { 296 if (orientation.usesWidthAsHeight()) {
298 // The destination rect will have it's width and height already reve rsed for the orientation of 297 // 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. 298 // 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()); 299 adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y() , adjustedDstRect.height(), adjustedDstRect.width());
301 } 300 }
302 } 301 }
303 302
304 SkRect skSrcRect = adjustedSrcRect; 303 RefPtr<SkColorFilter> transform;
305 canvas->drawImageRect(image.get(), skSrcRect, adjustedDstRect, &paint, 304 if (imageColorProfilesEnabled() && hasColorProfile())
306 WebCoreClampingModeToSkiaRectConstraint(clampMode)); 305 transform = imageColorTransform();
306
307 if (!transform) {
308 canvas->drawImageRect(skImage.get(), adjustedSrcRect, adjustedDstRect, & paint, srcRectConstraint);
309
310 canvas->restoreToCount(initialSaveCount);
311 if (skImage->isLazyGenerated())
312 PlatformInstrumentation::didDrawLazyPixelRef(skImage->uniqueID());
313 this->didDraw();
314 return;
315 }
316
317 float srcArea = adjustedSrcRect.width() * adjustedSrcRect.height();
318 float dstArea = adjustedDstRect.width() * adjustedDstRect.height();
319
320 if (dstArea <= srcArea) {
321 SkPaint transformPaint = paint;
322 transformPaint.setColorFilter(transform.get());
323 canvas->drawImageRect(skImage.get(), adjustedSrcRect, adjustedDstRect, & transformPaint, srcRectConstraint);
324
325 canvas->restoreToCount(initialSaveCount);
326 if (skImage->isLazyGenerated())
327 PlatformInstrumentation::didDrawLazyPixelRef(skImage->uniqueID());
328 this->didDraw();
329 return;
330 }
331
332 RefPtr<SkImage> image = skImage; // skImage might be indirectly drawn here ( due to transforms).
333
334 if (RefPtr<SkImageFilter> imageFilter = adoptRef(SkColorFilterImageFilter::C reate(transform.get())))
335 image = adoptRef(image->applyFilter(imageFilter.get(), nullptr, true));
336
337 canvas->drawImageRect(image.get(), adjustedSrcRect, adjustedDstRect, &paint, srcRectConstraint);
338
307 canvas->restoreToCount(initialSaveCount); 339 canvas->restoreToCount(initialSaveCount);
340 if (skImage->isLazyGenerated())
341 PlatformInstrumentation::didDrawLazyPixelRef(skImage->uniqueID());
342 this->didDraw();
343 return;
344 }
308 345
309 if (currentFrameIsLazyDecoded()) 346 void BitmapImage::didDraw()
310 PlatformInstrumentation::didDrawLazyPixelRef(image->uniqueID()); 347 {
311
312 if (ImageObserver* observer = imageObserver()) 348 if (ImageObserver* observer = imageObserver())
313 observer->didDraw(this); 349 observer->didDraw(this);
314 350
315 startAnimation(); 351 startAnimation();
316 } 352 }
317 353
318 size_t BitmapImage::frameCount() 354 size_t BitmapImage::frameCount()
319 { 355 {
320 if (!m_haveFrameCount) { 356 if (!m_haveFrameCount) {
321 m_frameCount = m_source.frameCount(); 357 m_frameCount = m_source.frameCount();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 { 427 {
392 if (frameCount() > 1) { 428 if (frameCount() > 1) {
393 RefPtr<SkImage> firstFrame = frameAtIndex(0); 429 RefPtr<SkImage> firstFrame = frameAtIndex(0);
394 if (firstFrame) 430 if (firstFrame)
395 return StaticBitmapImage::create(firstFrame); 431 return StaticBitmapImage::create(firstFrame);
396 } 432 }
397 433
398 return Image::imageForDefaultFrame(); 434 return Image::imageForDefaultFrame();
399 } 435 }
400 436
437 PassRefPtr<SkColorFilter> BitmapImage::imageColorTransform()
438 {
439 if (currentScreenId()) // FIXME: remove these <canvas> code asserts.
440 RELEASE_ASSERT(!drawingToCanvasElement());
441 else
442 RELEASE_ASSERT(drawingToCanvasElement()); // sRGB render target.
443
444 return createColorSpaceFilter(colorProfile().get(), screenColorProfile(curre ntScreenId()).get());
445 }
446
401 bool BitmapImage::frameHasAlphaAtIndex(size_t index) 447 bool BitmapImage::frameHasAlphaAtIndex(size_t index)
402 { 448 {
403 if (m_frames.size() <= index) 449 if (m_frames.size() <= index)
404 return true; 450 return true;
405 451
406 if (m_frames[index].m_haveMetadata) 452 if (m_frames[index].m_haveMetadata)
407 return m_frames[index].m_hasAlpha; 453 return m_frames[index].m_hasAlpha;
408 454
409 return m_source.frameHasAlphaAtIndex(index); 455 return m_source.frameHasAlphaAtIndex(index);
410 } 456 }
411 457
412 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode) 458 bool BitmapImage::currentFrameKnownToBeOpaque(MetadataMode metadataMode)
413 { 459 {
414 if (metadataMode == PreCacheMetadata) { 460 if (metadataMode == PreCacheMetadata) {
415 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the 461 // frameHasAlphaAtIndex() conservatively returns false for uncached fram es. To increase the
416 // chance of an accurate answer, pre-cache the current frame metadata. 462 // chance of an accurate answer, pre-cache the current frame metadata.
417 frameAtIndex(currentFrame()); 463 frameAtIndex(currentFrame());
418 } 464 }
465
419 return !frameHasAlphaAtIndex(currentFrame()); 466 return !frameHasAlphaAtIndex(currentFrame());
420 } 467 }
421 468
422 bool BitmapImage::currentFrameIsComplete() 469 bool BitmapImage::currentFrameIsComplete()
423 { 470 {
424 return frameIsCompleteAtIndex(currentFrame()); 471 return frameIsCompleteAtIndex(currentFrame());
425 } 472 }
426 473
427 bool BitmapImage::currentFrameIsLazyDecoded() 474 bool BitmapImage::currentFrameIsLazyDecoded()
428 { 475 {
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 destroyDecodedDataIfNecessary(); 689 destroyDecodedDataIfNecessary();
643 690
644 // We need to draw this frame if we advanced to it while not skipping, or if 691 // We need to draw this frame if we advanced to it while not skipping, or if
645 // while trying to skip frames we hit the last frame and thus had to stop. 692 // while trying to skip frames we hit the last frame and thus had to stop.
646 if (skippingFrames != advancedAnimation) 693 if (skippingFrames != advancedAnimation)
647 imageObserver()->animationAdvanced(this); 694 imageObserver()->animationAdvanced(this);
648 return advancedAnimation; 695 return advancedAnimation;
649 } 696 }
650 697
651 } // namespace blink 698 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698