228031b7f92f267d6f2a1a685af0c27b934d0bdc
[WebKit-https.git] / Source / WebCore / platform / graphics / BitmapImage.cpp
1 /*
2  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
3  * Copyright (C) 2004, 2005, 2006, 2008, 2015 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
25  */
26
27 #include "config.h"
28 #include "BitmapImage.h"
29
30 #include "FloatRect.h"
31 #include "GraphicsContext.h"
32 #include "ImageBuffer.h"
33 #include "ImageObserver.h"
34 #include "IntRect.h"
35 #include "Logging.h"
36 #include "Settings.h"
37 #include "TextStream.h"
38 #include "Timer.h"
39 #include <wtf/CurrentTime.h>
40 #include <wtf/Vector.h>
41 #include <wtf/text/WTFString.h>
42
43 #if PLATFORM(IOS)
44 #include <limits>
45 #endif
46
47 namespace WebCore {
48
49 BitmapImage::BitmapImage(ImageObserver* observer)
50     : Image(observer)
51     , m_source(this)
52 {
53 }
54
55 BitmapImage::BitmapImage(NativeImagePtr&& image, ImageObserver* observer)
56     : Image(observer)
57     , m_source(WTFMove(image))
58 {
59 }
60
61 BitmapImage::~BitmapImage()
62 {
63     invalidatePlatformData();
64     clearTimer();
65     m_source.stopAsyncDecodingQueue();
66 }
67
68 void BitmapImage::updateFromSettings(const Settings& settings)
69 {
70     m_allowSubsampling = settings.imageSubsamplingEnabled();
71     m_allowLargeImageAsyncDecoding = settings.largeImageAsyncDecodingEnabled();
72     m_allowAnimatedImageAsyncDecoding = settings.animatedImageAsyncDecodingEnabled();
73     m_showDebugBackground = settings.showDebugBorders();
74 }
75
76 void BitmapImage::destroyDecodedData(bool destroyAll)
77 {
78     LOG(Images, "BitmapImage::%s - %p - url: %s", __FUNCTION__, this, sourceURL().string().utf8().data());
79
80     if (!destroyAll)
81         m_source.destroyDecodedDataBeforeFrame(m_currentFrame);
82     else if (m_source.hasAsyncDecodingQueue())
83         m_source.destroyAllDecodedDataExcludeFrame(m_currentFrame);
84     else
85         m_source.destroyAllDecodedData();
86
87     // There's no need to throw away the decoder unless we're explicitly asked
88     // to destroy all of the frames.
89     if (!destroyAll || m_source.hasAsyncDecodingQueue())
90         m_source.clearFrameBufferCache(m_currentFrame);
91     else
92         m_source.clear(data());
93
94     invalidatePlatformData();
95 }
96
97 void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
98 {
99     // If we have decoded frames but there is no encoded data, we shouldn't destroy
100     // the decoded image since we won't be able to reconstruct it later.
101     if (!data() && frameCount())
102         return;
103
104     if (m_source.decodedSize() < LargeAnimationCutoff)
105         return;
106
107     destroyDecodedData(destroyAll);
108 }
109
110 EncodedDataStatus BitmapImage::dataChanged(bool allDataReceived)
111 {
112     return m_source.dataChanged(data(), allDataReceived);
113 }
114
115 NativeImagePtr BitmapImage::frameImageAtIndexCacheIfNeeded(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
116 {
117     if (!frameHasFullSizeNativeImageAtIndex(index, subsamplingLevel)) {
118         LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel was %d, resampling]", __FUNCTION__, this, sourceURL().string().utf8().data(), static_cast<int>(frameSubsamplingLevelAtIndex(index)));
119         invalidatePlatformData();
120     }
121
122     return m_source.frameImageAtIndexCacheIfNeeded(index, subsamplingLevel, targetContext);
123 }
124
125 NativeImagePtr BitmapImage::nativeImage(const GraphicsContext* targetContext)
126 {
127     return frameImageAtIndexCacheIfNeeded(0, SubsamplingLevel::Default, targetContext);
128 }
129
130 NativeImagePtr BitmapImage::nativeImageForCurrentFrame(const GraphicsContext* targetContext)
131 {
132     return frameImageAtIndexCacheIfNeeded(m_currentFrame, SubsamplingLevel::Default, targetContext);
133 }
134
135 #if USE(CG)
136 NativeImagePtr BitmapImage::nativeImageOfSize(const IntSize& size, const GraphicsContext* targetContext)
137 {
138     size_t count = frameCount();
139
140     for (size_t i = 0; i < count; ++i) {
141         auto image = frameImageAtIndexCacheIfNeeded(i, SubsamplingLevel::Default, targetContext);
142         if (image && nativeImageSize(image) == size)
143             return image;
144     }
145
146     // Fallback to the first frame image if we can't find the right size
147     return frameImageAtIndexCacheIfNeeded(0, SubsamplingLevel::Default, targetContext);
148 }
149
150 Vector<NativeImagePtr> BitmapImage::framesNativeImages()
151 {
152     Vector<NativeImagePtr> images;
153     size_t count = frameCount();
154
155     for (size_t i = 0; i < count; ++i) {
156         if (auto image = frameImageAtIndexCacheIfNeeded(i))
157             images.append(image);
158     }
159
160     return images;
161 }
162 #endif
163
164 #if !ASSERT_DISABLED
165 bool BitmapImage::notSolidColor()
166 {
167     return size().width() != 1 || size().height() != 1 || frameCount() > 1;
168 }
169 #endif
170
171 void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode mode, DecodingMode decodingMode, ImageOrientationDescription description)
172 {
173     if (destRect.isEmpty() || srcRect.isEmpty())
174         return;
175
176     FloatSize scaleFactorForDrawing = context.scaleFactorForDrawing(destRect, srcRect);
177     IntSize sizeForDrawing = expandedIntSize(size() * scaleFactorForDrawing);
178     
179     m_currentSubsamplingLevel = m_allowSubsampling ? m_source.subsamplingLevelForScaleFactor(context, scaleFactorForDrawing) : SubsamplingLevel::Default;
180     LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scaleFactorForDrawing = (%.4f, %.4f)]", __FUNCTION__, this, sourceURL().string().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), scaleFactorForDrawing.width(), scaleFactorForDrawing.height());
181
182     NativeImagePtr image;
183     if (decodingMode == DecodingMode::Asynchronous && shouldUseAsyncDecodingForLargeImages()) {
184         ASSERT(!canAnimate() && !m_currentFrame);
185
186         bool frameIsCompatible = frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingOptions(sizeForDrawing));
187         bool frameIsBeingDecoded = frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingOptions(sizeForDrawing));
188         bool frameIsComplete = frameIsCompleteAtIndex(m_currentFrame);
189
190         // If the current frame is incomplete, a new request for decoding this frame has to be made even if
191         // it is currently being decoded. New data may have been received since the previous request was made.
192         if ((!frameIsCompatible && !frameIsBeingDecoded) || !frameIsComplete) {
193             LOG(Images, "BitmapImage::%s - %p - url: %s [requesting large async decoding]", __FUNCTION__, this, sourceURL().string().utf8().data());
194             frameIsBeingDecoded = m_source.requestFrameAsyncDecodingAtIndex(0, m_currentSubsamplingLevel, sizeForDrawing);
195         }
196
197         if (!frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingMode::Asynchronous)) {
198             if (m_showDebugBackground)
199                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
200             return;
201         }
202
203         image = frameImageAtIndex(m_currentFrame);
204         ASSERT_IMPLIES(encodedDataStatus() == EncodedDataStatus::Complete, frameIsBeingDecoded || frameIsComplete);
205         LOG(Images, "BitmapImage::%s - %p - url: %s [a decoded image frame is available for drawing]", __FUNCTION__, this, sourceURL().string().utf8().data());
206     } else {
207         StartAnimationStatus status = internalStartAnimation();
208         ASSERT_IMPLIES(status == StartAnimationStatus::DecodingActive, frameHasFullSizeNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel));
209
210         if (status == StartAnimationStatus::DecodingActive && m_showDebugBackground) {
211             fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
212             return;
213         }
214
215         if (frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingMode::Asynchronous)) {
216             // FIXME: instead of showing the yellow rectangle and returning we need to wait for this the frame to finish decoding.
217             if (m_showDebugBackground) {
218                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
219                 LOG(Images, "BitmapImage::%s - %p - url: %s [waiting for async decoding to finish]", __FUNCTION__, this, sourceURL().string().utf8().data());
220             }
221             return;
222         }
223
224         image = frameImageAtIndexCacheIfNeeded(m_currentFrame, m_currentSubsamplingLevel, &context);
225         if (!image) // If it's too early we won't have an image yet.
226             return;
227     }
228
229     ASSERT(image);
230     Color color = singlePixelSolidColor();
231     if (color.isValid()) {
232         fillWithSolidColor(context, destRect, color, op);
233         return;
234     }
235
236     ImageOrientation orientation(description.imageOrientation());
237     if (description.respectImageOrientation() == RespectImageOrientation)
238         orientation = frameOrientationAtIndex(m_currentFrame);
239
240     drawNativeImage(image, context, destRect, srcRect, IntSize(size()), op, mode, orientation);
241
242     if (imageObserver())
243         imageObserver()->didDraw(this);
244 }
245
246 void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
247 {
248     if (tileRect.isEmpty())
249         return;
250
251     if (!ctxt.drawLuminanceMask()) {
252         Image::drawPattern(ctxt, destRect, tileRect, transform, phase, spacing, op, blendMode);
253         return;
254     }
255
256     if (!m_cachedImage) {
257         auto buffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(tileRect.size()), ColorSpaceSRGB, ctxt);
258         if (!buffer)
259             return;
260
261         ImageObserver* observer = imageObserver();
262
263         // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout.
264         setImageObserver(nullptr);
265
266         draw(buffer->context(), tileRect, tileRect, op, blendMode, DecodingMode::Synchronous, ImageOrientationDescription());
267
268         setImageObserver(observer);
269         buffer->convertToLuminanceMask();
270
271         m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled);
272         if (!m_cachedImage)
273             return;
274     }
275
276     ctxt.setDrawLuminanceMask(false);
277     m_cachedImage->drawPattern(ctxt, destRect, tileRect, transform, phase, spacing, op, blendMode);
278 }
279
280 bool BitmapImage::shouldAnimate()
281 {
282     return repetitionCount() && !m_animationFinished && imageObserver();
283 }
284
285 bool BitmapImage::canAnimate()
286 {
287     return shouldAnimate() && frameCount() > 1;
288 }
289
290 bool BitmapImage::shouldUseAsyncDecodingForLargeImages()
291 {
292     return !canAnimate() && m_allowLargeImageAsyncDecoding && m_source.shouldUseAsyncDecoding();
293 }
294
295 bool BitmapImage::shouldUseAsyncDecodingForAnimatedImages()
296 {
297     return canAnimate() && m_allowAnimatedImageAsyncDecoding && (shouldUseAsyncDecodingForAnimatedImagesForTesting() || m_source.shouldUseAsyncDecoding());
298 }
299
300 void BitmapImage::clearTimer()
301 {
302     m_frameTimer = nullptr;
303 }
304
305 void BitmapImage::startTimer(Seconds delay)
306 {
307     ASSERT(!m_frameTimer);
308     m_frameTimer = std::make_unique<Timer>(*this, &BitmapImage::advanceAnimation);
309     m_frameTimer->startOneShot(delay);
310 }
311
312 BitmapImage::StartAnimationStatus BitmapImage::internalStartAnimation()
313 {
314     if (!canAnimate())
315         return StartAnimationStatus::CannotStart;
316
317     if (m_frameTimer)
318         return StartAnimationStatus::TimerActive;
319
320     // Don't start a new animation until we draw the frame that is currently being decoded.
321     size_t nextFrame = (m_currentFrame + 1) % frameCount();
322     if (frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(nextFrame, DecodingMode::Asynchronous)) {
323         LOG(Images, "BitmapImage::%s - %p - url: %s [nextFrame = %ld is being decoded]", __FUNCTION__, this, sourceURL().string().utf8().data(), nextFrame);
324         return StartAnimationStatus::DecodingActive;
325     }
326
327     if (m_currentFrame >= frameCount() - 1) {
328         // Don't advance past the last frame if we haven't decoded the whole image
329         // yet and our repetition count is potentially unset. The repetition count
330         // in a GIF can potentially come after all the rest of the image data, so
331         // wait on it.
332         if (!m_source.isAllDataReceived() && repetitionCount() == RepetitionCountOnce)
333             return StartAnimationStatus::IncompleteData;
334
335         ++m_repetitionsComplete;
336
337         // Check for the end of animation.
338         if (repetitionCount() != RepetitionCountInfinite && m_repetitionsComplete >= repetitionCount()) {
339             m_animationFinished = true;
340             destroyDecodedDataIfNecessary(false);
341             return StartAnimationStatus::CannotStart;
342         }
343
344         destroyDecodedDataIfNecessary(true);
345     }
346
347     // Don't advance the animation to an incomplete frame.
348     if (!m_source.isAllDataReceived() && !frameIsCompleteAtIndex(nextFrame))
349         return StartAnimationStatus::IncompleteData;
350
351     MonotonicTime time = MonotonicTime::now();
352
353     // Handle initial state.
354     if (!m_desiredFrameStartTime)
355         m_desiredFrameStartTime = time;
356
357     // Setting 'm_desiredFrameStartTime' to 'time' means we are late; otherwise we are early.
358     m_desiredFrameStartTime = std::max(time, m_desiredFrameStartTime + Seconds { frameDurationAtIndex(m_currentFrame) });
359
360     // Request async decoding for nextFrame only if this is required. If nextFrame is not in the frameCache,
361     // it will be decoded on a separate work queue. When decoding nextFrame finishes, we will be notified
362     // through the callback newFrameNativeImageAvailableAtIndex(). Otherwise, advanceAnimation() will be called
363     // when the timer fires and m_currentFrame will be advanced to nextFrame since it is not being decoded.
364     if (shouldUseAsyncDecodingForAnimatedImages()) {
365         bool isAsyncDecode = m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel);
366
367 #if !LOG_DISABLED
368         if (isAsyncDecode)
369             LOG(Images, "BitmapImage::%s - %p - url: %s [requesting async decoding for nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), nextFrame);
370         else
371             LOG(Images, "BitmapImage::%s - %p - url: %s [cachedFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_cachedFrameCount, nextFrame);
372 #else
373         UNUSED_PARAM(isAsyncDecode);
374 #endif
375
376         m_desiredFrameDecodeTimeForTesting = time + std::max(m_frameDecodingDurationForTesting, 0_s);
377         if (m_clearDecoderAfterAsyncFrameRequestForTesting)
378             m_source.clear(data());
379     }
380
381     ASSERT(!m_frameTimer);
382     startTimer(m_desiredFrameStartTime - time);
383     return StartAnimationStatus::Started;
384 }
385
386 void BitmapImage::advanceAnimation()
387 {
388     clearTimer();
389
390     // Pretend as if decoding nextFrame has taken m_frameDecodingDurationForTesting from
391     // the time this decoding was requested.
392     if (shouldUseAsyncDecodingForAnimatedImagesForTesting()) {
393         MonotonicTime time = MonotonicTime::now();
394         // Start a timer with the remaining time from now till the m_desiredFrameDecodeTime.
395         if (m_desiredFrameDecodeTimeForTesting > std::max(time, m_desiredFrameStartTime)) {
396             startTimer(m_desiredFrameDecodeTimeForTesting - time);
397             return;
398         }
399     }
400
401     // Don't advance to nextFrame unless its decoding has finished or was not required.
402     size_t nextFrame = (m_currentFrame + 1) % frameCount();
403     if (!frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(nextFrame, DecodingMode::Asynchronous))
404         internalAdvanceAnimation();
405     else {
406         // Force repaint if showDebugBackground() is on.
407         if (m_showDebugBackground)
408             imageObserver()->changedInRect(this);
409         LOG(Images, "BitmapImage::%s - %p - url: %s [lateFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_lateFrameCount, nextFrame);
410     }
411 }
412
413 void BitmapImage::internalAdvanceAnimation()
414 {
415     m_currentFrame = (m_currentFrame + 1) % frameCount();
416     ASSERT(!frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingMode::Asynchronous));
417
418     destroyDecodedDataIfNecessary(false);
419
420     if (imageObserver())
421         imageObserver()->imageFrameAvailable(this, ImageAnimatingState::Yes);
422
423     LOG(Images, "BitmapImage::%s - %p - url: %s [m_currentFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), m_currentFrame);
424 }
425
426 bool BitmapImage::isAnimating() const
427 {
428     return !!m_frameTimer;
429 }
430
431 void BitmapImage::stopAnimation()
432 {
433     // This timer is used to animate all occurrences of this image. Don't invalidate
434     // the timer unless all renderers have stopped drawing.
435     clearTimer();
436     if (canAnimate())
437         m_source.stopAsyncDecodingQueue();
438 }
439
440 void BitmapImage::resetAnimation()
441 {
442     stopAnimation();
443     m_currentFrame = 0;
444     m_repetitionsComplete = RepetitionCountNone;
445     m_desiredFrameStartTime = { };
446     m_animationFinished = false;
447
448     // For extremely large animations, when the animation is reset, we just throw everything away.
449     destroyDecodedDataIfNecessary(true);
450 }
451
452 void BitmapImage::imageFrameAvailableAtIndex(size_t index)
453 {
454     UNUSED_PARAM(index);
455     LOG(Images, "BitmapImage::%s - %p - url: %s [requested frame %ld is now available]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
456
457     if (canAnimate()) {
458         ASSERT(index == (m_currentFrame + 1) % frameCount());
459         
460         // Don't advance to nextFrame unless the timer was fired before its decoding finishes.
461         if (canAnimate() && !m_frameTimer)
462             internalAdvanceAnimation();
463         else
464             LOG(Images, "BitmapImage::%s - %p - url: %s [earlyFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_earlyFrameCount, index);
465     } else {
466         ASSERT(index == m_currentFrame && !m_currentFrame);
467         imageObserver()->imageFrameAvailable(this, ImageAnimatingState::No);
468         
469         if (m_source.isAsyncDecodingQueueIdle())
470             m_source.stopAsyncDecodingQueue();
471     }
472 }
473
474 void BitmapImage::dump(TextStream& ts) const
475 {
476     Image::dump(ts);
477     
478     if (isAnimated())
479         ts.dumpProperty("current-frame", m_currentFrame);
480     
481     m_source.dump(ts);
482 }
483
484 }