OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 28 matching lines...) Expand all Loading... |
39 namespace blink { | 39 namespace blink { |
40 | 40 |
41 // Number of bits in .ICO/.CUR used to store the directory and its entries, | 41 // Number of bits in .ICO/.CUR used to store the directory and its entries, |
42 // respectively (doesn't match sizeof values for member structs since we omit | 42 // respectively (doesn't match sizeof values for member structs since we omit |
43 // some fields). | 43 // some fields). |
44 static const size_t sizeOfDirectory = 6; | 44 static const size_t sizeOfDirectory = 6; |
45 static const size_t sizeOfDirEntry = 16; | 45 static const size_t sizeOfDirEntry = 16; |
46 | 46 |
47 ICOImageDecoder::ICOImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOp
tion colorOptions, size_t maxDecodedBytes) | 47 ICOImageDecoder::ICOImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOp
tion colorOptions, size_t maxDecodedBytes) |
48 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) | 48 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) |
49 , m_fastReader(nullptr) | |
50 , m_decodedOffset(0) | 49 , m_decodedOffset(0) |
51 { | 50 { |
52 } | 51 } |
53 | 52 |
54 ICOImageDecoder::~ICOImageDecoder() | 53 ICOImageDecoder::~ICOImageDecoder() |
55 { | 54 { |
56 } | 55 } |
57 | 56 |
58 void ICOImageDecoder::onSetData(SharedBuffer* data) | 57 void ICOImageDecoder::onSetData(SharedBuffer* data) |
59 { | 58 { |
60 m_fastReader.setData(data); | |
61 | |
62 for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end();
++i) { | 59 for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end();
++i) { |
63 if (*i) | 60 if (*i) |
64 (*i)->setData(data); | 61 (*i)->setData(data); |
65 } | 62 } |
66 for (size_t i = 0; i < m_pngDecoders.size(); ++i) | 63 for (size_t i = 0; i < m_pngDecoders.size(); ++i) |
67 setDataForPNGDecoderAtIndex(i); | 64 setDataForPNGDecoderAtIndex(i); |
68 } | 65 } |
69 | 66 |
70 IntSize ICOImageDecoder::size() const | 67 IntSize ICOImageDecoder::size() const |
71 { | 68 { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 { | 119 { |
123 decodeSize(); | 120 decodeSize(); |
124 return m_dirEntries.size(); | 121 return m_dirEntries.size(); |
125 } | 122 } |
126 | 123 |
127 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) | 124 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) |
128 { | 125 { |
129 if (!m_pngDecoders[index]) | 126 if (!m_pngDecoders[index]) |
130 return; | 127 return; |
131 | 128 |
132 m_pngDecoders[index]->setData(m_data.get(), isAllDataReceived()); | 129 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; |
| 130 // Copy out PNG data to a separate vector and send to the PNG decoder. |
| 131 // FIXME: Save this copy by making the PNG decoder able to take an |
| 132 // optional offset. |
| 133 RefPtr<SharedBuffer> pngData(SharedBuffer::create(&m_data->data()[dirEntry.m
_imageOffset], m_data->size() - dirEntry.m_imageOffset)); |
| 134 m_pngDecoders[index]->setData(pngData.get(), isAllDataReceived()); |
133 } | 135 } |
134 | 136 |
135 void ICOImageDecoder::decode(size_t index, bool onlySize) | 137 void ICOImageDecoder::decode(size_t index, bool onlySize) |
136 { | 138 { |
137 if (failed()) | 139 if (failed()) |
138 return; | 140 return; |
139 | 141 |
140 // If we couldn't decode the image but we've received all the data, decoding | 142 // If we couldn't decode the image but we've received all the data, decoding |
141 // has failed. | 143 // has failed. |
142 if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDat
aReceived()) | 144 if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDat
aReceived()) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 m_bmpReaders[index]->setData(m_data.get()); | 179 m_bmpReaders[index]->setData(m_data.get()); |
178 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); | 180 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); |
179 } | 181 } |
180 m_frameSize = dirEntry.m_size; | 182 m_frameSize = dirEntry.m_size; |
181 bool result = m_bmpReaders[index]->decodeBMP(false); | 183 bool result = m_bmpReaders[index]->decodeBMP(false); |
182 m_frameSize = IntSize(); | 184 m_frameSize = IntSize(); |
183 return result; | 185 return result; |
184 } | 186 } |
185 | 187 |
186 if (!m_pngDecoders[index]) { | 188 if (!m_pngDecoders[index]) { |
187 AlphaOption alphaOption = m_premultiplyAlpha ? AlphaPremultiplied : Alph
aNotPremultiplied; | 189 m_pngDecoders[index] = adoptPtr( |
188 GammaAndColorProfileOption colorOptions = m_ignoreGammaAndColorProfile ?
GammaAndColorProfileIgnored : GammaAndColorProfileApplied; | 190 new PNGImageDecoder(m_premultiplyAlpha ? AlphaPremultiplied : AlphaN
otPremultiplied, |
189 m_pngDecoders[index] = adoptPtr(new PNGImageDecoder(alphaOption, colorOp
tions, m_maxDecodedBytes, dirEntry.m_imageOffset)); | 191 m_ignoreGammaAndColorProfile ? GammaAndColorProfileIgnored : Gam
maAndColorProfileApplied, m_maxDecodedBytes)); |
190 setDataForPNGDecoderAtIndex(index); | 192 setDataForPNGDecoderAtIndex(index); |
191 } | 193 } |
192 | |
193 // Fail if the size the PNGImageDecoder calculated does not match the size | 194 // Fail if the size the PNGImageDecoder calculated does not match the size |
194 // in the directory. | 195 // in the directory. |
195 if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size()
!= dirEntry.m_size)) | 196 if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size()
!= dirEntry.m_size)) |
196 return setFailed(); | 197 return setFailed(); |
197 m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); | 198 m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); |
198 m_frameBufferCache[index].setPremultiplyAlpha(m_premultiplyAlpha); | 199 m_frameBufferCache[index].setPremultiplyAlpha(m_premultiplyAlpha); |
199 return !m_pngDecoders[index]->failed() || setFailed(); | 200 return !m_pngDecoders[index]->failed() || setFailed(); |
200 } | 201 } |
201 | 202 |
202 bool ICOImageDecoder::processDirectory() | 203 bool ICOImageDecoder::processDirectory() |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 // The image size is the size of the largest entry. | 246 // The image size is the size of the largest entry. |
246 const IconDirectoryEntry& dirEntry = m_dirEntries.first(); | 247 const IconDirectoryEntry& dirEntry = m_dirEntries.first(); |
247 // Technically, this next call shouldn't be able to fail, since the width | 248 // Technically, this next call shouldn't be able to fail, since the width |
248 // and height here are each <= 256, and |m_frameSize| is empty. | 249 // and height here are each <= 256, and |m_frameSize| is empty. |
249 return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); | 250 return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); |
250 } | 251 } |
251 | 252 |
252 ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() | 253 ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() |
253 { | 254 { |
254 // Read icon data. | 255 // Read icon data. |
255 // The following calls to readUint8() return a uint8_t, which is appropriate | 256 // The casts to uint8_t in the next few lines are because that's the on-disk |
256 // because that's the on-disk type of the width and height values. Storing | 257 // type of the width and height values. Storing them in ints (instead of |
257 // them in ints (instead of matching uint8_ts) is so we can record dimension
s | 258 // matching uint8_ts) is so we can record dimensions of size 256 (which is |
258 // of size 256 (which is what a zero byte really means). | 259 // what a zero byte really means). |
259 int width = readUint8(0); | 260 int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]); |
260 if (!width) | 261 if (!width) |
261 width = 256; | 262 width = 256; |
262 int height = readUint8(1); | 263 int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]); |
263 if (!height) | 264 if (!height) |
264 height = 256; | 265 height = 256; |
265 IconDirectoryEntry entry; | 266 IconDirectoryEntry entry; |
266 entry.m_size = IntSize(width, height); | 267 entry.m_size = IntSize(width, height); |
267 if (m_fileType == CURSOR) { | 268 if (m_fileType == CURSOR) { |
268 entry.m_bitCount = 0; | 269 entry.m_bitCount = 0; |
269 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6)); | 270 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6)); |
270 } else { | 271 } else { |
271 entry.m_bitCount = readUint16(6); | 272 entry.m_bitCount = readUint16(6); |
272 entry.m_hotSpot = IntPoint(); | 273 entry.m_hotSpot = IntPoint(); |
273 } | 274 } |
274 entry.m_imageOffset = readUint32(12); | 275 entry.m_imageOffset = readUint32(12); |
275 | 276 |
276 // Some icons don't have a bit depth, only a color count. Convert the | 277 // Some icons don't have a bit depth, only a color count. Convert the |
277 // color count to the minimum necessary bit depth. It doesn't matter if | 278 // color count to the minimum necessary bit depth. It doesn't matter if |
278 // this isn't quite what the bitmap info header says later, as we only use | 279 // this isn't quite what the bitmap info header says later, as we only use |
279 // this value to determine which icon entry is best. | 280 // this value to determine which icon entry is best. |
280 if (!entry.m_bitCount) { | 281 if (!entry.m_bitCount) { |
281 int colorCount = readUint8(2); | 282 int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2
]); |
282 if (!colorCount) | 283 if (!colorCount) |
283 colorCount = 256; // Vague in the spec, needed by real-world icons. | 284 colorCount = 256; // Vague in the spec, needed by real-world icons. |
284 for (--colorCount; colorCount; colorCount >>= 1) | 285 for (--colorCount; colorCount; colorCount >>= 1) |
285 ++entry.m_bitCount; | 286 ++entry.m_bitCount; |
286 } | 287 } |
287 | 288 |
288 m_decodedOffset += sizeOfDirEntry; | 289 m_decodedOffset += sizeOfDirEntry; |
289 return entry; | 290 return entry; |
290 } | 291 } |
291 | 292 |
292 ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index) | 293 ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index) |
293 { | 294 { |
294 // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic | 295 // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic |
295 // number. | 296 // number. |
296 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size()); | 297 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size()); |
297 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; | 298 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; |
298 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) | 299 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) |
299 return Unknown; | 300 return Unknown; |
300 char buffer[4]; | 301 return strncmp(&m_data->data()[imageOffset], "\x89PNG", 4) ? BMP : PNG; |
301 const char* data = m_fastReader.getConsecutiveData(imageOffset, 4, buffer); | |
302 return strncmp(data, "\x89PNG", 4) ? BMP : PNG; | |
303 } | 302 } |
304 | 303 |
305 } | 304 } |
OLD | NEW |