70478a2cb0fde270858f71a40e5d5839642f56ee
[WebKit.git] / Source / WebCore / platform / graphics / win / ImageDecoderDirect2D.cpp
1 /*
2  * Copyright (C) 2016-2018 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 "ImageDecoderDirect2D.h"
28
29 #if USE(DIRECT2D)
30
31 #include "GraphicsContext.h"
32 #include "ImageOrientation.h"
33 #include "IntPoint.h"
34 #include "IntSize.h"
35 #include "Logging.h"
36 #include "NotImplemented.h"
37 #include "SharedBuffer.h"
38 #include <WinCodec.h>
39 #include <d2d1.h>
40 #include <wtf/NeverDestroyed.h>
41
42 namespace WebCore {
43
44 ImageDecoderDirect2D::ImageDecoderDirect2D()
45 {
46 }
47
48 IWICImagingFactory* ImageDecoderDirect2D::systemImagingFactory()
49 {
50     static IWICImagingFactory* wicImagingFactory = nullptr;
51     if (!wicImagingFactory) {
52         HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&wicImagingFactory);
53         RELEASE_ASSERT(SUCCEEDED(hr));
54     }
55
56     return wicImagingFactory;
57 }
58
59 size_t ImageDecoderDirect2D::bytesDecodedToDetermineProperties() const
60 {
61     // Set to match value used for CoreGraphics.
62     return 13088;
63 }
64
65 String ImageDecoderDirect2D::filenameExtension() const
66 {
67     notImplemented();
68     return String();
69 }
70
71 bool ImageDecoderDirect2D::isSizeAvailable() const
72 {
73     return m_nativeDecoder ? true : false;
74 }
75
76 EncodedDataStatus ImageDecoderDirect2D::encodedDataStatus() const
77 {
78     if (!m_nativeDecoder)
79         return EncodedDataStatus::Error;
80
81     // FIXME: Hook into WIC decoder (if async decode is even possible)
82     return EncodedDataStatus::Complete;
83 }
84
85 IntSize ImageDecoderDirect2D::size() const
86 {
87     if (!m_nativeDecoder)
88         return IntSize();
89
90     COMPtr<IWICBitmapFrameDecode> frame;
91     HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
92     if (!SUCCEEDED(hr))
93         return IntSize();
94
95     UINT width, height;
96     hr = frame->GetSize(&width, &height);
97     if (!SUCCEEDED(hr))
98         return IntSize();
99
100     return IntSize(width, height);
101 }
102
103 size_t ImageDecoderDirect2D::frameCount() const
104 {
105     if (!m_nativeDecoder)
106         return 0;
107
108     UINT count;
109     HRESULT hr = m_nativeDecoder->GetFrameCount(&count);
110     if (!SUCCEEDED(hr))
111         return 0;
112
113     return count;
114 }
115
116 RepetitionCount ImageDecoderDirect2D::repetitionCount() const
117 {
118     if (!m_nativeDecoder)
119         return RepetitionCountNone;
120
121     // FIXME: Identify image type, and determine proper repetition count.
122     return RepetitionCountNone;
123 }
124
125 Optional<IntPoint> ImageDecoderDirect2D::hotSpot() const
126 {
127     return IntPoint();
128 }
129
130 IntSize ImageDecoderDirect2D::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
131 {
132     if (!m_nativeDecoder)
133         return IntSize();
134
135     COMPtr<IWICBitmapFrameDecode> frame;
136     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
137     if (!SUCCEEDED(hr))
138         return IntSize();
139
140     UINT width, height;
141     hr = frame->GetSize(&width, &height);
142     if (!SUCCEEDED(hr))
143         return IntSize();
144
145     return IntSize(width, height);
146 }
147
148 bool ImageDecoderDirect2D::frameIsCompleteAtIndex(size_t index) const
149 {
150     if (!m_nativeDecoder)
151         return false;
152
153     COMPtr<IWICBitmapFrameDecode> frame;
154     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
155     return SUCCEEDED(hr);
156 }
157
158 ImageOrientation ImageDecoderDirect2D::frameOrientationAtIndex(size_t index) const
159 {
160     if (!m_nativeDecoder)
161         return ImageOrientation();
162
163     COMPtr<IWICBitmapFrameDecode> frame;
164     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
165     if (!SUCCEEDED(hr))
166         return ImageOrientation();
167
168     COMPtr<IWICMetadataQueryReader> metadata;
169     hr = frame->GetMetadataQueryReader(&metadata);
170     if (!SUCCEEDED(hr))
171         return ImageOrientation();
172
173     // FIXME: Identify image type, and ask proper orientation.
174     return ImageOrientation();
175 }
176
177 Seconds ImageDecoderDirect2D::frameDurationAtIndex(size_t index) const
178 {
179     if (!m_nativeDecoder)
180         return Seconds(0);
181
182     COMPtr<IWICBitmapFrameDecode> frame;
183     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
184     if (!SUCCEEDED(hr))
185         return Seconds(0);
186
187     // FIXME: Figure out correct image format-specific query for frame duration check.
188     notImplemented();
189     return Seconds(0);
190 }
191
192 bool ImageDecoderDirect2D::frameAllowSubsamplingAtIndex(size_t index) const
193 {
194     if (!m_nativeDecoder)
195         return false;
196
197     COMPtr<IWICBitmapFrameDecode> frame;
198     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
199     if (!SUCCEEDED(hr))
200         return false;
201
202     // FIXME: Figure out correct image format-specific query for subsampling check.
203     notImplemented();
204     return true;
205 }
206
207 bool ImageDecoderDirect2D::frameHasAlphaAtIndex(size_t index) const
208 {
209     if (!m_nativeDecoder)
210         return false;
211
212     COMPtr<IWICBitmapFrameDecode> frame;
213     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
214     if (!SUCCEEDED(hr))
215         return false;
216
217     // FIXME: Figure out correct image format-specific query for alpha check.
218     notImplemented();
219     return true;
220 }
221
222 unsigned ImageDecoderDirect2D::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
223 {
224     if (!m_nativeDecoder)
225         return 0;
226
227     auto frameSize = frameSizeAtIndex(index, subsamplingLevel);
228     return (frameSize.area() * 4).unsafeGet();
229 }
230
231 void ImageDecoderDirect2D::setTargetContext(ID2D1RenderTarget* renderTarget)
232 {
233     m_renderTarget = renderTarget;
234 }
235
236 NativeImagePtr ImageDecoderDirect2D::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions&)
237 {
238     if (!m_nativeDecoder || !m_renderTarget)
239         return nullptr;
240
241     COMPtr<IWICBitmapFrameDecode> frame;
242     HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
243     if (!SUCCEEDED(hr))
244         return nullptr;
245
246     COMPtr<IWICFormatConverter> converter;
247     hr = systemImagingFactory()->CreateFormatConverter(&converter);
248     if (!SUCCEEDED(hr))
249         return nullptr;
250
251     hr = converter->Initialize(frame.get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
252     if (!SUCCEEDED(hr))
253         return nullptr;
254
255     COMPtr<ID2D1Bitmap> bitmap;
256     hr = m_renderTarget->CreateBitmapFromWicBitmap(converter.get(), nullptr, &bitmap);
257     if (!SUCCEEDED(hr))
258         return nullptr;
259
260     return bitmap;
261 }
262
263 void ImageDecoderDirect2D::setData(SharedBuffer& data, bool allDataReceived)
264 {
265     if (!allDataReceived)
266         return;
267
268     COMPtr<IWICStream> stream;
269     HRESULT hr = systemImagingFactory()->CreateStream(&stream);
270     if (!SUCCEEDED(hr))
271         return;
272
273     char* dataPtr = const_cast<char*>(data.data());
274     hr = stream->InitializeFromMemory(reinterpret_cast<BYTE*>(dataPtr), data.size());
275     if (!SUCCEEDED(hr))
276         return;
277
278     m_nativeDecoder = nullptr;
279
280     hr = systemImagingFactory()->CreateDecoderFromStream(stream.get(), nullptr, WICDecodeMetadataCacheOnDemand, &m_nativeDecoder);
281     if (!SUCCEEDED(hr)) {
282         m_nativeDecoder = nullptr;
283         return;
284     }
285
286     // Image was valid.
287 }
288 }
289
290 #endif