Index: Source/core/platform/image-decoders/gif/GIFImageReader.cpp |
diff --git a/Source/core/platform/image-decoders/gif/GIFImageReader.cpp b/Source/core/platform/image-decoders/gif/GIFImageReader.cpp |
index 7716cedef363aebbee4eca7cfb9af0389a219161..fba6228e96bdf38f5eafd74a39baf0602f225aff 100644 |
--- a/Source/core/platform/image-decoders/gif/GIFImageReader.cpp |
+++ b/Source/core/platform/image-decoders/gif/GIFImageReader.cpp |
@@ -98,7 +98,7 @@ using WebCore::GIFImageDecoder; |
#define GETINT16(p) ((p)[1]<<8|(p)[0]) |
// Send the data to the display front-end. |
-bool GIFLZWContext::outputRow() |
+bool GIFLZWContext::outputRow(GIFRow::const_iterator rowBegin) |
{ |
int drowStart = irow; |
int drowEnd = irow; |
@@ -148,7 +148,7 @@ bool GIFLZWContext::outputRow() |
return true; |
// CALLBACK: Let the client know we have decoded a row. |
- if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBuffer, m_frameContext->width(), |
+ if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameContext->width(), |
drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1)) |
return false; |
@@ -205,20 +205,11 @@ bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
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.
|
int incode; |
const unsigned char *ch; |
+ size_t width = m_frameContext->width(); |
if (rowIter == rowBuffer.end()) |
return true; |
-#define OUTPUT_ROW \ |
- do { \ |
- if (!outputRow()) \ |
- return false; \ |
- rowsRemaining--; \ |
- rowIter = rowBuffer.begin(); \ |
- if (!rowsRemaining) \ |
- return true; \ |
- } while (0) |
- |
for (ch = block; bytesInBlock-- > 0; ch++) { |
// Feed the next byte into the decoder's 32-bit input buffer. |
datum += ((int) *ch) << bits; |
@@ -249,65 +240,95 @@ bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
} |
if (oldcode == -1) { |
+ // 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.
|
+ // code in the stream or the dictionary was reset. We'll write the |
+ // 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.
|
+ firstchar = oldcode = code; |
+ if (rowIter >= rowBuffer.end()) |
+ return false; |
*rowIter++ = suffix[code]; |
- if (rowIter == rowBuffer.end()) |
- OUTPUT_ROW; |
+ } else { |
+ incode = code; |
+ unsigned short codeLength = 0; |
+ if (code < avail) { |
+ // 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.
|
+ codeLength = suffixLength[code]; |
+ rowIter += codeLength; |
+ 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.
|
+ return false; |
+ } else if (code == avail) { |
+ // This is an incomplete code. Code length is the length of previous |
+ // code plus one. Code content is that of previous code concatenated |
+ // 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.
|
+ codeLength = suffixLength[oldcode] + 1; |
+ rowIter += codeLength; |
+ if (rowIter >= rowBuffer.end()) |
+ return false; |
+ |
+ // The last character of this code is the first character of the |
+ // previous code. Write it to output and then write the previous 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.
|
+ *--rowIter = firstchar; |
+ code = oldcode; |
+ } else { |
+ // Bad code received. Complete and incomplete codes are defined up |
+ // 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.
|
+ return false; |
+ } |
- firstchar = oldcode = code; |
- continue; |
- } |
+ while (code >= clearCode) { |
+ 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
|
+ return false; |
- incode = code; |
- if (code >= avail) { |
- stack[stackp++] = firstchar; |
- code = oldcode; |
+ // Even though suffix[] only holds characters through suffix[avail - 1], |
+ // allowing code >= avail here lets us be more tolerant of malformed |
+ // data. As long as code < MAX_BYTES, the only risk is a garbled image, |
+ // which is no worse than refusing to display it. |
+ *--rowIter = suffix[code]; |
+ code = prefix[code]; |
+ } |
- if (stackp == MAX_BYTES) |
- return false; |
+ *--rowIter = firstchar = suffix[code]; |
+ |
+ // Define a new codeword in the dictionary. |
+ 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.
|
+ prefix[avail] = oldcode; |
+ suffix[avail] = firstchar; |
+ suffixLength[avail] = suffixLength[oldcode] + 1; |
+ 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.
|
+ |
+ // If we've used up all the codewords of a given length |
+ // increase the length of codewords by one bit, but don't |
+ // 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.
|
+ 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.
|
+ codesize++; |
+ codemask += avail; |
+ } |
+ } |
+ oldcode = incode; |
+ rowIter += codeLength; |
} |
- while (code >= clearCode) { |
- if (code >= MAX_BYTES || code == prefix[code]) |
- return false; |
- |
- // Even though suffix[] only holds characters through suffix[avail - 1], |
- // allowing code >= avail here lets us be more tolerant of malformed |
- // data. As long as code < MAX_BYTES, the only risk is a garbled image, |
- // which is no worse than refusing to display it. |
- stack[stackp++] = suffix[code]; |
- code = prefix[code]; |
+ // Not enough bytes to output row. |
+ if (rowIter < rowBuffer.begin() + width) |
+ 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.
|
- if (stackp == MAX_BYTES) |
+ // There's enough data to output. Output as many rows as possible. |
+ GIFRow::iterator rowBegin = rowBuffer.begin(); |
+ 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.
|
+ if (!outputRow(rowBegin)) |
return false; |
+ rowsRemaining--; |
+ if (!rowsRemaining) |
+ return true; |
} |
- stack[stackp++] = firstchar = suffix[code]; |
- |
- // Define a new codeword in the dictionary. |
- if (avail < 4096) { |
- prefix[avail] = oldcode; |
- suffix[avail] = firstchar; |
- avail++; |
- |
- // If we've used up all the codewords of a given length |
- // increase the length of codewords by one bit, but don't |
- // exceed the specified maximum codeword size of 12 bits. |
- if ((!(avail & codemask)) && (avail < 4096)) { |
- codesize++; |
- codemask += avail; |
- } |
- } |
- oldcode = incode; |
- |
- // Copy the decoded data out to the scanline buffer. |
- do { |
- *rowIter++ = stack[--stackp]; |
- if (rowIter == rowBuffer.end()) |
- OUTPUT_ROW; |
- } while (stackp > 0); |
+ // These bytes cannot make up a full row. Move them to the beginning |
+ // 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.
|
+ size_t bytesToCopy = rowIter - rowBegin; |
+ memcpy(rowBuffer.begin(), rowBegin, bytesToCopy); |
+ rowIter = rowBuffer.begin() + bytesToCopy; |
} |
} |
- |
return true; |
} |
@@ -775,17 +796,18 @@ bool GIFLZWContext::prepareToDecode() |
irow = 0; |
// Initialize output row buffer. |
- rowBuffer.resize(m_frameContext->width()); |
+ 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.
|
rowIter = rowBuffer.begin(); |
rowsRemaining = m_frameContext->height(); |
// Clearing the whole suffix table lets us be more tolerant of bad data. |
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.
|
+ for (int i = 0; i < clearCode; ++i) |
+ suffix[i] = i; |
+ for (int i = 0; i < MAX_BYTES; i++) |
+ suffixLength[i] = 1; |
// Clearing the whole prefix table to prevent uninitialized access. |
memset(prefix, 0, sizeof(prefix)); |
- for (int i = 0; i < clearCode; i++) |
- suffix[i] = i; |
- stackp = 0; |
return true; |
} |