fbfd601a30565c31262fff9887e85c95705be5d6
[WebKit-https.git] / Source / WebCore / platform / graphics / ImageFrameCache.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ImageFrameCache.h"
28
29 #include "Image.h"
30 #include "ImageObserver.h"
31
32 #if USE(CG)
33 #include "ImageDecoderCG.h"
34 #else
35 #include "ImageDecoder.h"
36 #endif
37
38 #include <wtf/CheckedArithmetic.h>
39
40
41 namespace WebCore {
42
43 ImageFrameCache::ImageFrameCache(Image* image)
44     : m_image(image)
45 {
46 }
47
48 ImageFrameCache::ImageFrameCache(NativeImagePtr&& nativeImage)
49 {
50     m_frameCount = 1;
51     m_isSizeAvailable = true;
52     growFrames();
53
54     setNativeImage(WTFMove(nativeImage));
55
56     m_decodedSize = m_frames[0].frameBytes();
57
58     // The assumption is the memory image will be displayed with the default
59     // orientation. So set m_sizeRespectingOrientation to be the same as m_size.
60     m_size = m_frames[0].size();
61     m_sizeRespectingOrientation = m_size;
62 }
63
64 void ImageFrameCache::destroyDecodedData(bool destroyAll, size_t count)
65 {
66     if (destroyAll)
67         count = m_frames.size();
68     
69     unsigned decodedSize = 0;
70     for (size_t i = 0; i <  count; ++i)
71         decodedSize += m_frames[i].clearImage();
72
73     decodedSizeReset(decodedSize);
74 }
75
76 bool ImageFrameCache::destroyDecodedDataIfNecessary(bool destroyAll, size_t count)
77 {
78     unsigned decodedSize = 0;
79     for (auto& frame : m_frames)
80         decodedSize += frame.frameBytes();
81     
82     if (decodedSize < LargeAnimationCutoff)
83         return false;
84     
85     destroyDecodedData(destroyAll, count);
86     return true;
87 }
88
89 void ImageFrameCache::destroyIncompleteDecodedData()
90 {
91     unsigned decodedSize = 0;
92     
93     for (auto& frame : m_frames) {
94         if (!frame.hasMetadata() || frame.isComplete())
95             continue;
96         
97         decodedSize += frame.clear();
98     }
99
100     decodedSizeDecreased(decodedSize);
101 }
102
103 void ImageFrameCache::decodedSizeChanged(long long decodedSize)
104 {
105     if (!decodedSize || !m_image || !m_image->imageObserver())
106         return;
107     
108     m_image->imageObserver()->decodedSizeChanged(m_image, decodedSize);
109 }
110
111 void ImageFrameCache::decodedSizeIncreased(unsigned decodedSize)
112 {
113     if (!decodedSize)
114         return;
115     
116     m_decodedSize += decodedSize;
117     
118     // The fully-decoded frame will subsume the partially decoded data used
119     // to determine image properties.
120     long long changeSize = static_cast<long long>(decodedSize) - m_decodedPropertiesSize;
121     m_decodedPropertiesSize = 0;
122     decodedSizeChanged(changeSize);
123 }
124
125 void ImageFrameCache::decodedSizeDecreased(unsigned decodedSize)
126 {
127     if (!decodedSize)
128         return;
129
130     ASSERT(m_decodedSize >= decodedSize);
131     m_decodedSize -= decodedSize;
132     decodedSizeChanged(-static_cast<long long>(decodedSize));
133 }
134
135 void ImageFrameCache::decodedSizeReset(unsigned decodedSize)
136 {
137     ASSERT(m_decodedSize >= decodedSize);
138     m_decodedSize -= decodedSize;
139
140     // Clearing the ImageSource destroys the extra decoded data used for
141     // determining image properties.
142     decodedSize += m_decodedPropertiesSize;
143     m_decodedPropertiesSize = 0;
144     decodedSizeChanged(-static_cast<long long>(decodedSize));
145 }
146
147 void ImageFrameCache::didDecodeProperties(unsigned decodedPropertiesSize)
148 {
149     if (m_decodedSize)
150         return;
151
152     long long decodedSize = static_cast<long long>(decodedPropertiesSize) - m_decodedPropertiesSize;
153     m_decodedPropertiesSize = decodedPropertiesSize;
154     decodedSizeChanged(decodedSize);
155 }
156
157 void ImageFrameCache::growFrames()
158 {
159     ASSERT(isSizeAvailable());
160     ASSERT(m_frames.size() <= frameCount());
161     m_frames.grow(frameCount());
162 }
163
164 void ImageFrameCache::setNativeImage(NativeImagePtr&& nativeImage)
165 {
166     ASSERT(m_frames.size() == 1);
167     ImageFrame& frame = m_frames[0];
168
169     ASSERT(!isDecoderAvailable());
170
171     frame.m_nativeImage = WTFMove(nativeImage);
172
173     frame.m_decoding = ImageFrame::Decoding::Complete;
174     frame.m_size = nativeImageSize(frame.m_nativeImage);
175     frame.m_hasAlpha = nativeImageHasAlpha(frame.m_nativeImage);
176 }
177
178 void ImageFrameCache::setFrameNativeImage(NativeImagePtr&& nativeImage, size_t index, SubsamplingLevel subsamplingLevel)
179 {
180     ASSERT(index < m_frames.size());
181     ImageFrame& frame = m_frames[index];
182
183     ASSERT(isDecoderAvailable());
184
185     frame.m_nativeImage = WTFMove(nativeImage);
186     setFrameMetadata(index, subsamplingLevel);
187 }
188
189 void ImageFrameCache::setFrameMetadata(size_t index, SubsamplingLevel subsamplingLevel)
190 {
191     ASSERT(index < m_frames.size());
192     ImageFrame& frame = m_frames[index];
193
194     ASSERT(isDecoderAvailable());
195     frame.m_decoding = m_decoder->frameIsCompleteAtIndex(index) ? ImageFrame::Decoding::Complete : ImageFrame::Decoding::Partial;
196     if (frame.hasMetadata())
197         return;
198     
199     frame.m_subsamplingLevel = subsamplingLevel;
200     frame.m_size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
201     frame.m_orientation = m_decoder->frameOrientationAtIndex(index);
202     frame.m_hasAlpha = m_decoder->frameHasAlphaAtIndex(index);
203     
204     if (repetitionCount())
205         frame.m_duration = m_decoder->frameDurationAtIndex(index);
206 }
207
208 const ImageFrame& ImageFrameCache::frameAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching)
209 {
210     ASSERT(index < m_frames.size());
211     ImageFrame& frame = m_frames[index];
212     if (!isDecoderAvailable() || caching == ImageFrame::Caching::Empty)
213         return frame;
214     
215     if (subsamplingLevel == SubsamplingLevel::Undefinded)
216         subsamplingLevel = frame.subsamplingLevel();
217     
218     if (frame.hasInvalidNativeImage(subsamplingLevel)) {
219         unsigned decodedSize = frame.clear();
220         decodedSizeDecreased(decodedSize);
221     }
222     
223     if (!frame.isComplete() && caching == ImageFrame::Caching::Metadata)
224         setFrameMetadata(index, subsamplingLevel);
225     
226     if (!frame.hasNativeImage() && caching == ImageFrame::Caching::MetadataAndImage) {
227         size_t frameBytes = size().unclampedArea() * sizeof(RGBA32);
228
229         // Do not create the NativeImage if adding its frameByes to the MemoryCache will cause numerical overflow.
230         if (WTF::isInBounds<unsigned>(frameBytes + decodedSize())) {
231             setFrameNativeImage(m_decoder->createFrameImageAtIndex(index, subsamplingLevel), index, subsamplingLevel);
232             decodedSizeIncreased(frame.frameBytes());
233         }
234     }
235     
236     return frame;
237 }
238
239 void ImageFrameCache::clearMetadata()
240 {
241     m_frameCount = Nullopt;
242     m_singlePixelSolidColor = Nullopt;
243     m_maximumSubsamplingLevel = Nullopt;
244 }
245
246 template<typename T, T (ImageDecoder::*functor)() const>
247 T ImageFrameCache::metadata(const T& defaultValue, Optional<T>* cachedValue)
248 {
249     if (cachedValue && *cachedValue)
250         return cachedValue->value();
251
252     if (!isDecoderAvailable() || !m_decoder->isSizeAvailable())
253         return defaultValue;
254
255     if (!cachedValue)
256         return (m_decoder->*functor)();
257
258     *cachedValue = (m_decoder->*functor)();
259     didDecodeProperties(m_decoder->bytesDecodedToDetermineProperties());
260     return cachedValue->value();
261 }
262
263 template<typename T, T (ImageFrame::*functor)() const>
264 T ImageFrameCache::frameMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching, Optional<T>* cachedValue)
265 {
266     if (cachedValue && *cachedValue)
267         return cachedValue->value();
268     
269     const ImageFrame& frame = index < m_frames.size() ? frameAtIndex(index, subsamplingLevel, caching) : ImageFrame::defaultFrame();
270
271     // Don't cache any unavailable frame metadata.
272     if (!frame.hasMetadata() || !cachedValue)
273         return (frame.*functor)();
274     
275     *cachedValue = (frame.*functor)();
276     return cachedValue->value();
277 }
278
279 bool ImageFrameCache::isSizeAvailable()
280 {
281     if (m_isSizeAvailable)
282         return m_isSizeAvailable.value();
283     
284     if (!isDecoderAvailable() || !m_decoder->isSizeAvailable())
285         return false;
286     
287     m_isSizeAvailable = true;
288     didDecodeProperties(m_decoder->bytesDecodedToDetermineProperties());
289     return true;
290 }
291
292 size_t ImageFrameCache::frameCount()
293 {
294     return metadata<size_t, (&ImageDecoder::frameCount)>(m_frames.size(), &m_frameCount);
295 }
296
297 RepetitionCount ImageFrameCache::repetitionCount()
298 {
299     return metadata<RepetitionCount, (&ImageDecoder::repetitionCount)>(RepetitionCountNone, &m_repetitionCount);
300 }
301
302 String ImageFrameCache::filenameExtension()
303 {
304     return metadata<String, (&ImageDecoder::filenameExtension)>(String(), &m_filenameExtension);
305 }
306
307 Optional<IntPoint> ImageFrameCache::hotSpot()
308 {
309     return metadata<Optional<IntPoint>, (&ImageDecoder::hotSpot)>(Nullopt, &m_hotSpot);
310 }
311
312 IntSize ImageFrameCache::size()
313 {
314     return frameMetadataAtIndex<IntSize, (&ImageFrame::size)>(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &m_size);
315 }
316
317 IntSize ImageFrameCache::sizeRespectingOrientation()
318 {
319     return frameMetadataAtIndex<IntSize, (&ImageFrame::sizeRespectingOrientation)>(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &m_sizeRespectingOrientation);
320 }
321
322 Color ImageFrameCache::singlePixelSolidColor()
323 {
324     return frameCount() == 1 ? frameMetadataAtIndex<Color, (&ImageFrame::singlePixelSolidColor)>(0, SubsamplingLevel::Undefinded, ImageFrame::Caching::MetadataAndImage, &m_singlePixelSolidColor) : Color();
325 }
326
327 bool ImageFrameCache::frameIsCompleteAtIndex(size_t index)
328 {
329     return frameMetadataAtIndex<bool, (&ImageFrame::isComplete)>(index);
330 }
331
332 bool ImageFrameCache::frameHasAlphaAtIndex(size_t index)
333 {
334     return frameMetadataAtIndex<bool, (&ImageFrame::hasAlpha)>(index);
335 }
336
337 bool ImageFrameCache::frameHasImageAtIndex(size_t index)
338 {
339     return frameMetadataAtIndex<bool, (&ImageFrame::hasNativeImage)>(index);
340 }
341
342 bool ImageFrameCache::frameHasInvalidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
343 {
344     return frameHasImageAtIndex(index) && subsamplingLevel < frameSubsamplingLevelAtIndex(index);
345 }
346
347 SubsamplingLevel ImageFrameCache::frameSubsamplingLevelAtIndex(size_t index)
348 {
349     return frameMetadataAtIndex<SubsamplingLevel, (&ImageFrame::subsamplingLevel)>(index);
350 }
351
352 IntSize ImageFrameCache::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
353 {
354     return frameMetadataAtIndex<IntSize, (&ImageFrame::size)>(index, subsamplingLevel, ImageFrame::Caching::Metadata);
355 }
356
357 unsigned ImageFrameCache::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
358 {
359     return frameMetadataAtIndex<unsigned, (&ImageFrame::frameBytes)>(index, subsamplingLevel, ImageFrame::Caching::Metadata);
360 }
361
362 float ImageFrameCache::frameDurationAtIndex(size_t index)
363 {
364     return frameMetadataAtIndex<float, (&ImageFrame::duration)>(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
365 }
366
367 ImageOrientation ImageFrameCache::frameOrientationAtIndex(size_t index)
368 {
369     return frameMetadataAtIndex<ImageOrientation, (&ImageFrame::orientation)>(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
370 }
371
372 NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
373 {
374     return frameMetadataAtIndex<NativeImagePtr, (&ImageFrame::nativeImage)>(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
375 }
376
377 }