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 const size_t width = m_frameContext->width(); |
206 int incode; | |
207 const unsigned char *ch; | |
208 | 206 |
209 if (rowIter == rowBuffer.end()) | 207 if (rowIter == rowBuffer.end()) |
210 return true; | 208 return true; |
211 | 209 |
212 #define OUTPUT_ROW \ | 210 for (const unsigned char *ch = block; bytesInBlock-- > 0; ch++) { |
Peter Kasting
2013/08/31 00:08:49
Nit: Put * on typename
Alpha Left Google
2013/09/01 01:40:21
Done.
| |
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++) { | |
223 // Feed the next byte into the decoder's 32-bit input buffer. | 211 // Feed the next byte into the decoder's 32-bit input buffer. |
224 datum += ((int) *ch) << bits; | 212 datum += ((int) *ch) << bits; |
225 bits += 8; | 213 bits += 8; |
226 | 214 |
227 // Check for underflow of decoder's 32-bit input buffer. | 215 // Check for underflow of decoder's 32-bit input buffer. |
228 while (bits >= codesize) { | 216 while (bits >= codesize) { |
229 // Get the leading variable-length symbol from the data stream. | 217 // Get the leading variable-length symbol from the data stream. |
230 code = datum & codemask; | 218 int code = datum & codemask; |
231 datum >>= codesize; | 219 datum >>= codesize; |
232 bits -= codesize; | 220 bits -= codesize; |
233 | 221 |
234 // Reset the dictionary to its original state, if requested. | 222 // Reset the dictionary to its original state, if requested. |
235 if (code == clearCode) { | 223 if (code == clearCode) { |
236 codesize = m_frameContext->dataSize() + 1; | 224 codesize = m_frameContext->dataSize() + 1; |
237 codemask = (1 << codesize) - 1; | 225 codemask = (1 << codesize) - 1; |
238 avail = clearCode + 2; | 226 avail = clearCode + 2; |
239 oldcode = -1; | 227 oldcode = -1; |
240 continue; | 228 continue; |
241 } | 229 } |
242 | 230 |
243 // Check for explicit end-of-stream code. | 231 // Check for explicit end-of-stream code. |
244 if (code == (clearCode + 1)) { | 232 if (code == (clearCode + 1)) { |
245 // end-of-stream should only appear after all image data. | 233 // end-of-stream should only appear after all image data. |
246 if (!rowsRemaining) | 234 if (!rowsRemaining) |
247 return true; | 235 return true; |
248 return false; | 236 return false; |
249 } | 237 } |
250 | 238 |
251 if (oldcode == -1) { | 239 if (oldcode == -1) { |
Peter Kasting
2013/08/31 00:08:49
I just realized that because we don't check that (
Peter Kasting
2013/08/31 02:07:20
Update: The old code defended against this with th
Alpha Left Google
2013/09/01 01:40:21
I removed this branch and let the other branch han
| |
240 // The previous code is not available either because this is the | |
241 // first code in the stream or the dictionary was reset. | |
242 // This code must therefore just be a single character, which we | |
243 // can write directly to the stream. | |
244 firstchar = oldcode = code; | |
245 if (rowIter >= rowBuffer.end()) | |
Peter Kasting
2013/08/31 02:07:20
How can this condition or either of the ones below
Alpha Left Google
2013/09/01 01:40:21
That is true. Since we can be sure there's no cycl
| |
246 return false; | |
252 *rowIter++ = suffix[code]; | 247 *rowIter++ = suffix[code]; |
253 if (rowIter == rowBuffer.end()) | 248 } else { |
254 OUTPUT_ROW; | 249 int tempCode = code; |
250 unsigned short codeLength = 0; | |
251 if (code < avail) { | |
252 // This is a pre-existing code, so we already know what it | |
253 // encodes. | |
254 codeLength = suffixLength[code]; | |
255 rowIter += codeLength; | |
256 if (rowIter > rowBuffer.end()) | |
257 return false; | |
258 } else if (code == avail) { | |
259 // This is a new code just being added to the dictionary. | |
260 // It must encode the contents of the previous code, plus | |
261 // the first character of the previous code again. | |
262 codeLength = suffixLength[oldcode] + 1; | |
263 rowIter += codeLength; | |
264 if (rowIter > rowBuffer.end()) | |
265 return false; | |
266 *--rowIter = firstchar; | |
267 code = oldcode; | |
268 } else { | |
269 // This is an invalid code. | |
270 return false; | |
271 } | |
255 | 272 |
256 firstchar = oldcode = code; | 273 while (code >= clearCode) { |
257 continue; | 274 *--rowIter = suffix[code]; |
275 code = prefix[code]; | |
276 } | |
277 | |
278 *--rowIter = firstchar = suffix[code]; | |
279 | |
280 // Define a new codeword in the dictionary. | |
281 if (avail < MAX_DICTIONARY_ENTRIES) { | |
282 prefix[avail] = oldcode; | |
283 suffix[avail] = firstchar; | |
284 suffixLength[avail] = suffixLength[oldcode] + 1; | |
285 ++avail; | |
286 | |
287 // If we've used up all the codewords of a given length | |
288 // increase the length of codewords by one bit, but don't | |
289 // exceed the specified maximum codeword size. | |
290 if ((!(avail & codemask)) && (avail < MAX_DICTIONARY_ENTRIES )) { | |
291 ++codesize; | |
292 codemask += avail; | |
293 } | |
294 } | |
295 oldcode = tempCode; | |
296 rowIter += codeLength; | |
258 } | 297 } |
259 | 298 |
260 incode = code; | 299 // Output as many rows as possible. |
261 if (code >= avail) { | 300 GIFRow::iterator rowBegin = rowBuffer.begin(); |
262 stack[stackp++] = firstchar; | 301 for (; rowBegin + width <= rowIter; rowBegin += width) { |
263 code = oldcode; | 302 if (!outputRow(rowBegin)) |
264 | |
265 if (stackp == MAX_BYTES) | |
266 return false; | 303 return false; |
304 rowsRemaining--; | |
305 if (!rowsRemaining) | |
306 return true; | |
267 } | 307 } |
268 | 308 |
269 while (code >= clearCode) { | 309 if (rowBegin != rowBuffer.begin()) { |
270 if (code >= MAX_BYTES || code == prefix[code]) | 310 // Move the remaining bytes to the beginning of buffer. |
Peter Kasting
2013/08/31 00:08:49
Nit: buffer -> the buffer
Alpha Left Google
2013/09/01 01:40:21
Done.
| |
271 return false; | 311 size_t bytesToCopy = rowIter - rowBegin; |
Peter Kasting
2013/08/31 00:08:49
Nit: Can be const (since you seem to be willing to
Alpha Left Google
2013/09/01 01:40:21
Done.
| |
272 | 312 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); |
273 // Even though suffix[] only holds characters through suffix[ava il - 1], | 313 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 } | 314 } |
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 } | 315 } |
309 } | 316 } |
310 | |
311 return true; | 317 return true; |
312 } | 318 } |
313 | 319 |
314 void GIFColorMap::buildTable(const unsigned char* data, size_t length) | 320 void GIFColorMap::buildTable(const unsigned char* data, size_t length) |
315 { | 321 { |
316 if (!m_isDefined || !m_table.isEmpty()) | 322 if (!m_isDefined || !m_table.isEmpty()) |
317 return; | 323 return; |
318 | 324 |
319 RELEASE_ASSERT(m_position + m_colors * GIF_COLORS <= length); | 325 RELEASE_ASSERT(m_position + m_colors * BYTES_PER_COLORMAP_ENTRY <= length); |
320 const unsigned char* srcColormap = data + m_position; | 326 const unsigned char* srcColormap = data + m_position; |
321 m_table.resize(m_colors); | 327 m_table.resize(m_colors); |
322 for (Table::iterator iter = m_table.begin(); iter != m_table.end(); ++iter) { | 328 for (Table::iterator iter = m_table.begin(); iter != m_table.end(); ++iter) { |
323 *iter = SkPackARGB32NoCheck(255, srcColormap[0], srcColormap[1], srcColo rmap[2]); | 329 *iter = SkPackARGB32NoCheck(255, srcColormap[0], srcColormap[1], srcColo rmap[2]); |
324 srcColormap += GIF_COLORS; | 330 srcColormap += BYTES_PER_COLORMAP_ENTRY; |
325 } | 331 } |
326 } | 332 } |
327 | 333 |
328 // Perform decoding for this frame. frameDecoded will be true if the entire fram e is decoded. | 334 // Perform decoding for this frame. frameDecoded will be true if the entire fram e is decoded. |
329 // Returns false if a decoding error occurred. This is a fatal error and causes the GIFImageReader to set the "decode failed" flag. | 335 // Returns false if a decoding error occurred. This is a fatal error and causes the GIFImageReader to set the "decode failed" flag. |
330 // Otherwise, either not enough data is available to decode further than before, or the new data has been decoded successfully; returns true in this case. | 336 // Otherwise, either not enough data is available to decode further than before, or the new data has been decoded successfully; returns true in this case. |
331 bool GIFFrameContext::decode(const unsigned char* data, size_t length, WebCore:: GIFImageDecoder* client, bool* frameDecoded) | 337 bool GIFFrameContext::decode(const unsigned char* data, size_t length, WebCore:: GIFImageDecoder* client, bool* frameDecoded) |
332 { | 338 { |
333 m_localColorMap.buildTable(data, length); | 339 m_localColorMap.buildTable(data, length); |
334 | 340 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 | 455 |
450 // CALLBACK: Inform the decoderplugin of our size. | 456 // CALLBACK: Inform the decoderplugin of our size. |
451 // Note: A subsequent frame might have dimensions larger than the "s creen" dimensions. | 457 // Note: A subsequent frame might have dimensions larger than the "s creen" dimensions. |
452 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) | 458 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) |
453 return false; | 459 return false; |
454 | 460 |
455 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07 ); | 461 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07 ); |
456 | 462 |
457 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g lobal map */ | 463 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g lobal map */ |
458 m_globalColorMap.setTablePositionAndSize(dataPosition, globalCol orMapColors); | 464 m_globalColorMap.setTablePositionAndSize(dataPosition, globalCol orMapColors); |
459 GETN(GIF_COLORS * globalColorMapColors, GIFGlobalColormap); | 465 GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalC olormap); |
460 break; | 466 break; |
461 } | 467 } |
462 | 468 |
463 GETN(1, GIFImageStart); | 469 GETN(1, GIFImageStart); |
464 break; | 470 break; |
465 } | 471 } |
466 | 472 |
467 case GIFGlobalColormap: { | 473 case GIFGlobalColormap: { |
468 m_globalColorMap.setDefined(); | 474 m_globalColorMap.setDefined(); |
469 GETN(1, GIFImageStart); | 475 GETN(1, GIFImageStart); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 // frame can be progressively displayed. | 693 // frame can be progressively displayed. |
688 // FIXME: It is possible that a non-transparent frame | 694 // FIXME: It is possible that a non-transparent frame |
689 // can be interlaced and progressively displayed. | 695 // can be interlaced and progressively displayed. |
690 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame()); | 696 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame()); |
691 | 697 |
692 const bool isLocalColormapDefined = currentComponent[8] & 0x80; | 698 const bool isLocalColormapDefined = currentComponent[8] & 0x80; |
693 if (isLocalColormapDefined) { | 699 if (isLocalColormapDefined) { |
694 // The three low-order bits of currentComponent[8] specify the b its per pixel. | 700 // The three low-order bits of currentComponent[8] specify the b its per pixel. |
695 const size_t numColors = 2 << (currentComponent[8] & 0x7); | 701 const size_t numColors = 2 << (currentComponent[8] & 0x7); |
696 currentFrame->localColorMap().setTablePositionAndSize(dataPositi on, numColors); | 702 currentFrame->localColorMap().setTablePositionAndSize(dataPositi on, numColors); |
697 GETN(GIF_COLORS * numColors, GIFImageColormap); | 703 GETN(BYTES_PER_COLORMAP_ENTRY * numColors, GIFImageColormap); |
698 break; | 704 break; |
699 } | 705 } |
700 | 706 |
701 GETN(1, GIFLZWStart); | 707 GETN(1, GIFLZWStart); |
702 break; | 708 break; |
703 } | 709 } |
704 | 710 |
705 case GIFImageColormap: { | 711 case GIFImageColormap: { |
706 ASSERT(!m_frames.isEmpty()); | 712 ASSERT(!m_frames.isEmpty()); |
707 m_frames.last()->localColorMap().setDefined(); | 713 m_frames.last()->localColorMap().setDefined(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
751 if (m_frames.isEmpty() || m_frames.last()->isComplete()) | 757 if (m_frames.isEmpty() || m_frames.last()->isComplete()) |
752 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); | 758 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size()))); |
753 } | 759 } |
754 | 760 |
755 // FIXME: Move this method to close to doLZW(). | 761 // FIXME: Move this method to close to doLZW(). |
756 bool GIFLZWContext::prepareToDecode() | 762 bool GIFLZWContext::prepareToDecode() |
757 { | 763 { |
758 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); | 764 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d()); |
759 | 765 |
760 // Since we use a codesize of 1 more than the datasize, we need to ensure | 766 // 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). | 767 // that our datasize is strictly less than the MAX_DICTIONARY_ENTRY_BITS. |
762 // This sets the largest possible codemask correctly at 4095. | 768 if (m_frameContext->dataSize() >= MAX_DICTIONARY_ENTRY_BITS) |
763 if (m_frameContext->dataSize() >= MAX_LZW_BITS) | |
764 return false; | 769 return false; |
765 clearCode = 1 << m_frameContext->dataSize(); | 770 clearCode = 1 << m_frameContext->dataSize(); |
766 if (clearCode >= MAX_BYTES) | |
767 return false; | |
768 | |
769 avail = clearCode + 2; | 771 avail = clearCode + 2; |
770 oldcode = -1; | 772 oldcode = -1; |
771 codesize = m_frameContext->dataSize() + 1; | 773 codesize = m_frameContext->dataSize() + 1; |
772 codemask = (1 << codesize) - 1; | 774 codemask = (1 << codesize) - 1; |
773 datum = bits = 0; | 775 datum = bits = 0; |
774 ipass = m_frameContext->interlaced() ? 1 : 0; | 776 ipass = m_frameContext->interlaced() ? 1 : 0; |
775 irow = 0; | 777 irow = 0; |
776 | 778 |
777 // Initialize output row buffer. | 779 // We want to know the longest sequence encodable by a dictionary with |
778 rowBuffer.resize(m_frameContext->width()); | 780 // MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base |
781 // values themselves at the beginning of the dictionary, as well as the need | |
782 // for a clear code or a termination code, we could use every entry to | |
783 // encode a series of multiple values. If the input value stream looked | |
784 // like "AAAAA..." (a long string of just one value), the first dictionary | |
785 // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus | |
786 // the longest sequence would be MAX_DICTIONARY_ENTRIES + 1 values. | |
787 // | |
788 // However, we have to account for reserved entries. The first |datasize| | |
789 // bits are reserved for the base values, and the next two entries are | |
790 // reserved for the clear code and termination code. In theory a GIF can | |
791 // set the datasize to 0, meaning we have just two reserved entries, making | |
792 // the longest sequence (MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since | |
793 // each value is a byte, this is also the number of bytes in the longest | |
794 // encodable sequence. | |
795 const size_t maxBytes = MAX_DICTIONARY_ENTRIES - 1; | |
796 | |
797 // Now allocate the output buffer. We decode directly into this buffer | |
798 // until we have at least one row worth of data, then call outputRow(). | |
799 // This means worst case we may have (row width - 1) bytes in the buffer | |
800 // and then decode a sequence |maxBytes| long to append. | |
801 rowBuffer.resize(m_frameContext->width() - 1 + maxBytes); | |
779 rowIter = rowBuffer.begin(); | 802 rowIter = rowBuffer.begin(); |
780 rowsRemaining = m_frameContext->height(); | 803 rowsRemaining = m_frameContext->height(); |
781 | 804 |
782 // Clearing the whole suffix table lets us be more tolerant of bad data. | 805 // Clearing the whole suffix table lets us be more tolerant of bad data. |
Peter Kasting
2013/08/31 00:08:49
I think this comment and the memset can just be nu
Alpha Left Google
2013/09/01 01:40:21
Thinking about this a bit more since we're now mor
| |
783 memset(suffix, 0, sizeof(suffix)); | 806 for (int i = 0; i < clearCode; ++i) |
807 suffix[i] = i; | |
808 memset(suffix + clearCode, 0, sizeof(suffix) - clearCode); | |
809 | |
810 for (int i = 0; i < MAX_DICTIONARY_ENTRIES; i++) | |
811 suffixLength[i] = 1; | |
784 | 812 |
785 // Clearing the whole prefix table to prevent uninitialized access. | 813 // Clearing the whole prefix table to prevent uninitialized access. |
786 memset(prefix, 0, sizeof(prefix)); | 814 memset(prefix, 0, sizeof(prefix)); |
787 for (int i = 0; i < clearCode; i++) | |
788 suffix[i] = i; | |
789 stackp = 0; | |
790 return true; | 815 return true; |
791 } | 816 } |
OLD | NEW |