Chromium Code Reviews| 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 |