Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: Source/platform/image-decoders/ico/ICOImageDecoder.cpp

Issue 1316203008: Never consolidate data in ICO decoder (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@FastSharedBuffer
Patch Set: Remove unnecessary blank line Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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)
49 , m_decodedOffset(0) 50 , m_decodedOffset(0)
50 { 51 {
51 } 52 }
52 53
53 ICOImageDecoder::~ICOImageDecoder() 54 ICOImageDecoder::~ICOImageDecoder()
54 { 55 {
55 } 56 }
56 57
57 void ICOImageDecoder::onSetData(SharedBuffer* data) 58 void ICOImageDecoder::onSetData(SharedBuffer* data)
58 { 59 {
60 m_fastReader.setData(data);
61
59 for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end(); ++i) { 62 for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end(); ++i) {
60 if (*i) 63 if (*i)
61 (*i)->setData(data); 64 (*i)->setData(data);
62 } 65 }
63 for (size_t i = 0; i < m_pngDecoders.size(); ++i) 66 for (size_t i = 0; i < m_pngDecoders.size(); ++i)
64 setDataForPNGDecoderAtIndex(i); 67 setDataForPNGDecoderAtIndex(i);
65 } 68 }
66 69
67 IntSize ICOImageDecoder::size() const 70 IntSize ICOImageDecoder::size() const
68 { 71 {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 { 122 {
120 decodeSize(); 123 decodeSize();
121 return m_dirEntries.size(); 124 return m_dirEntries.size();
122 } 125 }
123 126
124 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) 127 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index)
125 { 128 {
126 if (!m_pngDecoders[index]) 129 if (!m_pngDecoders[index])
127 return; 130 return;
128 131
129 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; 132 m_pngDecoders[index]->setData(m_data.get(), isAllDataReceived());
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());
135 } 133 }
136 134
137 void ICOImageDecoder::decode(size_t index, bool onlySize) 135 void ICOImageDecoder::decode(size_t index, bool onlySize)
138 { 136 {
139 if (failed()) 137 if (failed())
140 return; 138 return;
141 139
142 // If we couldn't decode the image but we've received all the data, decoding 140 // If we couldn't decode the image but we've received all the data, decoding
143 // has failed. 141 // has failed.
144 if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDat aReceived()) 142 if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDat aReceived())
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 m_bmpReaders[index]->setData(m_data.get()); 177 m_bmpReaders[index]->setData(m_data.get());
180 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); 178 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]);
181 } 179 }
182 m_frameSize = dirEntry.m_size; 180 m_frameSize = dirEntry.m_size;
183 bool result = m_bmpReaders[index]->decodeBMP(false); 181 bool result = m_bmpReaders[index]->decodeBMP(false);
184 m_frameSize = IntSize(); 182 m_frameSize = IntSize();
185 return result; 183 return result;
186 } 184 }
187 185
188 if (!m_pngDecoders[index]) { 186 if (!m_pngDecoders[index]) {
189 m_pngDecoders[index] = adoptPtr( 187 AlphaOption alphaOption = m_premultiplyAlpha ? AlphaPremultiplied : Alph aNotPremultiplied;
190 new PNGImageDecoder(m_premultiplyAlpha ? AlphaPremultiplied : AlphaN otPremultiplied, 188 GammaAndColorProfileOption colorOptions = m_ignoreGammaAndColorProfile ? GammaAndColorProfileIgnored : GammaAndColorProfileApplied;
Peter Kasting 2015/09/08 20:03:13 Nit: I'd name this "option" instead of "options" t
scroggo_chromium 2015/09/08 20:52:51 This name was suggested to me by noel@ a refactori
191 m_ignoreGammaAndColorProfile ? GammaAndColorProfileIgnored : Gam maAndColorProfileApplied, m_maxDecodedBytes)); 189
190 // dirEntry.m_imageOffset is known to be correct, since this function is never called unless decodeDirectory succeeds.
Peter Kasting 2015/09/08 20:03:13 Nit: This comment is probably unnecessary, we assu
scroggo_chromium 2015/09/08 20:52:51 Done.
191 m_pngDecoders[index] = adoptPtr(new PNGImageDecoder(alphaOption, colorOp tions, m_maxDecodedBytes, dirEntry.m_imageOffset));
192
192 setDataForPNGDecoderAtIndex(index); 193 setDataForPNGDecoderAtIndex(index);
193 } 194 }
195
194 // Fail if the size the PNGImageDecoder calculated does not match the size 196 // Fail if the size the PNGImageDecoder calculated does not match the size
195 // in the directory. 197 // in the directory.
196 if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) 198 if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size))
197 return setFailed(); 199 return setFailed();
198 m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); 200 m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0);
199 m_frameBufferCache[index].setPremultiplyAlpha(m_premultiplyAlpha); 201 m_frameBufferCache[index].setPremultiplyAlpha(m_premultiplyAlpha);
200 return !m_pngDecoders[index]->failed() || setFailed(); 202 return !m_pngDecoders[index]->failed() || setFailed();
201 } 203 }
202 204
203 bool ICOImageDecoder::processDirectory() 205 bool ICOImageDecoder::processDirectory()
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 // The image size is the size of the largest entry. 248 // The image size is the size of the largest entry.
247 const IconDirectoryEntry& dirEntry = m_dirEntries.first(); 249 const IconDirectoryEntry& dirEntry = m_dirEntries.first();
248 // Technically, this next call shouldn't be able to fail, since the width 250 // Technically, this next call shouldn't be able to fail, since the width
249 // and height here are each <= 256, and |m_frameSize| is empty. 251 // and height here are each <= 256, and |m_frameSize| is empty.
250 return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); 252 return setSize(dirEntry.m_size.width(), dirEntry.m_size.height());
251 } 253 }
252 254
253 ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() 255 ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry()
254 { 256 {
255 // Read icon data. 257 // Read icon data.
256 // The casts to uint8_t in the next few lines are because that's the on-disk 258 // The following calls to readUint8 return an uint8_t, which is appropriate
Peter Kasting 2015/09/08 20:03:13 Nit: "...readUint8() return a uint8_t..." (add par
scroggo_chromium 2015/09/08 20:52:51 Done.
257 // type of the width and height values. Storing them in ints (instead of 259 // because that's the on-disk type of the width and height values. Storing
258 // matching uint8_ts) is so we can record dimensions of size 256 (which is 260 // them in ints (instead of matching uint8_ts) is so we can record dimension s
259 // what a zero byte really means). 261 // of size 256 (which is what a zero byte really means).
260 int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]); 262 int width = readUint8(0);
261 if (!width) 263 if (!width)
262 width = 256; 264 width = 256;
263 int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]); 265 int height = readUint8(1);
264 if (!height) 266 if (!height)
265 height = 256; 267 height = 256;
266 IconDirectoryEntry entry; 268 IconDirectoryEntry entry;
267 entry.m_size = IntSize(width, height); 269 entry.m_size = IntSize(width, height);
268 if (m_fileType == CURSOR) { 270 if (m_fileType == CURSOR) {
269 entry.m_bitCount = 0; 271 entry.m_bitCount = 0;
270 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6)); 272 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6));
271 } else { 273 } else {
272 entry.m_bitCount = readUint16(6); 274 entry.m_bitCount = readUint16(6);
273 entry.m_hotSpot = IntPoint(); 275 entry.m_hotSpot = IntPoint();
274 } 276 }
275 entry.m_imageOffset = readUint32(12); 277 entry.m_imageOffset = readUint32(12);
276 278
277 // Some icons don't have a bit depth, only a color count. Convert the 279 // Some icons don't have a bit depth, only a color count. Convert the
278 // color count to the minimum necessary bit depth. It doesn't matter if 280 // color count to the minimum necessary bit depth. It doesn't matter if
279 // this isn't quite what the bitmap info header says later, as we only use 281 // this isn't quite what the bitmap info header says later, as we only use
280 // this value to determine which icon entry is best. 282 // this value to determine which icon entry is best.
281 if (!entry.m_bitCount) { 283 if (!entry.m_bitCount) {
282 int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2 ]); 284 int colorCount = readUint8(2);
283 if (!colorCount) 285 if (!colorCount)
284 colorCount = 256; // Vague in the spec, needed by real-world icons. 286 colorCount = 256; // Vague in the spec, needed by real-world icons.
285 for (--colorCount; colorCount; colorCount >>= 1) 287 for (--colorCount; colorCount; colorCount >>= 1)
286 ++entry.m_bitCount; 288 ++entry.m_bitCount;
287 } 289 }
288 290
289 m_decodedOffset += sizeOfDirEntry; 291 m_decodedOffset += sizeOfDirEntry;
290 return entry; 292 return entry;
291 } 293 }
292 294
293 ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index) 295 ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index)
294 { 296 {
295 // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic 297 // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic
296 // number. 298 // number.
297 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size()); 299 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size());
298 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; 300 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset;
299 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) 301 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4))
300 return Unknown; 302 return Unknown;
301 return strncmp(&m_data->data()[imageOffset], "\x89PNG", 4) ? BMP : PNG; 303 char buffer[4];
304 const char* data = m_fastReader.getConsecutiveData(imageOffset, 4, buffer);
305 return strncmp(data, "\x89PNG", 4) ? BMP : PNG;
302 } 306 }
303 307
304 } 308 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698