1/*
2 * Copyright (C) 2016-2017 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#pragma once
27
28#include "ImageFrame.h"
29
30#include <wtf/Forward.h>
31#include <wtf/Optional.h>
32#include <wtf/SynchronizedFixedQueue.h>
33#include <wtf/WeakPtr.h>
34#include <wtf/WorkQueue.h>
35#include <wtf/text/TextStream.h>
36
37namespace WebCore {
38
39class BitmapImage;
40class GraphicsContext;
41class ImageDecoder;
42
43class ImageSource : public ThreadSafeRefCounted<ImageSource>, public CanMakeWeakPtr<ImageSource> {
44 friend class BitmapImage;
45public:
46 ~ImageSource();
47
48 static Ref<ImageSource> create(BitmapImage* image, AlphaOption alphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption gammaAndColorProfileOption = GammaAndColorProfileOption::Applied)
49 {
50 return adoptRef(*new ImageSource(image, alphaOption, gammaAndColorProfileOption));
51 }
52
53 static Ref<ImageSource> create(NativeImagePtr&& nativeImage)
54 {
55 return adoptRef(*new ImageSource(WTFMove(nativeImage)));
56 }
57
58 void setData(SharedBuffer* data, bool allDataReceived);
59 void resetData(SharedBuffer* data);
60 EncodedDataStatus dataChanged(SharedBuffer* data, bool allDataReceived);
61 bool isAllDataReceived();
62
63 unsigned decodedSize() const { return m_decodedSize; }
64 void destroyAllDecodedData() { destroyDecodedData(frameCount(), frameCount()); }
65 void destroyAllDecodedDataExcludeFrame(size_t excludeFrame) { destroyDecodedData(frameCount(), excludeFrame); }
66 void destroyDecodedDataBeforeFrame(size_t beforeFrame) { destroyDecodedData(beforeFrame, beforeFrame); }
67 void destroyIncompleteDecodedData();
68 void clearFrameBufferCache(size_t beforeFrame);
69
70 void growFrames();
71 void clearMetadata();
72 void clearImage() { m_image = nullptr; }
73 URL sourceURL() const;
74 String mimeType() const;
75 long long expectedContentLength() const;
76
77 // Asynchronous image decoding
78 bool canUseAsyncDecoding();
79 void startAsyncDecodingQueue();
80 void requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const Optional<IntSize>& = { });
81 void stopAsyncDecodingQueue();
82 bool hasAsyncDecodingQueue() const { return m_decodingQueue; }
83 bool isAsyncDecodingQueueIdle() const;
84 void setFrameDecodingDurationForTesting(Seconds duration) { m_frameDecodingDurationForTesting = duration; }
85 Seconds frameDecodingDurationForTesting() const { return m_frameDecodingDurationForTesting; }
86
87 // Image metadata which is calculated either by the ImageDecoder or directly
88 // from the NativeImage if this class was created for a memory image.
89 EncodedDataStatus encodedDataStatus();
90 bool isSizeAvailable() { return encodedDataStatus() >= EncodedDataStatus::SizeAvailable; }
91 WEBCORE_EXPORT size_t frameCount();
92 RepetitionCount repetitionCount();
93 String uti();
94 String filenameExtension();
95 Optional<IntPoint> hotSpot();
96
97 // Image metadata which is calculated from the first ImageFrame.
98 WEBCORE_EXPORT IntSize size();
99 IntSize sizeRespectingOrientation();
100 Color singlePixelSolidColor();
101 SubsamplingLevel maximumSubsamplingLevel();
102
103 // ImageFrame metadata which does not require caching the ImageFrame.
104 bool frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t, const DecodingOptions&);
105 DecodingStatus frameDecodingStatusAtIndex(size_t);
106 bool frameHasAlphaAtIndex(size_t);
107 bool frameHasImageAtIndex(size_t);
108 bool frameHasFullSizeNativeImageAtIndex(size_t, const Optional<SubsamplingLevel>&);
109 bool frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t, const Optional<SubsamplingLevel>&, const DecodingOptions&);
110 SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
111
112 // ImageFrame metadata which forces caching or re-caching the ImageFrame.
113 IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
114 unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
115 WEBCORE_EXPORT Seconds frameDurationAtIndex(size_t);
116 ImageOrientation frameOrientationAtIndex(size_t);
117
118#if USE(DIRECT2D)
119 void setTargetContext(const GraphicsContext*);
120#endif
121 NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
122 NativeImagePtr frameImageAtIndex(size_t);
123 NativeImagePtr frameImageAtIndexCacheIfNeeded(size_t, SubsamplingLevel = SubsamplingLevel::Default);
124
125private:
126 ImageSource(BitmapImage*, AlphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption = GammaAndColorProfileOption::Applied);
127 ImageSource(NativeImagePtr&&);
128
129 template<typename T, T (ImageDecoder::*functor)() const>
130 T metadata(const T& defaultValue, Optional<T>* cachedValue = nullptr);
131
132 template<typename T, typename... Args>
133 T frameMetadataAtIndex(size_t, T (ImageFrame::*functor)(Args...) const, Args&&...);
134
135 template<typename T, typename... Args>
136 T frameMetadataAtIndexCacheIfNeeded(size_t, T (ImageFrame::*functor)() const, Optional<T>* cachedValue, Args&&...);
137
138 bool ensureDecoderAvailable(SharedBuffer* data);
139 bool isDecoderAvailable() const { return m_decoder; }
140 void destroyDecodedData(size_t frameCount, size_t excludeFrame);
141 void decodedSizeChanged(long long decodedSize);
142 void didDecodeProperties(unsigned decodedPropertiesSize);
143 void decodedSizeIncreased(unsigned decodedSize);
144 void decodedSizeDecreased(unsigned decodedSize);
145 void decodedSizeReset(unsigned decodedSize);
146 void encodedDataStatusChanged(EncodedDataStatus);
147
148 void setNativeImage(NativeImagePtr&&);
149 void cacheMetadataAtIndex(size_t, SubsamplingLevel, DecodingStatus = DecodingStatus::Invalid);
150 void cacheNativeImageAtIndex(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus = DecodingStatus::Invalid);
151 void cacheNativeImageAtIndexAsync(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus);
152
153 struct ImageFrameRequest;
154 static const int BufferSize = 8;
155 WorkQueue& decodingQueue();
156 SynchronizedFixedQueue<ImageFrameRequest, BufferSize>& frameRequestQueue();
157
158 const ImageFrame& frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const Optional<SubsamplingLevel>& = { });
159
160 void dump(TextStream&);
161
162 BitmapImage* m_image { nullptr };
163 RefPtr<ImageDecoder> m_decoder;
164 AlphaOption m_alphaOption { AlphaOption::Premultiplied };
165 GammaAndColorProfileOption m_gammaAndColorProfileOption { GammaAndColorProfileOption::Applied };
166
167 unsigned m_decodedSize { 0 };
168 unsigned m_decodedPropertiesSize { 0 };
169 Vector<ImageFrame, 1> m_frames;
170
171 // Asynchronous image decoding.
172 struct ImageFrameRequest {
173 size_t index;
174 SubsamplingLevel subsamplingLevel;
175 DecodingOptions decodingOptions;
176 DecodingStatus decodingStatus;
177 bool operator==(const ImageFrameRequest& other) const
178 {
179 return index == other.index && subsamplingLevel == other.subsamplingLevel && decodingOptions == other.decodingOptions && decodingStatus == other.decodingStatus;
180 }
181 };
182 using FrameRequestQueue = SynchronizedFixedQueue<ImageFrameRequest, BufferSize>;
183 using FrameCommitQueue = Deque<ImageFrameRequest, BufferSize>;
184 RefPtr<FrameRequestQueue> m_frameRequestQueue;
185 FrameCommitQueue m_frameCommitQueue;
186 RefPtr<WorkQueue> m_decodingQueue;
187 Seconds m_frameDecodingDurationForTesting;
188
189 // Image metadata.
190 Optional<EncodedDataStatus> m_encodedDataStatus;
191 Optional<size_t> m_frameCount;
192 Optional<RepetitionCount> m_repetitionCount;
193 Optional<String> m_uti;
194 Optional<String> m_filenameExtension;
195 Optional<Optional<IntPoint>> m_hotSpot;
196
197 // Image metadata which is calculated from the first ImageFrame.
198 Optional<IntSize> m_size;
199 Optional<IntSize> m_sizeRespectingOrientation;
200 Optional<Color> m_singlePixelSolidColor;
201 Optional<SubsamplingLevel> m_maximumSubsamplingLevel;
202};
203
204}
205