[Qt] Unreviewed build fix after r136410
[WebKit-https.git] / Source / WebCore / platform / image-decoders / ImageDecoder.cpp
1 /*
2  * Copyright (C) 2008-2009 Torch Mobile, Inc.
3  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public License
16  *  along with this library; see the file COPYING.LIB.  If not, write to
17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  *  Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "ImageDecoder.h"
24
25 #include "BMPImageDecoder.h"
26 #include "GIFImageDecoder.h"
27 #include "ICOImageDecoder.h"
28 #if PLATFORM(QT)
29 #include "ImageDecoderQt.h"
30 #endif
31 #if !PLATFORM(QT) || USE(LIBJPEG)
32 #include "JPEGImageDecoder.h"
33 #endif
34 #include "PNGImageDecoder.h"
35 #include "PlatformMemoryInstrumentation.h"
36 #include "SharedBuffer.h"
37 #if USE(WEBP)
38 #include "WEBPImageDecoder.h"
39 #endif
40
41 #include <algorithm>
42 #include <cmath>
43 #include <wtf/MemoryInstrumentationVector.h>
44
45 using namespace std;
46
47 namespace WebCore {
48
49 namespace {
50
51 unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
52 {
53     unsigned bytesExtracted = 0;
54     const char* moreData;
55     while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
56         unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
57         memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
58         bytesExtracted += bytesToCopy;
59         if (bytesExtracted == bufferLength)
60             break;
61         offset += bytesToCopy;
62     }
63     return bytesExtracted;
64 }
65
66 bool matchesGIFSignature(char* contents)
67 {
68     return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6);
69 }
70
71 bool matchesPNGSignature(char* contents)
72 {
73     return !memcmp(contents, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8);
74 }
75
76 bool matchesJPEGSignature(char* contents)
77 {
78     return !memcmp(contents, "\xFF\xD8\xFF", 3);
79 }
80
81 #if USE(WEBP)
82 bool matchesWebPSignature(char* contents)
83 {
84     return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
85 }
86 #endif
87
88 bool matchesBMPSignature(char* contents)
89 {
90     return !memcmp(contents, "BM", 2);
91 }
92
93 bool matchesICOSignature(char* contents)
94 {
95     return !memcmp(contents, "\x00\x00\x01\x00", 4);
96 }
97
98 bool matchesCURSignature(char* contents)
99 {
100     return !memcmp(contents, "\x00\x00\x02\x00", 4);
101 }
102
103 }
104
105 ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
106 {
107     static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
108     char contents[lengthOfLongestSignature];
109     unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
110     if (length < lengthOfLongestSignature)
111         return 0;
112
113     if (matchesGIFSignature(contents))
114         return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
115
116 #if !PLATFORM(QT) || (PLATFORM(QT) && USE(LIBPNG))
117     if (matchesPNGSignature(contents))
118         return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
119
120     if (matchesICOSignature(contents) || matchesCURSignature(contents))
121         return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
122 #endif
123
124 #if !PLATFORM(QT) || (PLATFORM(QT) && USE(LIBJPEG))
125     if (matchesJPEGSignature(contents))
126         return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
127 #endif
128
129 #if USE(WEBP)
130     if (matchesWebPSignature(contents))
131         return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
132 #endif
133
134     if (matchesBMPSignature(contents))
135         return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
136
137 #if PLATFORM(QT)
138     return new ImageDecoderQt(alphaOption, gammaAndColorProfileOption);
139 #endif
140     return 0;
141 }
142
143 #if !USE(SKIA)
144
145 ImageFrame::ImageFrame()
146     : m_hasAlpha(false)
147     , m_status(FrameEmpty)
148     , m_duration(0)
149     , m_disposalMethod(DisposeNotSpecified)
150     , m_premultiplyAlpha(true)
151 {
152
153
154 ImageFrame& ImageFrame::operator=(const ImageFrame& other)
155 {
156     if (this == &other)
157         return *this;
158
159     copyBitmapData(other);
160     setOriginalFrameRect(other.originalFrameRect());
161     setStatus(other.status());
162     setDuration(other.duration());
163     setDisposalMethod(other.disposalMethod());
164     setPremultiplyAlpha(other.premultiplyAlpha());
165     return *this;
166 }
167
168 void ImageFrame::clearPixelData()
169 {
170     m_backingStore.clear();
171     m_bytes = 0;
172     m_status = FrameEmpty;
173     // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
174     // to free the bitmap data, but other functions like initFrameBuffer() and
175     // frameComplete() may still need to read other metadata out of this frame
176     // later.
177 }
178
179 void ImageFrame::zeroFillPixelData()
180 {
181     memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
182     m_hasAlpha = true;
183 }
184
185 bool ImageFrame::copyBitmapData(const ImageFrame& other)
186 {
187     if (this == &other)
188         return true;
189
190     m_backingStore = other.m_backingStore;
191     m_bytes = m_backingStore.data();
192     m_size = other.m_size;
193     setHasAlpha(other.m_hasAlpha);
194     return true;
195 }
196
197 bool ImageFrame::setSize(int newWidth, int newHeight)
198 {
199     ASSERT(!width() && !height());
200     size_t backingStoreSize = newWidth * newHeight;
201     if (!m_backingStore.tryReserveCapacity(backingStoreSize))
202         return false;
203     m_backingStore.resize(backingStoreSize);
204     m_bytes = m_backingStore.data();
205     m_size = IntSize(newWidth, newHeight);
206
207     zeroFillPixelData();
208     return true;
209 }
210
211 bool ImageFrame::hasAlpha() const
212 {
213     return m_hasAlpha;
214 }
215
216 void ImageFrame::setHasAlpha(bool alpha)
217 {
218     m_hasAlpha = alpha;
219 }
220
221 void ImageFrame::setColorProfile(const ColorProfile& colorProfile)
222 {
223     m_colorProfile = colorProfile;
224 }
225
226 void ImageFrame::setStatus(FrameStatus status)
227 {
228     m_status = status;
229 }
230
231 void ImageFrame::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
232 {
233     MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image);
234     info.addMember(m_backingStore);
235 }
236
237 #endif
238
239 namespace {
240
241 enum MatchType {
242     Exact,
243     UpperBound,
244     LowerBound
245 };
246
247 inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int length)
248 {
249     double inflateRate = 1. / scaleRate;
250     scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5));
251     for (int scaledIndex = 0; ; ++scaledIndex) {
252         int index = static_cast<int>(scaledIndex * inflateRate + 0.5);
253         if (index >= length)
254             break;
255         scaledValues.append(index);
256     }
257 }
258
259 template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart)
260 {
261     if (scaledValues.isEmpty())
262         return valueToMatch;
263
264     const int* dataStart = scaledValues.data();
265     const int* dataEnd = dataStart + scaledValues.size();
266     const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch);
267     switch (type) {
268     case Exact:
269         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : -1;
270     case LowerBound:
271         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : matched - dataStart - 1;
272     case UpperBound:
273     default:
274         return matched != dataEnd ? matched - dataStart : -1;
275     }
276 }
277
278 }
279
280 bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
281 {
282     if (m_frameBufferCache.size() <= index)
283         return true;
284     if (m_frameBufferCache[index].status() == ImageFrame::FrameComplete)
285         return m_frameBufferCache[index].hasAlpha();
286     return true;
287 }
288
289 unsigned ImageDecoder::frameBytesAtIndex(size_t index) const
290 {
291     if (m_frameBufferCache.size() <= index)
292         return 0;
293     // FIXME: Use the dimension of the requested frame.
294     return m_size.area() * sizeof(ImageFrame::PixelData);
295 }
296
297 void ImageDecoder::prepareScaleDataIfNecessary()
298 {
299     m_scaled = false;
300     m_scaledColumns.clear();
301     m_scaledRows.clear();
302
303     int width = size().width();
304     int height = size().height();
305     int numPixels = height * width;
306     if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels)
307         return;
308
309     m_scaled = true;
310     double scale = sqrt(m_maxNumPixels / (double)numPixels);
311     fillScaledValues(m_scaledColumns, scale, width);
312     fillScaledValues(m_scaledRows, scale, height);
313 }
314
315 int ImageDecoder::upperBoundScaledX(int origX, int searchStart)
316 {
317     return getScaledValue<UpperBound>(m_scaledColumns, origX, searchStart);
318 }
319
320 int ImageDecoder::lowerBoundScaledX(int origX, int searchStart)
321 {
322     return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart);
323 }
324
325 int ImageDecoder::upperBoundScaledY(int origY, int searchStart)
326 {
327     return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart);
328 }
329
330 int ImageDecoder::lowerBoundScaledY(int origY, int searchStart)
331 {
332     return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart);
333 }
334
335 int ImageDecoder::scaledY(int origY, int searchStart)
336 {
337     return getScaledValue<Exact>(m_scaledRows, origY, searchStart);
338 }
339
340 void ImageDecoder::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
341 {
342     MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image);
343     info.addMember(m_data);
344     info.addMember(m_frameBufferCache);
345     info.addMember(m_colorProfile);
346     info.addMember(m_scaledColumns);
347     info.addMember(m_scaledRows);
348 }
349
350 }