0f1bcb1a36980815edb34dc323ecb506a13c78d6
[WebKit-https.git] / Source / WebCore / platform / graphics / win / ImageDecoderDirect2D.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 "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 ImageDecoder::ImageDecoder()
45 {
46 }
47
48 IWICImagingFactory* ImageDecoder::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 ImageDecoder::bytesDecodedToDetermineProperties()
60 {
61     // Set to match value used for CoreGraphics.
62     return 13088;
63 }
64
65 String ImageDecoder::filenameExtension() const
66 {
67     notImplemented();
68     return String();
69 }
70
71 bool ImageDecoder::isSizeAvailable() const
72 {
73     return m_nativeDecoder ? true : false;
74 }
75
76 IntSize ImageDecoder::size() const
77 {
78     if (!m_nativeDecoder)
79         return IntSize();
80
81     COMPtr<IWICBitmapFrameDecode> frame;
82     HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
83     if (!SUCCEEDED(hr))
84         return IntSize();
85
86     UINT width, height;
87     hr = frame->GetSize(&width, &height);
88     if (!SUCCEEDED(hr))
89         return IntSize();
90
91     return IntSize(width, height);
92 }
93
94 size_t ImageDecoder::frameCount() const
95 {
96     if (!m_nativeDecoder)
97         return 0;
98
99     UINT count;
100     HRESULT hr = m_nativeDecoder->GetFrameCount(&count);
101     if (!SUCCEEDED(hr))
102         return 0;
103
104     return count;
105 }
106
107 RepetitionCount ImageDecoder::repetitionCount() const
108 {
109     return RepetitionCountNone;
110 }
111
112 Optional<IntPoint> ImageDecoder::hotSpot() const
113 {
114     return IntPoint();
115 }
116
117 IntSize ImageDecoder::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
118 {
119     if (!m_nativeDecoder)
120         return IntSize();
121
122     COMPtr<IWICBitmapFrameDecode> frame;
123     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
124     if (!SUCCEEDED(hr))
125         return IntSize();
126
127     UINT width, height;
128     hr = frame->GetSize(&width, &height);
129     if (!SUCCEEDED(hr))
130         return IntSize();
131
132     return IntSize(width, height);
133 }
134
135 bool ImageDecoder::frameIsCompleteAtIndex(size_t index) const
136 {
137     if (!m_nativeDecoder)
138         return false;
139
140     COMPtr<IWICBitmapFrameDecode> frame;
141     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
142     if (!SUCCEEDED(hr))
143         return false;
144
145     return true;
146 }
147
148 ImageOrientation ImageDecoder::frameOrientationAtIndex(size_t index) const
149 {
150     notImplemented();
151     return ImageOrientation();
152 }
153
154 float ImageDecoder::frameDurationAtIndex(size_t index) const
155 {
156     notImplemented();
157     return 0;
158 }
159
160 bool ImageDecoder::frameAllowSubsamplingAtIndex(size_t) const
161 {
162     notImplemented();
163     return true;
164 }
165
166 bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
167 {
168     notImplemented();
169     return true;
170 }
171
172 unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
173 {
174     if (!m_nativeDecoder)
175         return 0;
176
177     COMPtr<IWICBitmapFrameDecode> frame;
178     HRESULT hr = m_nativeDecoder->GetFrame(index, &frame);
179     if (!SUCCEEDED(hr))
180         return 0;
181
182     UINT width, height;
183     hr = frame->GetSize(&width, &height);
184     if (!SUCCEEDED(hr))
185         return 0;
186
187     return width * height * 4;
188 }
189
190 void ImageDecoder::setRenderTarget(ID2D1RenderTarget* renderTarget)
191 {
192     m_renderTarget = renderTarget;
193 }
194
195 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode) const
196 {
197     if (!m_nativeDecoder)
198         return nullptr;
199
200     COMPtr<IWICBitmapFrameDecode> frame;
201     HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
202     if (!SUCCEEDED(hr))
203         return nullptr;
204
205     COMPtr<IWICFormatConverter> converter;
206     hr = systemImagingFactory()->CreateFormatConverter(&converter);
207     if (!SUCCEEDED(hr))
208         return nullptr;
209
210     hr = converter->Initialize(frame.get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
211     if (!SUCCEEDED(hr))
212         return nullptr;
213
214     ASSERT(m_renderTarget);
215     if (!m_renderTarget)
216         return nullptr;
217
218     COMPtr<ID2D1Bitmap> bitmap;
219     hr = m_renderTarget->CreateBitmapFromWicBitmap(converter.get(), nullptr, &bitmap);
220     if (!SUCCEEDED(hr))
221         return nullptr;
222
223     return bitmap;
224 }
225
226 void ImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
227 {
228     if (allDataReceived)
229         return;
230
231     COMPtr<IWICStream> stream;
232     HRESULT hr = systemImagingFactory()->CreateStream(&stream);
233     if (!SUCCEEDED(hr))
234         return;
235
236     char* dataPtr = const_cast<char*>(data.data());
237     hr = stream->InitializeFromMemory(reinterpret_cast<BYTE*>(dataPtr), data.size());
238     if (!SUCCEEDED(hr))
239         return;
240
241     m_nativeDecoder = nullptr;
242
243     hr = systemImagingFactory()->CreateDecoderFromStream(stream.get(), nullptr, WICDecodeMetadataCacheOnDemand, &m_nativeDecoder);
244     ASSERT(SUCCEEDED(hr));
245 }
246
247 }
248
249 #endif