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

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

Issue 2065423003: Re-land: Blink image-decoders: (lazy) deferred image decoding support for ICO (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix decodeFrameCount - copy approach from WebP and GIF decoder Created 4 years, 6 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size(); 78 return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size();
79 } 79 }
80 80
81 bool ICOImageDecoder::setSize(unsigned width, unsigned height) 81 bool ICOImageDecoder::setSize(unsigned width, unsigned height)
82 { 82 {
83 // The size calculated inside the BMPImageReader had better match the one in 83 // The size calculated inside the BMPImageReader had better match the one in
84 // the icon directory. 84 // the icon directory.
85 return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntS ize(width, height) == m_frameSize) || setFailed()); 85 return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntS ize(width, height) == m_frameSize) || setFailed());
86 } 86 }
87 87
88 bool ICOImageDecoder::frameIsCompleteAtIndex(size_t index) const
89 {
90 if (index >= m_dirEntries.size())
91 return false;
92 const IconDirectoryEntry& dirEntry = m_dirEntries[index];
93 return (dirEntry.m_imageOffset + dirEntry.m_byteSize) <= m_data->size();
94 }
95
88 bool ICOImageDecoder::setFailed() 96 bool ICOImageDecoder::setFailed()
89 { 97 {
90 m_bmpReaders.clear(); 98 m_bmpReaders.clear();
91 m_pngDecoders.clear(); 99 m_pngDecoders.clear();
92 return ImageDecoder::setFailed(); 100 return ImageDecoder::setFailed();
93 } 101 }
94 102
95 bool ICOImageDecoder::hotSpot(IntPoint& hotSpot) const 103 bool ICOImageDecoder::hotSpot(IntPoint& hotSpot) const
96 { 104 {
97 // When unspecified, the default frame is always frame 0. This is consistent with 105 // When unspecified, the default frame is always frame 0. This is consistent with
(...skipping 17 matching lines...) Expand all
115 { 123 {
116 // Larger icons are better. After that, higher bit-depth icons are better. 124 // Larger icons are better. After that, higher bit-depth icons are better.
117 const int aEntryArea = a.m_size.width() * a.m_size.height(); 125 const int aEntryArea = a.m_size.width() * a.m_size.height();
118 const int bEntryArea = b.m_size.width() * b.m_size.height(); 126 const int bEntryArea = b.m_size.width() * b.m_size.height();
119 return (aEntryArea == bEntryArea) ? (a.m_bitCount > b.m_bitCount) : (aEntryA rea > bEntryArea); 127 return (aEntryArea == bEntryArea) ? (a.m_bitCount > b.m_bitCount) : (aEntryA rea > bEntryArea);
120 } 128 }
121 129
122 size_t ICOImageDecoder::decodeFrameCount() 130 size_t ICOImageDecoder::decodeFrameCount()
123 { 131 {
124 decodeSize(); 132 decodeSize();
133
134 // If decodeSize() fails, return the existing number of frames. This way
135 // if we get halfway through the image before decoding fails, we won't
136 // suddenly start reporting that the image has zero frames.
137 if (failed())
138 return m_frameBufferCache.size();
139
140 // Length of sequence of completely received frames.
141 for (size_t i = 0; i < m_dirEntries.size(); ++i) {
142 const IconDirectoryEntry& dirEntry = m_dirEntries[i];
143 if ((dirEntry.m_imageOffset + dirEntry.m_byteSize) > m_data->size())
144 return i;
145 }
125 return m_dirEntries.size(); 146 return m_dirEntries.size();
126 } 147 }
127 148
128 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) 149 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index)
129 { 150 {
130 if (!m_pngDecoders[index]) 151 if (!m_pngDecoders[index])
131 return; 152 return;
132 153
133 m_pngDecoders[index]->setData(m_data.get(), isAllDataReceived()); 154 m_pngDecoders[index]->setData(m_data.get(), isAllDataReceived());
134 } 155 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 bool ICOImageDecoder::decodeAtIndex(size_t index) 189 bool ICOImageDecoder::decodeAtIndex(size_t index)
169 { 190 {
170 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size()); 191 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size());
171 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; 192 const IconDirectoryEntry& dirEntry = m_dirEntries[index];
172 const ImageType imageType = imageTypeAtIndex(index); 193 const ImageType imageType = imageTypeAtIndex(index);
173 if (imageType == Unknown) 194 if (imageType == Unknown)
174 return false; // Not enough data to determine image type yet. 195 return false; // Not enough data to determine image type yet.
175 196
176 if (imageType == BMP) { 197 if (imageType == BMP) {
177 if (!m_bmpReaders[index]) { 198 if (!m_bmpReaders[index]) {
178 // We need to have already sized m_frameBufferCache before this, and
179 // we must not resize it again later (see caution in frameCount()).
180 ASSERT(m_frameBufferCache.size() == m_dirEntries.size());
181 m_bmpReaders[index] = adoptPtr(new BMPImageReader(this, dirEntry.m_i mageOffset, 0, true)); 199 m_bmpReaders[index] = adoptPtr(new BMPImageReader(this, dirEntry.m_i mageOffset, 0, true));
182 m_bmpReaders[index]->setData(m_data.get()); 200 m_bmpReaders[index]->setData(m_data.get());
183 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]);
184 } 201 }
202 // Update the pointer to the buffer as it could change after
203 // m_frameBufferCache.resize().
204 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]);
185 m_frameSize = dirEntry.m_size; 205 m_frameSize = dirEntry.m_size;
186 bool result = m_bmpReaders[index]->decodeBMP(false); 206 bool result = m_bmpReaders[index]->decodeBMP(false);
187 m_frameSize = IntSize(); 207 m_frameSize = IntSize();
188 return result; 208 return result;
189 } 209 }
190 210
191 if (!m_pngDecoders[index]) { 211 if (!m_pngDecoders[index]) {
192 AlphaOption alphaOption = m_premultiplyAlpha ? AlphaPremultiplied : Alph aNotPremultiplied; 212 AlphaOption alphaOption = m_premultiplyAlpha ? AlphaPremultiplied : Alph aNotPremultiplied;
193 GammaAndColorProfileOption colorOptions = m_ignoreGammaAndColorProfile ? GammaAndColorProfileIgnored : GammaAndColorProfileApplied; 213 GammaAndColorProfileOption colorOptions = m_ignoreGammaAndColorProfile ? GammaAndColorProfileIgnored : GammaAndColorProfileApplied;
194 m_pngDecoders[index] = adoptPtr(new PNGImageDecoder(alphaOption, colorOp tions, m_maxDecodedBytes, dirEntry.m_imageOffset)); 214 m_pngDecoders[index] = adoptPtr(new PNGImageDecoder(alphaOption, colorOp tions, m_maxDecodedBytes, dirEntry.m_imageOffset));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 height = 256; 293 height = 256;
274 IconDirectoryEntry entry; 294 IconDirectoryEntry entry;
275 entry.m_size = IntSize(width, height); 295 entry.m_size = IntSize(width, height);
276 if (m_fileType == CURSOR) { 296 if (m_fileType == CURSOR) {
277 entry.m_bitCount = 0; 297 entry.m_bitCount = 0;
278 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6)); 298 entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6));
279 } else { 299 } else {
280 entry.m_bitCount = readUint16(6); 300 entry.m_bitCount = readUint16(6);
281 entry.m_hotSpot = IntPoint(); 301 entry.m_hotSpot = IntPoint();
282 } 302 }
303 entry.m_byteSize = readUint32(8);
283 entry.m_imageOffset = readUint32(12); 304 entry.m_imageOffset = readUint32(12);
284 305
285 // Some icons don't have a bit depth, only a color count. Convert the 306 // Some icons don't have a bit depth, only a color count. Convert the
286 // color count to the minimum necessary bit depth. It doesn't matter if 307 // color count to the minimum necessary bit depth. It doesn't matter if
287 // this isn't quite what the bitmap info header says later, as we only use 308 // this isn't quite what the bitmap info header says later, as we only use
288 // this value to determine which icon entry is best. 309 // this value to determine which icon entry is best.
289 if (!entry.m_bitCount) { 310 if (!entry.m_bitCount) {
290 int colorCount = readUint8(2); 311 int colorCount = readUint8(2);
291 if (!colorCount) 312 if (!colorCount)
292 colorCount = 256; // Vague in the spec, needed by real-world icons. 313 colorCount = 256; // Vague in the spec, needed by real-world icons.
(...skipping 12 matching lines...) Expand all
305 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size()); 326 ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size());
306 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; 327 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset;
307 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) 328 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4))
308 return Unknown; 329 return Unknown;
309 char buffer[4]; 330 char buffer[4];
310 const char* data = m_fastReader.getConsecutiveData(imageOffset, 4, buffer); 331 const char* data = m_fastReader.getConsecutiveData(imageOffset, 4, buffer);
311 return strncmp(data, "\x89PNG", 4) ? BMP : PNG; 332 return strncmp(data, "\x89PNG", 4) ? BMP : PNG;
312 } 333 }
313 334
314 } // namespace blink 335 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698