OLD | NEW |
---|---|
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* ***** BEGIN LICENSE BLOCK ***** | 2 /* ***** BEGIN LICENSE BLOCK ***** |
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 * | 4 * |
5 * The contents of this file are subject to the Mozilla Public License Version | 5 * The contents of this file are subject to the Mozilla Public License Version |
6 * 1.1 (the "License"); you may not use this file except in compliance with | 6 * 1.1 (the "License"); you may not use this file except in compliance with |
7 * the License. You may obtain a copy of the License at | 7 * the License. You may obtain a copy of the License at |
8 * http://www.mozilla.org/MPL/ | 8 * http://www.mozilla.org/MPL/ |
9 * | 9 * |
10 * Software distributed under the License is distributed on an "AS IS" basis, | 10 * Software distributed under the License is distributed on an "AS IS" basis, |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 | 139 |
140 if ((unsigned)drowEnd >= m_frameContext->height()) | 140 if ((unsigned)drowEnd >= m_frameContext->height()) |
141 drowEnd = m_frameContext->height() - 1; | 141 drowEnd = m_frameContext->height() - 1; |
142 } | 142 } |
143 | 143 |
144 // Protect against too much image data. | 144 // Protect against too much image data. |
145 if ((unsigned)drowStart >= m_frameContext->height()) | 145 if ((unsigned)drowStart >= m_frameContext->height()) |
146 return true; | 146 return true; |
147 | 147 |
148 // CALLBACK: Let the client know we have decoded a row. | 148 // CALLBACK: Let the client know we have decoded a row. |
149 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameCo ntext->width(), | 149 if (!m_client->haveDecodedRow(*m_frameContext, rowBegin, |
150 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) | 150 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) |
151 return false; | 151 return false; |
152 | 152 |
153 if (!m_frameContext->interlaced()) | 153 if (!m_frameContext->interlaced()) |
154 irow++; | 154 irow++; |
155 else { | 155 else { |
156 do { | 156 do { |
157 switch (ipass) { | 157 switch (ipass) { |
158 case 1: | 158 case 1: |
159 irow += 8; | 159 irow += 8; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 // Perform Lempel-Ziv-Welch decoding. | 198 // Perform Lempel-Ziv-Welch decoding. |
199 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. | 199 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. |
200 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. | 200 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. |
201 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) | 201 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
202 { | 202 { |
203 const size_t width = m_frameContext->width(); | 203 const size_t width = m_frameContext->width(); |
204 | 204 |
205 if (rowIter == rowBuffer.end()) | 205 if (rowIter == rowBuffer.end()) |
206 return true; | 206 return true; |
207 | 207 |
208 for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) { | 208 for (const unsigned char* ch = block; bytesInBlock-- > 0; ++ch) { |
scroggo_chromium
2016/01/06 21:50:41
This seems like an unnecessary change, and at leas
aleksandar.stojiljkovic
2016/01/18 13:58:50
Done.
| |
209 // Feed the next byte into the decoder's 32-bit input buffer. | 209 // Feed the next byte into the decoder's 32-bit input buffer. |
210 datum += ((int) *ch) << bits; | 210 datum += ((int) *ch) << bits; |
211 bits += 8; | 211 bits += 8; |
212 | 212 |
213 // Check for underflow of decoder's 32-bit input buffer. | 213 // Check for underflow of decoder's 32-bit input buffer. |
214 while (bits >= codesize) { | 214 while (bits >= codesize) { |
215 // Get the leading variable-length symbol from the data stream. | 215 // Get the leading variable-length symbol from the data stream. |
216 int code = datum & codemask; | 216 int code = datum & codemask; |
217 datum >>= codesize; | 217 datum >>= codesize; |
218 bits -= codesize; | 218 bits -= codesize; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 if (!(avail & codemask) && avail < MAX_DICTIONARY_ENTRIES) { | 277 if (!(avail & codemask) && avail < MAX_DICTIONARY_ENTRIES) { |
278 ++codesize; | 278 ++codesize; |
279 codemask += avail; | 279 codemask += avail; |
280 } | 280 } |
281 } | 281 } |
282 oldcode = tempCode; | 282 oldcode = tempCode; |
283 rowIter += codeLength; | 283 rowIter += codeLength; |
284 | 284 |
285 // Output as many rows as possible. | 285 // Output as many rows as possible. |
286 GIFRow::iterator rowBegin = rowBuffer.begin(); | 286 GIFRow::iterator rowBegin = rowBuffer.begin(); |
287 for (; rowBegin + width <= rowIter; rowBegin += width) { | 287 if (rowBegin + width <= rowIter) { |
288 if (!outputRow(rowBegin)) | 288 for (; rowBegin + width <= rowIter; rowBegin += width) { |
289 return false; | 289 if (!outputRow(rowBegin)) |
290 rowsRemaining--; | 290 return false; |
291 if (!rowsRemaining) | 291 rowsRemaining--; |
292 return true; | 292 if (!rowsRemaining) |
293 } | 293 return true; |
294 } | |
294 | 295 |
295 if (rowBegin != rowBuffer.begin()) { | |
296 // Move the remaining bytes to the beginning of the buffer. | 296 // Move the remaining bytes to the beginning of the buffer. |
297 const size_t bytesToCopy = rowIter - rowBegin; | 297 const size_t bytesToCopy = rowIter - rowBegin; |
298 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); | 298 if (bytesToCopy) |
299 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); | |
299 rowIter = rowBuffer.begin() + bytesToCopy; | 300 rowIter = rowBuffer.begin() + bytesToCopy; |
300 } | 301 } |
301 } | 302 } |
302 } | 303 } |
303 return true; | 304 return true; |
304 } | 305 } |
305 | 306 |
306 void GIFColorMap::buildTable(blink::FastSharedBufferReader* reader) | 307 void GIFColorMap::buildTable(blink::FastSharedBufferReader* reader) |
307 { | 308 { |
308 if (!m_isDefined || !m_table.isEmpty()) | 309 if (!m_isDefined || !m_table.isEmpty()) |
(...skipping 27 matching lines...) Expand all Loading... | |
336 | 337 |
337 m_lzwContext = adoptPtr(new GIFLZWContext(client, this)); | 338 m_lzwContext = adoptPtr(new GIFLZWContext(client, this)); |
338 if (!m_lzwContext->prepareToDecode()) { | 339 if (!m_lzwContext->prepareToDecode()) { |
339 m_lzwContext.clear(); | 340 m_lzwContext.clear(); |
340 return false; | 341 return false; |
341 } | 342 } |
342 | 343 |
343 m_currentLzwBlock = 0; | 344 m_currentLzwBlock = 0; |
344 } | 345 } |
345 | 346 |
347 if (m_lzwContext->hasRemainingRows()) { | |
348 if (!client->initFrameBuffer(m_frameId)) | |
scroggo_chromium
2016/01/06 21:50:41
This function (GIFFrameContext::decode) may be cal
aleksandar.stojiljkovic
2016/01/18 13:58:50
Acknowledged.
It is intentional.
initFrameBuffer d
| |
349 return false; | |
350 } | |
351 | |
346 // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode. | 352 // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode. |
347 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingR ows()) { | 353 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingR ows()) { |
348 size_t blockPosition = m_lzwBlocks[m_currentLzwBlock].blockPosition; | 354 size_t blockPosition = m_lzwBlocks[m_currentLzwBlock].blockPosition; |
349 size_t blockSize = m_lzwBlocks[m_currentLzwBlock].blockSize; | 355 size_t blockSize = m_lzwBlocks[m_currentLzwBlock].blockSize; |
350 if (blockPosition + blockSize > reader->size()) | 356 if (blockPosition + blockSize > reader->size()) |
351 return false; | 357 return false; |
352 | 358 |
353 while (blockSize) { | 359 while (blockSize) { |
354 const char* segment = 0; | 360 const char* segment = 0; |
355 size_t segmentLength = reader->getSomeData(segment, blockPosition); | 361 size_t segmentLength = reader->getSomeData(segment, blockPosition); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 m_version = 87; | 453 m_version = 87; |
448 else | 454 else |
449 return false; | 455 return false; |
450 GETN(7, GIFGlobalHeader); | 456 GETN(7, GIFGlobalHeader); |
451 break; | 457 break; |
452 } | 458 } |
453 | 459 |
454 case GIFGlobalHeader: { | 460 case GIFGlobalHeader: { |
455 const unsigned char* currentComponent = | 461 const unsigned char* currentComponent = |
456 reinterpret_cast<const unsigned char*>( | 462 reinterpret_cast<const unsigned char*>( |
457 reader.getConsecutiveData(currentComponentPosition, 5, readB uffer)); | 463 reader.getConsecutiveData(currentComponentPosition, 6, readB uffer)); |
458 | 464 |
459 // This is the height and width of the "screen" or frame into which | 465 // This is the height and width of the "screen" or frame into which |
460 // images are rendered. The individual images can be smaller than | 466 // images are rendered. The individual images can be smaller than |
461 // the screen size and located with an origin anywhere within the | 467 // the screen size and located with an origin anywhere within the |
462 // screen. | 468 // screen. |
463 // Note that we don't inform the client of the size yet, as it might | 469 // Note that we don't inform the client of the size yet, as it might |
464 // change after we read the first frame's image header. | 470 // change after we read the first frame's image header. |
465 m_screenWidth = GETINT16(currentComponent); | 471 m_screenWidth = GETINT16(currentComponent); |
466 m_screenHeight = GETINT16(currentComponent + 2); | 472 m_screenHeight = GETINT16(currentComponent + 2); |
467 | 473 |
468 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07 ); | 474 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07 ); |
475 m_backgroundIndex = currentComponent[5]; | |
469 | 476 |
470 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g lobal map */ | 477 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g lobal map */ |
471 m_globalColorMap.setTablePositionAndSize(dataPosition, globalCol orMapColors); | 478 m_globalColorMap.setTablePositionAndSize(dataPosition, globalCol orMapColors); |
472 GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalC olormap); | 479 GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalC olormap); |
473 break; | 480 break; |
474 } | 481 } |
475 | 482 |
476 GETN(1, GIFImageStart); | 483 GETN(1, GIFImageStart); |
477 break; | 484 break; |
478 } | 485 } |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 rowIter = rowBuffer.begin(); | 848 rowIter = rowBuffer.begin(); |
842 rowsRemaining = m_frameContext->height(); | 849 rowsRemaining = m_frameContext->height(); |
843 | 850 |
844 // Clearing the whole suffix table lets us be more tolerant of bad data. | 851 // Clearing the whole suffix table lets us be more tolerant of bad data. |
845 for (int i = 0; i < clearCode; ++i) { | 852 for (int i = 0; i < clearCode; ++i) { |
846 suffix[i] = i; | 853 suffix[i] = i; |
847 suffixLength[i] = 1; | 854 suffixLength[i] = 1; |
848 } | 855 } |
849 return true; | 856 return true; |
850 } | 857 } |
OLD | NEW |