2acf98ec2946723c45d1148fd985e23fa361ca33
[WebKit-https.git] / 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
24 #include "ImageDecoder.h"
25
26 #include <algorithm>
27 #include <cmath>
28
29 #include "BMPImageDecoder.h"
30 #include "GIFImageDecoder.h"
31 #include "ICOImageDecoder.h"
32 #include "JPEGImageDecoder.h"
33 #include "PNGImageDecoder.h"
34 #include "SharedBuffer.h"
35
36 using namespace std;
37
38 namespace WebCore {
39
40 static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
41 {
42     unsigned bytesExtracted = 0;
43     const char* moreData;
44     while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
45         unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
46         memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
47         bytesExtracted += bytesToCopy;
48         if (bytesExtracted == bufferLength)
49             break;
50         offset += bytesToCopy;
51     }
52     return bytesExtracted;
53 }
54
55 ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
56 {
57     // We need at least 4 bytes to figure out what kind of image we're dealing
58     // with.
59     static const unsigned maxMarkerLength = 4;
60     char contents[maxMarkerLength];
61     unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0);
62     if (length < maxMarkerLength)
63         return 0;
64
65     const unsigned char* uContents = reinterpret_cast<const unsigned char*>(contents);
66
67     // GIFs begin with GIF8(7 or 9).
68     if (strncmp(contents, "GIF8", 4) == 0)
69         return new GIFImageDecoder();
70
71     // Test for PNG.
72     if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
73         return new PNGImageDecoder();
74
75     // JPEG
76     if (!memcmp(contents, "\xFF\xD8\xFF", 3))
77         return new JPEGImageDecoder();
78
79     // BMP
80     if (strncmp(contents, "BM", 2) == 0)
81         return new BMPImageDecoder();
82
83     // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
84     // CURs begin with 2-byte 0 followed by 2-byte 2.
85     if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
86         return new ICOImageDecoder();
87
88     // Give up. We don't know what the heck this is.
89     return 0;
90 }
91
92 #if !PLATFORM(SKIA)
93
94 RGBA32Buffer::RGBA32Buffer()
95     : m_hasAlpha(false)
96     , m_status(FrameEmpty)
97     , m_duration(0)
98     , m_disposalMethod(DisposeNotSpecified)
99 {
100
101
102 void RGBA32Buffer::clear()
103 {
104     m_bytes.clear();
105     m_status = FrameEmpty;
106     // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
107     // to free the bitmap data, but other functions like initFrameBuffer() and
108     // frameComplete() may still need to read other metadata out of this frame
109     // later.
110 }
111
112 void RGBA32Buffer::zeroFill()
113 {
114     m_bytes.fill(0);
115     m_hasAlpha = true;
116 }
117
118 void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other)
119 {
120     if (this == &other)
121         return;
122
123     m_bytes = other.m_bytes;
124     m_size = other.m_size;
125     setHasAlpha(other.m_hasAlpha);
126 }
127
128 bool RGBA32Buffer::setSize(int newWidth, int newHeight)
129 {
130     // NOTE: This has no way to check for allocation failure if the requested
131     // size was too big...
132     m_bytes.resize(newWidth * newHeight);
133     m_size = IntSize(newWidth, newHeight);
134
135     // Zero the image.
136     zeroFill();
137
138     return true;
139 }
140
141 bool RGBA32Buffer::hasAlpha() const
142 {
143     return m_hasAlpha;
144 }
145
146 void RGBA32Buffer::setHasAlpha(bool alpha)
147 {
148     m_hasAlpha = alpha;
149 }
150
151 void RGBA32Buffer::setStatus(FrameStatus status)
152 {
153     m_status = status;
154 }
155
156 RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
157 {
158     if (this == &other)
159         return *this;
160
161     copyBitmapData(other);
162     setRect(other.rect());
163     setStatus(other.status());
164     setDuration(other.duration());
165     setDisposalMethod(other.disposalMethod());
166     return *this;
167 }
168
169 int RGBA32Buffer::width() const
170 {
171     return m_size.width();
172 }
173
174 int RGBA32Buffer::height() const
175 {
176     return m_size.height();
177 }
178
179 #endif
180
181 namespace {
182
183 enum MatchType {
184     Exact,
185     UpperBound,
186     LowerBound
187 };
188
189 inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int length)
190 {
191     double inflateRate = 1. / scaleRate;
192     scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5));
193     for (int scaledIndex = 0; ; ++scaledIndex) {
194         int index = static_cast<int>(scaledIndex * inflateRate + 0.5);
195         if (index >= length)
196             break;
197         scaledValues.append(index);
198     }
199 }
200
201 template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart)
202 {
203     if (scaledValues.isEmpty())
204         return valueToMatch;
205
206     const int* dataStart = scaledValues.data();
207     const int* dataEnd = dataStart + scaledValues.size();
208     const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch);
209     switch (type) {
210     case Exact:
211         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : -1;
212     case LowerBound:
213         return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : matched - dataStart - 1;
214     case UpperBound:
215     default:
216         return matched != dataEnd ? matched - dataStart : -1;
217     }
218 }
219
220 }
221
222 void ImageDecoder::prepareScaleDataIfNecessary()
223 {
224     int width = size().width();
225     int height = size().height();
226     int numPixels = height * width;
227     if (m_maxNumPixels > 0 && numPixels > m_maxNumPixels) {
228         m_scaled = true;
229         double scale = sqrt(m_maxNumPixels / (double)numPixels);
230         fillScaledValues(m_scaledColumns, scale, width);
231         fillScaledValues(m_scaledRows, scale, height);
232     } else if (m_scaled) {
233         m_scaled = false;
234         m_scaledColumns.clear();
235         m_scaledRows.clear();
236     }
237 }
238
239 int ImageDecoder::upperBoundScaledX(int origX, int searchStart)
240 {
241     return getScaledValue<UpperBound>(m_scaledColumns, origX, searchStart);
242 }
243
244 int ImageDecoder::lowerBoundScaledX(int origX, int searchStart)
245 {
246     return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart);
247 }
248
249 int ImageDecoder::upperBoundScaledY(int origY, int searchStart)
250 {
251     return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart);
252 }
253
254 int ImageDecoder::lowerBoundScaledY(int origY, int searchStart)
255 {
256     return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart);
257 }
258
259 int ImageDecoder::scaledY(int origY, int searchStart)
260 {
261     return getScaledValue<Exact>(m_scaledRows, origY, searchStart);
262 }
263
264 }