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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 #define GETN(n, s) \ | 91 #define GETN(n, s) \ |
| 92 do { \ | 92 do { \ |
| 93 m_bytesToConsume = (n); \ | 93 m_bytesToConsume = (n); \ |
| 94 m_state = (s); \ | 94 m_state = (s); \ |
| 95 } while (0) | 95 } while (0) |
| 96 | 96 |
| 97 // Get a 16-bit value stored in little-endian format. | 97 // Get a 16-bit value stored in little-endian format. |
| 98 #define GETINT16(p) ((p)[1]<<8|(p)[0]) | 98 #define GETINT16(p) ((p)[1]<<8|(p)[0]) |
| 99 | 99 |
| 100 // Send the data to the display front-end. | 100 // Send the data to the display front-end. |
| 101 bool GIFLZWContext::outputRow() | 101 bool GIFLZWContext::outputRow(GIFRow::const_iterator rowBegin) |
| 102 { | 102 { |
| 103 int drowStart = irow; | 103 int drowStart = irow; |
| 104 int drowEnd = irow; | 104 int drowEnd = irow; |
| 105 | 105 |
| 106 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while | 106 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while |
| 107 // displaying to diminish the "venetian-blind" effect as the image is | 107 // displaying to diminish the "venetian-blind" effect as the image is |
| 108 // loaded. Adjust pixel vertical positions to avoid the appearance of the | 108 // loaded. Adjust pixel vertical positions to avoid the appearance of the |
| 109 // image crawling up the screen as successive passes are drawn. | 109 // image crawling up the screen as successive passes are drawn. |
| 110 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) { | 110 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) { |
| 111 unsigned rowDup = 0; | 111 unsigned rowDup = 0; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 141 | 141 |
| 142 if ((unsigned)drowEnd >= m_frameContext->height()) | 142 if ((unsigned)drowEnd >= m_frameContext->height()) |
| 143 drowEnd = m_frameContext->height() - 1; | 143 drowEnd = m_frameContext->height() - 1; |
| 144 } | 144 } |
| 145 | 145 |
| 146 // Protect against too much image data. | 146 // Protect against too much image data. |
| 147 if ((unsigned)drowStart >= m_frameContext->height()) | 147 if ((unsigned)drowStart >= m_frameContext->height()) |
| 148 return true; | 148 return true; |
| 149 | 149 |
| 150 // CALLBACK: Let the client know we have decoded a row. | 150 // CALLBACK: Let the client know we have decoded a row. |
| 151 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBuffer, m_frameC ontext->width(), | 151 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameCo ntext->width(), |
| 152 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) | 152 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) |
| 153 return false; | 153 return false; |
| 154 | 154 |
| 155 if (!m_frameContext->interlaced()) | 155 if (!m_frameContext->interlaced()) |
| 156 irow++; | 156 irow++; |
| 157 else { | 157 else { |
| 158 do { | 158 do { |
| 159 switch (ipass) { | 159 switch (ipass) { |
| 160 case 1: | 160 case 1: |
| 161 irow += 8; | 161 irow += 8; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 } while (irow > (m_frameContext->height() - 1)); | 195 } while (irow > (m_frameContext->height() - 1)); |
| 196 } | 196 } |
| 197 return true; | 197 return true; |
| 198 } | 198 } |
| 199 | 199 |
| 200 // Perform Lempel-Ziv-Welch decoding. | 200 // Perform Lempel-Ziv-Welch decoding. |
| 201 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. | 201 // Returns true if decoding was successful. In this case the block will have bee n completely consumed and/or rowsRemaining will be 0. |
| 202 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. | 202 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag. |
| 203 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) | 203 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
| 204 { | 204 { |
| 205 int code; | 205 int code; |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Declare these first three where they are firs
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 206 int incode; | 206 int incode; |
| 207 const unsigned char *ch; | 207 const unsigned char *ch; |
| 208 size_t width = m_frameContext->width(); | |
| 208 | 209 |
| 209 if (rowIter == rowBuffer.end()) | 210 if (rowIter == rowBuffer.end()) |
| 210 return true; | 211 return true; |
| 211 | 212 |
| 212 #define OUTPUT_ROW \ | |
| 213 do { \ | |
| 214 if (!outputRow()) \ | |
| 215 return false; \ | |
| 216 rowsRemaining--; \ | |
| 217 rowIter = rowBuffer.begin(); \ | |
| 218 if (!rowsRemaining) \ | |
| 219 return true; \ | |
| 220 } while (0) | |
| 221 | |
| 222 for (ch = block; bytesInBlock-- > 0; ch++) { | 213 for (ch = block; bytesInBlock-- > 0; ch++) { |
| 223 // Feed the next byte into the decoder's 32-bit input buffer. | 214 // Feed the next byte into the decoder's 32-bit input buffer. |
| 224 datum += ((int) *ch) << bits; | 215 datum += ((int) *ch) << bits; |
| 225 bits += 8; | 216 bits += 8; |
| 226 | 217 |
| 227 // Check for underflow of decoder's 32-bit input buffer. | 218 // Check for underflow of decoder's 32-bit input buffer. |
| 228 while (bits >= codesize) { | 219 while (bits >= codesize) { |
| 229 // Get the leading variable-length symbol from the data stream. | 220 // Get the leading variable-length symbol from the data stream. |
| 230 code = datum & codemask; | 221 code = datum & codemask; |
| 231 datum >>= codesize; | 222 datum >>= codesize; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 242 | 233 |
| 243 // Check for explicit end-of-stream code. | 234 // Check for explicit end-of-stream code. |
| 244 if (code == (clearCode + 1)) { | 235 if (code == (clearCode + 1)) { |
| 245 // end-of-stream should only appear after all image data. | 236 // end-of-stream should only appear after all image data. |
| 246 if (!rowsRemaining) | 237 if (!rowsRemaining) |
| 247 return true; | 238 return true; |
| 248 return false; | 239 return false; |
| 249 } | 240 } |
| 250 | 241 |
| 251 if (oldcode == -1) { | 242 if (oldcode == -1) { |
| 243 // The previous code is not available either because this is the first | |
|
Peter Kasting
2013/08/29 23:46:25
Tiny nit: It seems like your comments in this sect
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 244 // code in the stream or the dictionary was reset. We'll write t he | |
| 245 // current code to stream. The code will have only one character . | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Maybe better second sentence:
This code must
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 246 firstchar = oldcode = code; | |
| 247 if (rowIter >= rowBuffer.end()) | |
| 248 return false; | |
| 252 *rowIter++ = suffix[code]; | 249 *rowIter++ = suffix[code]; |
| 253 if (rowIter == rowBuffer.end()) | 250 } else { |
| 254 OUTPUT_ROW; | 251 incode = code; |
| 252 unsigned short codeLength = 0; | |
| 253 if (code < avail) { | |
| 254 // This is a complete code. Code length and code content are known. | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
This is a pre-existing code,
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 255 codeLength = suffixLength[code]; | |
| 256 rowIter += codeLength; | |
| 257 if (rowIter >= rowBuffer.end()) | |
|
Peter Kasting
2013/08/29 23:46:25
Shouldn't this be '>', not ">=", since the row ite
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 258 return false; | |
| 259 } else if (code == avail) { | |
| 260 // This is an incomplete code. Code length is the length of previous | |
| 261 // code plus one. Code content is that of previous code conc atenated | |
| 262 // by the first character of previous code. | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: How about:
This is a new code just being add
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 263 codeLength = suffixLength[oldcode] + 1; | |
| 264 rowIter += codeLength; | |
| 265 if (rowIter >= rowBuffer.end()) | |
| 266 return false; | |
| 255 | 267 |
| 256 firstchar = oldcode = code; | 268 // The last character of this code is the first character of the |
| 257 continue; | 269 // previous code. Write it to output and then write the prev ious code. |
|
Peter Kasting
2013/08/29 23:46:25
Nit: This comment seems unnecessary given the abov
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 270 *--rowIter = firstchar; | |
| 271 code = oldcode; | |
| 272 } else { | |
| 273 // Bad code received. Complete and incomplete codes are defi ned up | |
| 274 // to |avail|. | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
This is an invalid code.
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 275 return false; | |
| 276 } | |
| 277 | |
| 278 while (code >= clearCode) { | |
| 279 if (code >= MAX_BYTES || code == prefix[code]) | |
|
Peter Kasting
2013/08/29 23:46:25
|code| must be less than MAX_BYTES, given how it w
Alpha Left Google
2013/08/30 23:25:36
I removed this block of comments entirely. Having
| |
| 280 return false; | |
| 281 | |
| 282 // Even though suffix[] only holds characters through suffix [avail - 1], | |
| 283 // allowing code >= avail here lets us be more tolerant of m alformed | |
| 284 // data. As long as code < MAX_BYTES, the only risk is a gar bled image, | |
| 285 // which is no worse than refusing to display it. | |
| 286 *--rowIter = suffix[code]; | |
| 287 code = prefix[code]; | |
| 288 } | |
| 289 | |
| 290 *--rowIter = firstchar = suffix[code]; | |
| 291 | |
| 292 // Define a new codeword in the dictionary. | |
| 293 if (avail < 4096) { | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Use MAX_DICTIONARY_ENTRIES here in place of 4
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 294 prefix[avail] = oldcode; | |
| 295 suffix[avail] = firstchar; | |
| 296 suffixLength[avail] = suffixLength[oldcode] + 1; | |
| 297 avail++; | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: I suggest using preincrement form wherever po
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 298 | |
| 299 // If we've used up all the codewords of a given length | |
| 300 // increase the length of codewords by one bit, but don't | |
| 301 // exceed the specified maximum codeword size of 12 bits. | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Remove "of 12 bits". Here and elsewhere, I'd
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 302 if ((!(avail & codemask)) && (avail < 4096)) { | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Instead of "(avail < 4096)", the equivalent "
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 303 codesize++; | |
| 304 codemask += avail; | |
| 305 } | |
| 306 } | |
| 307 oldcode = incode; | |
| 308 rowIter += codeLength; | |
| 258 } | 309 } |
| 259 | 310 |
| 260 incode = code; | 311 // Not enough bytes to output row. |
| 261 if (code >= avail) { | 312 if (rowIter < rowBuffer.begin() + width) |
| 262 stack[stackp++] = firstchar; | 313 continue; |
|
Peter Kasting
2013/08/29 23:46:25
Nit: It seems slightly clearer to me to skip this,
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 263 code = oldcode; | |
| 264 | 314 |
| 265 if (stackp == MAX_BYTES) | 315 // There's enough data to output. Output as many rows as possible. |
| 316 GIFRow::iterator rowBegin = rowBuffer.begin(); | |
| 317 for (;rowBegin + width <= rowIter; rowBegin += width) { | |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Space after first semicolon.
If you don't ta
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 318 if (!outputRow(rowBegin)) | |
| 266 return false; | 319 return false; |
| 320 rowsRemaining--; | |
| 321 if (!rowsRemaining) | |
| 322 return true; | |
| 267 } | 323 } |
| 268 | 324 |
| 269 while (code >= clearCode) { | 325 // These bytes cannot make up a full row. Move them to the beginning |
| 270 if (code >= MAX_BYTES || code == prefix[code]) | 326 // of buffer. |
|
Peter Kasting
2013/08/29 23:46:25
Nit: How about just:
Move the remaining bytes to
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 271 return false; | 327 size_t bytesToCopy = rowIter - rowBegin; |
| 272 | 328 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); |
| 273 // Even though suffix[] only holds characters through suffix[ava il - 1], | 329 rowIter = rowBuffer.begin() + bytesToCopy; |
| 274 // allowing code >= avail here lets us be more tolerant of malfo rmed | |
| 275 // data. As long as code < MAX_BYTES, the only risk is a garbled image, | |
| 276 // which is no worse than refusing to display it. | |
| 277 stack[stackp++] = suffix[code]; | |
| 278 code = prefix[code]; | |
| 279 | |
| 280 if (stackp == MAX_BYTES) | |
| 281 return false; | |
| 282 } | |
| 283 | |
| 284 stack[stackp++] = firstchar = suffix[code]; | |
| 285 | |
| 286 // Define a new codeword in the dictionary. | |
| 287 if (avail < 4096) { | |
| 288 prefix[avail] = oldcode; | |
| 289 suffix[avail] = firstchar; | |
| 290 avail++; | |
| 291 | |
| 292 // If we've used up all the codewords of a given length | |
| 293 // increase the length of codewords by one bit, but don't | |
| 294 // exceed the specified maximum codeword size of 12 bits. | |
| 295 if ((!(avail & codemask)) && (avail < 4096)) { | |
| 296 codesize++; | |
| 297 codemask += avail; | |
| 298 } | |
| 299 } | |
| 300 oldcode = incode; | |
| 301 | |
| 302 // Copy the decoded data out to the scanline buffer. | |
| 303 do { | |
| 304 *rowIter++ = stack[--stackp]; | |
| 305 if (rowIter == rowBuffer.end()) | |
| 306 OUTPUT_ROW; | |
| 307 } while (stackp > 0); | |
| 308 } | 330 } |
| 309 } | 331 } |
| 310 | |
| 311 return true; | 332 return true; |
| 312 } | 333 } |
| 313 | 334 |
| 314 void GIFColorMap::buildTable(const unsigned char* data, size_t length) | 335 void GIFColorMap::buildTable(const unsigned char* data, size_t length) |
| 315 { | 336 { |
| 316 if (!m_isDefined || !m_table.isEmpty()) | 337 if (!m_isDefined || !m_table.isEmpty()) |
| 317 return; | 338 return; |
| 318 | 339 |
| 319 RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length); | 340 RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length); |
| 320 const unsigned char* srcColormap = data + m_position; | 341 const unsigned char* srcColormap = data + m_position; |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 752 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); | 773 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); |
| 753 } | 774 } |
| 754 | 775 |
| 755 // FIXME: Move this method to close to doLZW(). | 776 // FIXME: Move this method to close to doLZW(). |
| 756 bool GIFLZWContext::prepareToDecode() | 777 bool GIFLZWContext::prepareToDecode() |
| 757 { | 778 { |
| 758 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); | 779 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); |
| 759 | 780 |
| 760 // Since we use a codesize of 1 more than the datasize, we need to ensure | 781 // Since we use a codesize of 1 more than the datasize, we need to ensure |
| 761 // that our datasize is strictly less than the MAX_LZW_BITS value (12). | 782 // that our datasize is strictly less than the MAX_LZW_BITS value (12). |
| 762 // This sets the largest possible codemask correctly at 4095. | 783 // This sets the largest possible codemask correctly at 4095. |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Remove last sentence, and remove "(12)" from
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 763 if (m_frameContext->dataSize() >= MAX_LZW_BITS) | 784 if (m_frameContext->dataSize() >= MAX_LZW_BITS) |
| 764 return false; | 785 return false; |
| 765 clearCode = 1 << m_frameContext->dataSize(); | 786 clearCode = 1 << m_frameContext->dataSize(); |
| 766 if (clearCode >= MAX_BYTES) | 787 if (clearCode >= MAX_BYTES) |
|
Peter Kasting
2013/08/29 23:46:25
This conditional cannot fail given the previous co
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 767 return false; | 788 return false; |
| 768 | 789 |
| 769 avail = clearCode + 2; | 790 avail = clearCode + 2; |
| 770 oldcode = -1; | 791 oldcode = -1; |
| 771 codesize = m_frameContext->dataSize() + 1; | 792 codesize = m_frameContext->dataSize() + 1; |
| 772 codemask = (1 << codesize) - 1; | 793 codemask = (1 << codesize) - 1; |
| 773 datum = bits = 0; | 794 datum = bits = 0; |
| 774 ipass = m_frameContext->interlaced() ? 1 : 0; | 795 ipass = m_frameContext->interlaced() ? 1 : 0; |
| 775 irow = 0; | 796 irow = 0; |
| 776 | 797 |
| 777 // Initialize output row buffer. | 798 // Initialize output row buffer. |
| 778 rowBuffer.resize(m_frameContext->width()); | 799 rowBuffer.resize(m_frameContext->width() + MAX_BYTES); |
|
Peter Kasting
2013/08/29 23:46:25
(See my comment atop GIFImageReader.h as to why I
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 779 rowIter = rowBuffer.begin(); | 800 rowIter = rowBuffer.begin(); |
| 780 rowsRemaining = m_frameContext->height(); | 801 rowsRemaining = m_frameContext->height(); |
| 781 | 802 |
| 782 // Clearing the whole suffix table lets us be more tolerant of bad data. | 803 // Clearing the whole suffix table lets us be more tolerant of bad data. |
| 783 memset(suffix, 0, sizeof(suffix)); | 804 memset(suffix, 0, sizeof(suffix)); |
|
Peter Kasting
2013/08/29 23:46:25
Nit: Seems like we could save a little time on the
Alpha Left Google
2013/08/30 23:25:36
Done.
| |
| 805 for (int i = 0; i < clearCode; ++i) | |
| 806 suffix[i] = i; | |
| 807 for (int i = 0; i < MAX_BYTES; i++) | |
| 808 suffixLength[i] = 1; | |
| 784 | 809 |
| 785 // Clearing the whole prefix table to prevent uninitialized access. | 810 // Clearing the whole prefix table to prevent uninitialized access. |
| 786 memset(prefix, 0, sizeof(prefix)); | 811 memset(prefix, 0, sizeof(prefix)); |
| 787 for (int i = 0; i < clearCode; i++) | |
| 788 suffix[i] = i; | |
| 789 stackp = 0; | |
| 790 return true; | 812 return true; |
| 791 } | 813 } |
| OLD | NEW |