blob: 2603807cb394d672e4859c3b40994ab7386a918c [file] [log] [blame]
scroggo19b91532016-10-24 09:03:26 -07001/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
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
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Chris Saari <saari@netscape.com>
24 * Apple Computer
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40/*
41The Graphics Interchange Format(c) is the copyright property of CompuServe
42Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
43enhance, alter, modify or change in any way the definition of the format.
44
45CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
46license for the use of the Graphics Interchange Format(sm) in computer
47software; computer software utilizing GIF(sm) must acknowledge ownership of the
48Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
49User and Technical Documentation. Computer software utilizing GIF, which is
50distributed or may be distributed without User or Technical Documentation must
51display to the screen or printer a message acknowledging ownership of the
52Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
53this case, the acknowledgement may be displayed in an opening screen or leading
54banner, or a closing screen or trailing banner. A message such as the following
55may be used:
56
57 "The Graphics Interchange Format(c) is the Copyright property of
58 CompuServe Incorporated. GIF(sm) is a Service Mark property of
59 CompuServe Incorporated."
60
61For further information, please contact :
62
63 CompuServe Incorporated
64 Graphics Technology Department
65 5000 Arlington Center Boulevard
66 Columbus, Ohio 43220
67 U. S. A.
68
69CompuServe Incorporated maintains a mailing list with all those individuals and
70organizations who wish to receive copies of this document when it is corrected
71or revised. This service is offered free of charge; please provide us with your
72mailing address.
73*/
74
scroggo3d3a65c2016-10-24 12:28:30 -070075#include "SkGifImageReader.h"
scroggo19b91532016-10-24 09:03:26 -070076#include "SkColorPriv.h"
77#include "SkGifCodec.h"
78
79#include <algorithm>
80#include <string.h>
81
82
83// GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'.
84//
85// Note, the hold will never need to be bigger than 256 bytes to gather up in the hold,
86// as each GIF block (except colormaps) can never be bigger than 256 bytes.
87// Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap.
scroggo3d3a65c2016-10-24 12:28:30 -070088// So a fixed buffer in SkGifImageReader is good enough.
scroggo19b91532016-10-24 09:03:26 -070089// This buffer is only needed to copy left-over data from one GifWrite call to the next
90#define GETN(n, s) \
91 do { \
92 m_bytesToConsume = (n); \
93 m_state = (s); \
94 } while (0)
95
96// Get a 16-bit value stored in little-endian format.
97#define GETINT16(p) ((p)[1]<<8|(p)[0])
98
99// Send the data to the display front-end.
scroggof9acbe22016-10-25 12:43:21 -0700100bool SkGIFLZWContext::outputRow(const unsigned char* rowBegin)
scroggo19b91532016-10-24 09:03:26 -0700101{
102 int drowStart = irow;
103 int drowEnd = irow;
104
105 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while
106 // displaying to diminish the "venetian-blind" effect as the image is
107 // loaded. Adjust pixel vertical positions to avoid the appearance of the
108 // image crawling up the screen as successive passes are drawn.
109 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) {
110 unsigned rowDup = 0;
111 unsigned rowShift = 0;
112
113 switch (ipass) {
114 case 1:
115 rowDup = 7;
116 rowShift = 3;
117 break;
118 case 2:
119 rowDup = 3;
120 rowShift = 1;
121 break;
122 case 3:
123 rowDup = 1;
124 rowShift = 0;
125 break;
126 default:
127 break;
128 }
129
130 drowStart -= rowShift;
131 drowEnd = drowStart + rowDup;
132
133 // Extend if bottom edge isn't covered because of the shift upward.
134 if (((m_frameContext->height() - 1) - drowEnd) <= rowShift)
135 drowEnd = m_frameContext->height() - 1;
136
137 // Clamp first and last rows to upper and lower edge of image.
138 if (drowStart < 0)
139 drowStart = 0;
140
141 if ((unsigned)drowEnd >= m_frameContext->height())
142 drowEnd = m_frameContext->height() - 1;
143 }
144
145 // Protect against too much image data.
146 if ((unsigned)drowStart >= m_frameContext->height())
147 return true;
148
149 // CALLBACK: Let the client know we have decoded a row.
Matt Sarett4ef986d2016-11-03 14:52:28 -0400150 const bool writeTransparentPixels = (SkCodec::kNone == m_frameContext->getRequiredFrame());
scroggo19b91532016-10-24 09:03:26 -0700151 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin,
scroggo1285f412016-10-26 13:48:03 -0700152 drowStart, drowEnd - drowStart + 1, writeTransparentPixels))
scroggo19b91532016-10-24 09:03:26 -0700153 return false;
154
155 if (!m_frameContext->interlaced())
156 irow++;
157 else {
158 do {
159 switch (ipass) {
160 case 1:
161 irow += 8;
162 if (irow >= m_frameContext->height()) {
163 ipass++;
164 irow = 4;
165 }
166 break;
167
168 case 2:
169 irow += 8;
170 if (irow >= m_frameContext->height()) {
171 ipass++;
172 irow = 2;
173 }
174 break;
175
176 case 3:
177 irow += 4;
178 if (irow >= m_frameContext->height()) {
179 ipass++;
180 irow = 1;
181 }
182 break;
183
184 case 4:
185 irow += 2;
186 if (irow >= m_frameContext->height()) {
187 ipass++;
188 irow = 0;
189 }
190 break;
191
192 default:
193 break;
194 }
195 } while (irow > (m_frameContext->height() - 1));
196 }
197 return true;
198}
199
200// Perform Lempel-Ziv-Welch decoding.
201// Returns true if decoding was successful. In this case the block will have been completely consumed and/or rowsRemaining will be 0.
scroggo3d3a65c2016-10-24 12:28:30 -0700202// Otherwise, decoding failed; returns false in this case, which will always cause the SkGifImageReader to set the "decode failed" flag.
scroggof9acbe22016-10-25 12:43:21 -0700203bool SkGIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
scroggo19b91532016-10-24 09:03:26 -0700204{
205 const size_t width = m_frameContext->width();
206
207 if (rowIter == rowBuffer.end())
208 return true;
209
210 for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) {
211 // Feed the next byte into the decoder's 32-bit input buffer.
212 datum += ((int) *ch) << bits;
213 bits += 8;
214
215 // Check for underflow of decoder's 32-bit input buffer.
216 while (bits >= codesize) {
217 // Get the leading variable-length symbol from the data stream.
218 int code = datum & codemask;
219 datum >>= codesize;
220 bits -= codesize;
221
222 // Reset the dictionary to its original state, if requested.
223 if (code == clearCode) {
224 codesize = m_frameContext->dataSize() + 1;
225 codemask = (1 << codesize) - 1;
226 avail = clearCode + 2;
227 oldcode = -1;
228 continue;
229 }
230
231 // Check for explicit end-of-stream code.
232 if (code == (clearCode + 1)) {
233 // end-of-stream should only appear after all image data.
234 if (!rowsRemaining)
235 return true;
236 return false;
237 }
238
239 const int tempCode = code;
240 unsigned short codeLength = 0;
241 if (code < avail) {
242 // This is a pre-existing code, so we already know what it
243 // encodes.
244 codeLength = suffixLength[code];
245 rowIter += codeLength;
246 } else if (code == avail && oldcode != -1) {
247 // This is a new code just being added to the dictionary.
248 // It must encode the contents of the previous code, plus
249 // the first character of the previous code again.
250 codeLength = suffixLength[oldcode] + 1;
251 rowIter += codeLength;
252 *--rowIter = firstchar;
253 code = oldcode;
254 } else {
255 // This is an invalid code. The dictionary is just initialized
256 // and the code is incomplete. We don't know how to handle
257 // this case.
258 return false;
259 }
260
261 while (code >= clearCode) {
262 *--rowIter = suffix[code];
263 code = prefix[code];
264 }
265
266 *--rowIter = firstchar = suffix[code];
267
268 // Define a new codeword in the dictionary as long as we've read
269 // more than one value from the stream.
scroggof9acbe22016-10-25 12:43:21 -0700270 if (avail < SK_MAX_DICTIONARY_ENTRIES && oldcode != -1) {
scroggo19b91532016-10-24 09:03:26 -0700271 prefix[avail] = oldcode;
272 suffix[avail] = firstchar;
273 suffixLength[avail] = suffixLength[oldcode] + 1;
274 ++avail;
275
276 // If we've used up all the codewords of a given length
277 // increase the length of codewords by one bit, but don't
278 // exceed the specified maximum codeword size.
scroggof9acbe22016-10-25 12:43:21 -0700279 if (!(avail & codemask) && avail < SK_MAX_DICTIONARY_ENTRIES) {
scroggo19b91532016-10-24 09:03:26 -0700280 ++codesize;
281 codemask += avail;
282 }
283 }
284 oldcode = tempCode;
285 rowIter += codeLength;
286
287 // Output as many rows as possible.
288 unsigned char* rowBegin = rowBuffer.begin();
289 for (; rowBegin + width <= rowIter; rowBegin += width) {
290 if (!outputRow(rowBegin))
291 return false;
292 rowsRemaining--;
293 if (!rowsRemaining)
294 return true;
295 }
296
297 if (rowBegin != rowBuffer.begin()) {
298 // Move the remaining bytes to the beginning of the buffer.
299 const size_t bytesToCopy = rowIter - rowBegin;
300 memcpy(&rowBuffer.front(), rowBegin, bytesToCopy);
301 rowIter = rowBuffer.begin() + bytesToCopy;
302 }
303 }
304 }
305 return true;
306}
307
Leon Scroggins III932efed2016-12-16 11:39:51 -0500308sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkColorType colorType,
309 size_t transparentPixel) const
scroggo19b91532016-10-24 09:03:26 -0700310{
311 if (!m_isDefined)
312 return nullptr;
313
314 const PackColorProc proc = choose_pack_color_proc(false, colorType);
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500315 if (m_table && proc == m_packColorProc && m_transPixel == transparentPixel) {
316 SkASSERT(transparentPixel > (unsigned) m_table->count()
317 || m_table->operator[](transparentPixel) == SK_ColorTRANSPARENT);
318 // This SkColorTable has already been built with the same transparent color and
319 // packing proc. Reuse it.
320 return m_table;
scroggo19b91532016-10-24 09:03:26 -0700321 }
322 m_packColorProc = proc;
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500323 m_transPixel = transparentPixel;
scroggo19b91532016-10-24 09:03:26 -0700324
Leon Scroggins III932efed2016-12-16 11:39:51 -0500325 const size_t bytes = m_colors * SK_BYTES_PER_COLORMAP_ENTRY;
326 sk_sp<SkData> rawData(streamBuffer->getDataAtPosition(m_position, bytes));
327 if (!rawData) {
328 return nullptr;
329 }
330
scroggof9acbe22016-10-25 12:43:21 -0700331 SkASSERT(m_colors <= SK_MAX_COLORS);
Leon Scroggins III932efed2016-12-16 11:39:51 -0500332 const uint8_t* srcColormap = rawData->bytes();
scroggof9acbe22016-10-25 12:43:21 -0700333 SkPMColor colorStorage[SK_MAX_COLORS];
scroggo19b91532016-10-24 09:03:26 -0700334 for (size_t i = 0; i < m_colors; i++) {
335 if (i == transparentPixel) {
336 colorStorage[i] = SK_ColorTRANSPARENT;
337 } else {
338 colorStorage[i] = proc(255, srcColormap[0], srcColormap[1], srcColormap[2]);
339 }
scroggof9acbe22016-10-25 12:43:21 -0700340 srcColormap += SK_BYTES_PER_COLORMAP_ENTRY;
scroggo19b91532016-10-24 09:03:26 -0700341 }
scroggof9acbe22016-10-25 12:43:21 -0700342 for (size_t i = m_colors; i < SK_MAX_COLORS; i++) {
scroggo19b91532016-10-24 09:03:26 -0700343 colorStorage[i] = SK_ColorTRANSPARENT;
344 }
scroggof9acbe22016-10-25 12:43:21 -0700345 m_table = sk_sp<SkColorTable>(new SkColorTable(colorStorage, SK_MAX_COLORS));
scroggo19b91532016-10-24 09:03:26 -0700346 return m_table;
347}
348
Leon Scroggins III932efed2016-12-16 11:39:51 -0500349sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, size_t index) {
scroggo19b91532016-10-24 09:03:26 -0700350 if (index >= m_frames.size()) {
351 return nullptr;
352 }
353
scroggof9acbe22016-10-25 12:43:21 -0700354 const SkGIFFrameContext* frameContext = m_frames[index].get();
355 const SkGIFColorMap& localColorMap = frameContext->localColorMap();
Leon Scroggins III932efed2016-12-16 11:39:51 -0500356 const size_t transPix = frameContext->transparentPixel();
scroggo19b91532016-10-24 09:03:26 -0700357 if (localColorMap.isDefined()) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500358 return localColorMap.buildTable(&m_streamBuffer, colorType, transPix);
scroggo19b91532016-10-24 09:03:26 -0700359 }
360 if (m_globalColorMap.isDefined()) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500361 return m_globalColorMap.buildTable(&m_streamBuffer, colorType, transPix);
scroggo19b91532016-10-24 09:03:26 -0700362 }
363 return nullptr;
364}
365
366// Perform decoding for this frame. frameComplete will be true if the entire frame is decoded.
scroggo3d3a65c2016-10-24 12:28:30 -0700367// Returns false if a decoding error occurred. This is a fatal error and causes the SkGifImageReader to set the "decode failed" flag.
scroggo19b91532016-10-24 09:03:26 -0700368// 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.
Leon Scroggins III932efed2016-12-16 11:39:51 -0500369bool SkGIFFrameContext::decode(SkStreamBuffer* streamBuffer, SkGifCodec* client,
370 bool* frameComplete)
scroggo19b91532016-10-24 09:03:26 -0700371{
372 *frameComplete = false;
373 if (!m_lzwContext) {
scroggof9acbe22016-10-25 12:43:21 -0700374 // Wait for more data to properly initialize SkGIFLZWContext.
scroggo19b91532016-10-24 09:03:26 -0700375 if (!isDataSizeDefined() || !isHeaderDefined())
376 return true;
377
scroggof9acbe22016-10-25 12:43:21 -0700378 m_lzwContext.reset(new SkGIFLZWContext(client, this));
Leon Scroggins III45565b62016-12-05 14:56:30 -0500379 if (!m_lzwContext->prepareToDecode()) {
scroggo19b91532016-10-24 09:03:26 -0700380 m_lzwContext.reset();
381 return false;
382 }
383
384 m_currentLzwBlock = 0;
385 }
386
387 // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode.
388 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingRows()) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500389 const auto& block = m_lzwBlocks[m_currentLzwBlock];
390 const size_t len = block.blockSize;
391
392 sk_sp<SkData> data(streamBuffer->getDataAtPosition(block.blockPosition, len));
393 if (!data) {
394 return false;
395 }
396 if (!m_lzwContext->doLZW(reinterpret_cast<const unsigned char*>(data->data()), len)) {
scroggo19b91532016-10-24 09:03:26 -0700397 return false;
398 }
399 ++m_currentLzwBlock;
400 }
401
402 // If this frame is data complete then the previous loop must have completely decoded all LZW blocks.
403 // There will be no more decoding for this frame so it's time to cleanup.
404 if (isComplete()) {
405 *frameComplete = true;
406 m_lzwContext.reset();
407 }
408 return true;
409}
410
411// Decode a frame.
scroggof9acbe22016-10-25 12:43:21 -0700412// This method uses SkGIFFrameContext:decode() to decode the frame; decoding error is reported to client as a critical failure.
scroggo19b91532016-10-24 09:03:26 -0700413// Return true if decoding has progressed. Return false if an error has occurred.
scroggo3d3a65c2016-10-24 12:28:30 -0700414bool SkGifImageReader::decode(size_t frameIndex, bool* frameComplete)
scroggo19b91532016-10-24 09:03:26 -0700415{
scroggof9acbe22016-10-25 12:43:21 -0700416 SkGIFFrameContext* currentFrame = m_frames[frameIndex].get();
scroggo19b91532016-10-24 09:03:26 -0700417
Leon Scroggins III932efed2016-12-16 11:39:51 -0500418 return currentFrame->decode(&m_streamBuffer, m_client, frameComplete);
scroggo19b91532016-10-24 09:03:26 -0700419}
420
421// Parse incoming GIF data stream into internal data structures.
422// Return true if parsing has progressed or there is not enough data.
423// Return false if a fatal error is encountered.
scroggof9acbe22016-10-25 12:43:21 -0700424bool SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
scroggo19b91532016-10-24 09:03:26 -0700425{
426 if (m_parseCompleted) {
427 return true;
428 }
429
scroggoe71b1a12016-11-01 08:28:28 -0700430 if (SkGIFLoopCountQuery == query && m_loopCount != cLoopCountNotSeen) {
431 // Loop count has already been parsed.
432 return true;
433 }
434
scroggof9acbe22016-10-25 12:43:21 -0700435 // SkGIFSizeQuery and SkGIFFrameCountQuery are negative, so this is only meaningful when >= 0.
scroggo19b91532016-10-24 09:03:26 -0700436 const int lastFrameToParse = (int) query;
437 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse
438 && m_frames[lastFrameToParse]->isComplete()) {
439 // We have already parsed this frame.
440 return true;
441 }
442
443 while (true) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500444 if (!m_streamBuffer.buffer(m_bytesToConsume)) {
445 // The stream does not yet have enough data.
scroggo19b91532016-10-24 09:03:26 -0700446 return true;
447 }
448
449 switch (m_state) {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500450 case SkGIFLZW: {
scroggo19b91532016-10-24 09:03:26 -0700451 SkASSERT(!m_frames.empty());
Leon Scroggins III932efed2016-12-16 11:39:51 -0500452 auto* frame = m_frames.back().get();
453 frame->addLzwBlock(m_streamBuffer.markPosition(), m_bytesToConsume);
scroggof9acbe22016-10-25 12:43:21 -0700454 GETN(1, SkGIFSubBlock);
scroggo19b91532016-10-24 09:03:26 -0700455 break;
Leon Scroggins III932efed2016-12-16 11:39:51 -0500456 }
scroggof9acbe22016-10-25 12:43:21 -0700457 case SkGIFLZWStart: {
scroggo19b91532016-10-24 09:03:26 -0700458 SkASSERT(!m_frames.empty());
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500459 auto* currentFrame = m_frames.back().get();
460 setRequiredFrame(currentFrame);
461
462 currentFrame->setDataSize(this->getOneByte());
scroggof9acbe22016-10-25 12:43:21 -0700463 GETN(1, SkGIFSubBlock);
scroggo19b91532016-10-24 09:03:26 -0700464 break;
465 }
466
scroggof9acbe22016-10-25 12:43:21 -0700467 case SkGIFType: {
scroggo19b91532016-10-24 09:03:26 -0700468 const char* currentComponent = m_streamBuffer.get();
469
470 // All GIF files begin with "GIF87a" or "GIF89a".
471 if (!memcmp(currentComponent, "GIF89a", 6))
472 m_version = 89;
473 else if (!memcmp(currentComponent, "GIF87a", 6))
474 m_version = 87;
475 else {
476 // This prevents attempting to continue reading this invalid stream.
scroggof9acbe22016-10-25 12:43:21 -0700477 GETN(0, SkGIFDone);
scroggo19b91532016-10-24 09:03:26 -0700478 return false;
479 }
scroggof9acbe22016-10-25 12:43:21 -0700480 GETN(7, SkGIFGlobalHeader);
scroggo19b91532016-10-24 09:03:26 -0700481 break;
482 }
483
scroggof9acbe22016-10-25 12:43:21 -0700484 case SkGIFGlobalHeader: {
scroggo19b91532016-10-24 09:03:26 -0700485 const unsigned char* currentComponent =
486 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
487
488 // This is the height and width of the "screen" or frame into which
489 // images are rendered. The individual images can be smaller than
490 // the screen size and located with an origin anywhere within the
491 // screen.
492 // Note that we don't inform the client of the size yet, as it might
493 // change after we read the first frame's image header.
494 m_screenWidth = GETINT16(currentComponent);
495 m_screenHeight = GETINT16(currentComponent + 2);
496
497 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07);
498
499 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* global map */
500 m_globalColorMap.setNumColors(globalColorMapColors);
scroggof9acbe22016-10-25 12:43:21 -0700501 GETN(SK_BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, SkGIFGlobalColormap);
scroggo19b91532016-10-24 09:03:26 -0700502 break;
503 }
504
scroggof9acbe22016-10-25 12:43:21 -0700505 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700506 break;
507 }
508
scroggof9acbe22016-10-25 12:43:21 -0700509 case SkGIFGlobalColormap: {
Leon Scroggins III932efed2016-12-16 11:39:51 -0500510 m_globalColorMap.setTablePosition(m_streamBuffer.markPosition());
scroggof9acbe22016-10-25 12:43:21 -0700511 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700512 break;
513 }
514
scroggof9acbe22016-10-25 12:43:21 -0700515 case SkGIFImageStart: {
scroggo19b91532016-10-24 09:03:26 -0700516 const char currentComponent = m_streamBuffer.get()[0];
517
518 if (currentComponent == '!') { // extension.
scroggof9acbe22016-10-25 12:43:21 -0700519 GETN(2, SkGIFExtension);
scroggo19b91532016-10-24 09:03:26 -0700520 break;
521 }
522
523 if (currentComponent == ',') { // image separator.
scroggof9acbe22016-10-25 12:43:21 -0700524 GETN(9, SkGIFImageHeader);
scroggo19b91532016-10-24 09:03:26 -0700525 break;
526 }
527
528 // If we get anything other than ',' (image separator), '!'
529 // (extension), or ';' (trailer), there is extraneous data
530 // between blocks. The GIF87a spec tells us to keep reading
531 // until we find an image separator, but GIF89a says such
532 // a file is corrupt. We follow Mozilla's implementation and
533 // proceed as if the file were correctly terminated, so the
534 // GIF will display.
scroggof9acbe22016-10-25 12:43:21 -0700535 GETN(0, SkGIFDone);
scroggo19b91532016-10-24 09:03:26 -0700536 break;
537 }
538
scroggof9acbe22016-10-25 12:43:21 -0700539 case SkGIFExtension: {
scroggo19b91532016-10-24 09:03:26 -0700540 const unsigned char* currentComponent =
541 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
542
543 size_t bytesInBlock = currentComponent[1];
scroggof9acbe22016-10-25 12:43:21 -0700544 SkGIFState exceptionState = SkGIFSkipBlock;
scroggo19b91532016-10-24 09:03:26 -0700545
546 switch (*currentComponent) {
547 case 0xf9:
scroggo19b91532016-10-24 09:03:26 -0700548 // The GIF spec mandates that the GIFControlExtension header block length is 4 bytes,
scroggof9acbe22016-10-25 12:43:21 -0700549 exceptionState = SkGIFControlExtension;
scroggo19b91532016-10-24 09:03:26 -0700550 // and the parser for this block reads 4 bytes, so we must enforce that the buffer
551 // contains at least this many bytes. If the GIF specifies a different length, we
552 // allow that, so long as it's larger; the additional data will simply be ignored.
553 bytesInBlock = std::max(bytesInBlock, static_cast<size_t>(4));
554 break;
555
556 // The GIF spec also specifies the lengths of the following two extensions' headers
557 // (as 12 and 11 bytes, respectively). Because we ignore the plain text extension entirely
558 // and sanity-check the actual length of the application extension header before reading it,
559 // we allow GIFs to deviate from these values in either direction. This is important for
560 // real-world compatibility, as GIFs in the wild exist with application extension headers
561 // that are both shorter and longer than 11 bytes.
562 case 0x01:
563 // ignoring plain text extension
564 break;
565
566 case 0xff:
scroggof9acbe22016-10-25 12:43:21 -0700567 exceptionState = SkGIFApplicationExtension;
scroggo19b91532016-10-24 09:03:26 -0700568 break;
569
570 case 0xfe:
scroggof9acbe22016-10-25 12:43:21 -0700571 exceptionState = SkGIFConsumeComment;
scroggo19b91532016-10-24 09:03:26 -0700572 break;
573 }
574
575 if (bytesInBlock)
576 GETN(bytesInBlock, exceptionState);
577 else
scroggof9acbe22016-10-25 12:43:21 -0700578 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700579 break;
580 }
581
scroggof9acbe22016-10-25 12:43:21 -0700582 case SkGIFConsumeBlock: {
scroggo19b91532016-10-24 09:03:26 -0700583 const unsigned char currentComponent = this->getOneByte();
584 if (!currentComponent)
scroggof9acbe22016-10-25 12:43:21 -0700585 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700586 else
scroggof9acbe22016-10-25 12:43:21 -0700587 GETN(currentComponent, SkGIFSkipBlock);
scroggo19b91532016-10-24 09:03:26 -0700588 break;
589 }
590
scroggof9acbe22016-10-25 12:43:21 -0700591 case SkGIFSkipBlock: {
592 GETN(1, SkGIFConsumeBlock);
scroggo19b91532016-10-24 09:03:26 -0700593 break;
594 }
595
scroggof9acbe22016-10-25 12:43:21 -0700596 case SkGIFControlExtension: {
scroggo19b91532016-10-24 09:03:26 -0700597 const unsigned char* currentComponent =
598 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
599
600 addFrameIfNecessary();
scroggof9acbe22016-10-25 12:43:21 -0700601 SkGIFFrameContext* currentFrame = m_frames.back().get();
scroggo19b91532016-10-24 09:03:26 -0700602 if (*currentComponent & 0x1)
603 currentFrame->setTransparentPixel(currentComponent[3]);
604
605 // We ignore the "user input" bit.
606
607 // NOTE: This relies on the values in the FrameDisposalMethod enum
608 // matching those in the GIF spec!
609 int rawDisposalMethod = ((*currentComponent) >> 2) & 0x7;
610 switch (rawDisposalMethod) {
611 case 1:
612 case 2:
613 case 3:
614 currentFrame->setDisposalMethod((SkCodecAnimation::DisposalMethod) rawDisposalMethod);
615 break;
616 case 4:
617 // Some specs say that disposal method 3 is "overwrite previous", others that setting
618 // the third bit of the field (i.e. method 4) is. We map both to the same value.
619 currentFrame->setDisposalMethod(SkCodecAnimation::RestorePrevious_DisposalMethod);
620 break;
621 default:
622 // Other values use the default.
623 currentFrame->setDisposalMethod(SkCodecAnimation::Keep_DisposalMethod);
624 break;
625 }
626 currentFrame->setDelayTime(GETINT16(currentComponent + 1) * 10);
scroggof9acbe22016-10-25 12:43:21 -0700627 GETN(1, SkGIFConsumeBlock);
scroggo19b91532016-10-24 09:03:26 -0700628 break;
629 }
630
scroggof9acbe22016-10-25 12:43:21 -0700631 case SkGIFCommentExtension: {
scroggo19b91532016-10-24 09:03:26 -0700632 const unsigned char currentComponent = this->getOneByte();
633 if (currentComponent)
scroggof9acbe22016-10-25 12:43:21 -0700634 GETN(currentComponent, SkGIFConsumeComment);
scroggo19b91532016-10-24 09:03:26 -0700635 else
scroggof9acbe22016-10-25 12:43:21 -0700636 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700637 break;
638 }
639
scroggof9acbe22016-10-25 12:43:21 -0700640 case SkGIFConsumeComment: {
641 GETN(1, SkGIFCommentExtension);
scroggo19b91532016-10-24 09:03:26 -0700642 break;
643 }
644
scroggof9acbe22016-10-25 12:43:21 -0700645 case SkGIFApplicationExtension: {
scroggo19b91532016-10-24 09:03:26 -0700646 // Check for netscape application extension.
Leon Scroggins III932efed2016-12-16 11:39:51 -0500647 if (m_bytesToConsume == 11) {
scroggo19b91532016-10-24 09:03:26 -0700648 const unsigned char* currentComponent =
649 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
650
651 if (!memcmp(currentComponent, "NETSCAPE2.0", 11) || !memcmp(currentComponent, "ANIMEXTS1.0", 11))
scroggof9acbe22016-10-25 12:43:21 -0700652 GETN(1, SkGIFNetscapeExtensionBlock);
scroggo19b91532016-10-24 09:03:26 -0700653 }
654
scroggof9acbe22016-10-25 12:43:21 -0700655 if (m_state != SkGIFNetscapeExtensionBlock)
656 GETN(1, SkGIFConsumeBlock);
scroggo19b91532016-10-24 09:03:26 -0700657 break;
658 }
659
660 // Netscape-specific GIF extension: animation looping.
scroggof9acbe22016-10-25 12:43:21 -0700661 case SkGIFNetscapeExtensionBlock: {
scroggo19b91532016-10-24 09:03:26 -0700662 const int currentComponent = this->getOneByte();
scroggof9acbe22016-10-25 12:43:21 -0700663 // SkGIFConsumeNetscapeExtension always reads 3 bytes from the stream; we should at least wait for this amount.
scroggo19b91532016-10-24 09:03:26 -0700664 if (currentComponent)
scroggof9acbe22016-10-25 12:43:21 -0700665 GETN(std::max(3, currentComponent), SkGIFConsumeNetscapeExtension);
scroggo19b91532016-10-24 09:03:26 -0700666 else
scroggof9acbe22016-10-25 12:43:21 -0700667 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700668 break;
669 }
670
671 // Parse netscape-specific application extensions
scroggof9acbe22016-10-25 12:43:21 -0700672 case SkGIFConsumeNetscapeExtension: {
scroggo19b91532016-10-24 09:03:26 -0700673 const unsigned char* currentComponent =
674 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
675
676 int netscapeExtension = currentComponent[0] & 7;
677
678 // Loop entire animation specified # of times. Only read the loop count during the first iteration.
679 if (netscapeExtension == 1) {
680 m_loopCount = GETINT16(currentComponent + 1);
681
682 // Zero loop count is infinite animation loop request.
683 if (!m_loopCount)
scroggoe71b1a12016-11-01 08:28:28 -0700684 m_loopCount = SkCodec::kRepetitionCountInfinite;
scroggo19b91532016-10-24 09:03:26 -0700685
scroggof9acbe22016-10-25 12:43:21 -0700686 GETN(1, SkGIFNetscapeExtensionBlock);
scroggoe71b1a12016-11-01 08:28:28 -0700687
688 if (SkGIFLoopCountQuery == query) {
689 m_streamBuffer.flush();
690 return true;
691 }
scroggo19b91532016-10-24 09:03:26 -0700692 } else if (netscapeExtension == 2) {
693 // Wait for specified # of bytes to enter buffer.
694
695 // Don't do this, this extension doesn't exist (isn't used at all)
696 // and doesn't do anything, as our streaming/buffering takes care of it all...
697 // See: http://semmix.pl/color/exgraf/eeg24.htm
scroggof9acbe22016-10-25 12:43:21 -0700698 GETN(1, SkGIFNetscapeExtensionBlock);
scroggo19b91532016-10-24 09:03:26 -0700699 } else {
700 // 0,3-7 are yet to be defined netscape extension codes
701 // This prevents attempting to continue reading this invalid stream.
scroggof9acbe22016-10-25 12:43:21 -0700702 GETN(0, SkGIFDone);
scroggo19b91532016-10-24 09:03:26 -0700703 return false;
704 }
705 break;
706 }
707
scroggof9acbe22016-10-25 12:43:21 -0700708 case SkGIFImageHeader: {
scroggo19b91532016-10-24 09:03:26 -0700709 unsigned height, width, xOffset, yOffset;
710 const unsigned char* currentComponent =
711 reinterpret_cast<const unsigned char*>(m_streamBuffer.get());
712
713 /* Get image offsets, with respect to the screen origin */
714 xOffset = GETINT16(currentComponent);
715 yOffset = GETINT16(currentComponent + 2);
716
717 /* Get image width and height. */
718 width = GETINT16(currentComponent + 4);
719 height = GETINT16(currentComponent + 6);
720
721 // Some GIF files have frames that don't fit in the specified
722 // overall image size. For the first frame, we can simply enlarge
723 // the image size to allow the frame to be visible. We can't do
724 // this on subsequent frames because the rest of the decoding
725 // infrastructure assumes the image size won't change as we
726 // continue decoding, so any subsequent frames that are even
727 // larger will be cropped.
728 // Luckily, handling just the first frame is sufficient to deal
729 // with most cases, e.g. ones where the image size is erroneously
730 // set to zero, since usually the first frame completely fills
731 // the image.
732 if (currentFrameIsFirstFrame()) {
733 m_screenHeight = std::max(m_screenHeight, yOffset + height);
734 m_screenWidth = std::max(m_screenWidth, xOffset + width);
735 }
736
737 // NOTE: Chromium placed this block after setHeaderDefined, down
738 // below we returned true when asked for the size. So Chromium
739 // created an image which would fail. Is this the correct behavior?
740 // We choose to return false early, so we will not create an
741 // SkCodec.
742
743 // Work around more broken GIF files that have zero image width or
744 // height.
745 if (!height || !width) {
746 height = m_screenHeight;
747 width = m_screenWidth;
748 if (!height || !width) {
749 // This prevents attempting to continue reading this invalid stream.
scroggof9acbe22016-10-25 12:43:21 -0700750 GETN(0, SkGIFDone);
scroggo19b91532016-10-24 09:03:26 -0700751 return false;
752 }
753 }
754
Jim Van Verth3cfdf6c2016-10-26 09:45:23 -0400755 const bool isLocalColormapDefined = SkToBool(currentComponent[8] & 0x80);
scroggo19b91532016-10-24 09:03:26 -0700756 // The three low-order bits of currentComponent[8] specify the bits per pixel.
757 const size_t numColors = 2 << (currentComponent[8] & 0x7);
758 if (currentFrameIsFirstFrame()) {
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500759 if (hasTransparentPixel(0, isLocalColormapDefined, numColors)) {
scroggo19b91532016-10-24 09:03:26 -0700760 m_firstFrameHasAlpha = true;
761 m_firstFrameSupportsIndex8 = true;
762 } else {
763 const bool frameIsSubset = xOffset > 0 || yOffset > 0
764 || xOffset + width < m_screenWidth
765 || yOffset + height < m_screenHeight;
766 m_firstFrameHasAlpha = frameIsSubset;
767 m_firstFrameSupportsIndex8 = !frameIsSubset;
768 }
769 }
770
Leon Scroggins III4993b952016-12-08 11:54:04 -0500771 addFrameIfNecessary();
772 SkGIFFrameContext* currentFrame = m_frames.back().get();
773 currentFrame->setHeaderDefined();
774
scroggof9acbe22016-10-25 12:43:21 -0700775 if (query == SkGIFSizeQuery) {
scroggo19b91532016-10-24 09:03:26 -0700776 // The decoder needs to stop, so we return here, before
777 // flushing the buffer. Next time through, we'll be in the same
778 // state, requiring the same amount in the buffer.
scroggo19b91532016-10-24 09:03:26 -0700779 return true;
780 }
781
scroggo19b91532016-10-24 09:03:26 -0700782
783 currentFrame->setRect(xOffset, yOffset, width, height);
Jim Van Verth3cfdf6c2016-10-26 09:45:23 -0400784 currentFrame->setInterlaced(SkToBool(currentComponent[8] & 0x40));
scroggo19b91532016-10-24 09:03:26 -0700785
786 // Overlaying interlaced, transparent GIFs over
787 // existing image data using the Haeberli display hack
788 // requires saving the underlying image in order to
789 // avoid jaggies at the transparency edges. We are
790 // unprepared to deal with that, so don't display such
791 // images progressively. Which means only the first
792 // frame can be progressively displayed.
793 // FIXME: It is possible that a non-transparent frame
794 // can be interlaced and progressively displayed.
795 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame());
796
797 if (isLocalColormapDefined) {
798 currentFrame->localColorMap().setNumColors(numColors);
scroggof9acbe22016-10-25 12:43:21 -0700799 GETN(SK_BYTES_PER_COLORMAP_ENTRY * numColors, SkGIFImageColormap);
scroggo19b91532016-10-24 09:03:26 -0700800 break;
801 }
802
scroggof9acbe22016-10-25 12:43:21 -0700803 GETN(1, SkGIFLZWStart);
scroggo19b91532016-10-24 09:03:26 -0700804 break;
805 }
806
scroggof9acbe22016-10-25 12:43:21 -0700807 case SkGIFImageColormap: {
scroggo19b91532016-10-24 09:03:26 -0700808 SkASSERT(!m_frames.empty());
Leon Scroggins III932efed2016-12-16 11:39:51 -0500809 auto& cmap = m_frames.back()->localColorMap();
810 cmap.setTablePosition(m_streamBuffer.markPosition());
scroggof9acbe22016-10-25 12:43:21 -0700811 GETN(1, SkGIFLZWStart);
scroggo19b91532016-10-24 09:03:26 -0700812 break;
813 }
814
scroggof9acbe22016-10-25 12:43:21 -0700815 case SkGIFSubBlock: {
scroggo19b91532016-10-24 09:03:26 -0700816 const size_t bytesInBlock = this->getOneByte();
817 if (bytesInBlock)
scroggof9acbe22016-10-25 12:43:21 -0700818 GETN(bytesInBlock, SkGIFLZW);
scroggo19b91532016-10-24 09:03:26 -0700819 else {
820 // Finished parsing one frame; Process next frame.
821 SkASSERT(!m_frames.empty());
822 // Note that some broken GIF files do not have enough LZW blocks to fully
823 // decode all rows but we treat it as frame complete.
824 m_frames.back()->setComplete();
scroggof9acbe22016-10-25 12:43:21 -0700825 GETN(1, SkGIFImageStart);
scroggo19b91532016-10-24 09:03:26 -0700826 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse) {
827 m_streamBuffer.flush();
828 return true;
829 }
830 }
831 break;
832 }
833
scroggof9acbe22016-10-25 12:43:21 -0700834 case SkGIFDone: {
scroggo19b91532016-10-24 09:03:26 -0700835 m_parseCompleted = true;
836 return true;
837 }
838
839 default:
840 // We shouldn't ever get here.
841 // This prevents attempting to continue reading this invalid stream.
scroggof9acbe22016-10-25 12:43:21 -0700842 GETN(0, SkGIFDone);
scroggo19b91532016-10-24 09:03:26 -0700843 return false;
844 break;
845 } // switch
846 m_streamBuffer.flush();
847 }
848
849 return true;
850}
851
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500852bool SkGifImageReader::hasTransparentPixel(size_t i, bool isLocalColormapDefined,
853 size_t localColors) {
854 if (m_frames.size() <= i) {
855 // This should only happen when parsing the first frame.
856 SkASSERT(0 == i);
857
858 // We did not see a Graphics Control Extension, so no transparent
859 // pixel was specified. But if there is no color table, this frame is
860 // still transparent.
861 return !isLocalColormapDefined && m_globalColorMap.numColors() == 0;
862 }
863
864 const size_t transparentPixel = m_frames[i]->transparentPixel();
865 if (isLocalColormapDefined) {
866 return transparentPixel < localColors;
867 }
868
869 const size_t globalColors = m_globalColorMap.numColors();
870 if (!globalColors) {
871 // No color table for this frame, so the frame is empty.
872 // This is technically different from having a transparent
873 // pixel, but we'll treat it the same - nothing to draw here.
874 return true;
875 }
876
877 // If there is a global color table, it will be parsed before reaching
878 // here. If its numColors is set, it will be defined.
879 SkASSERT(m_globalColorMap.isDefined());
880 return transparentPixel < globalColors;
881}
882
scroggo3d3a65c2016-10-24 12:28:30 -0700883void SkGifImageReader::addFrameIfNecessary()
scroggo19b91532016-10-24 09:03:26 -0700884{
885 if (m_frames.empty() || m_frames.back()->isComplete()) {
886 const size_t i = m_frames.size();
scroggof9acbe22016-10-25 12:43:21 -0700887 std::unique_ptr<SkGIFFrameContext> frame(new SkGIFFrameContext(i));
scroggo19b91532016-10-24 09:03:26 -0700888 m_frames.push_back(std::move(frame));
889 }
890}
891
Leon Scroggins IIIb0b625b2016-12-22 16:40:24 -0500892void SkGifImageReader::setRequiredFrame(SkGIFFrameContext* frame) {
893 const size_t i = frame->frameId();
894 if (0 == i) {
895 frame->setRequiredFrame(SkCodec::kNone);
896 return;
897 }
898
899 const SkGIFFrameContext* prevFrame = m_frames[i - 1].get();
900 if (prevFrame->getDisposalMethod() == SkCodecAnimation::RestorePrevious_DisposalMethod) {
901 frame->setRequiredFrame(prevFrame->getRequiredFrame());
902 return;
903 }
904
905 // Note: We could correct these after decoding - i.e. some frames may turn out to be
906 // independent if they do not use the transparent pixel, but that would require
907 // checking whether each pixel used the transparent pixel.
908 const SkGIFColorMap& localMap = frame->localColorMap();
909 const bool transValid = hasTransparentPixel(i, localMap.isDefined(), localMap.numColors());
910
911 const SkIRect prevFrameRect = prevFrame->frameRect();
912 const bool frameCoversPriorFrame = frame->frameRect().contains(prevFrameRect);
913
914 if (!transValid && frameCoversPriorFrame) {
915 frame->setRequiredFrame(prevFrame->getRequiredFrame());
916 return;
917 }
918
919 switch (prevFrame->getDisposalMethod()) {
920 case SkCodecAnimation::Keep_DisposalMethod:
921 frame->setRequiredFrame(i - 1);
922 break;
923 case SkCodecAnimation::RestorePrevious_DisposalMethod:
924 // This was already handled above.
925 SkASSERT(false);
926 break;
927 case SkCodecAnimation::RestoreBGColor_DisposalMethod:
928 // If the prior frame covers the whole image
929 if (prevFrameRect == SkIRect::MakeWH(m_screenWidth, m_screenHeight)
930 // Or the prior frame was independent
931 || prevFrame->getRequiredFrame() == SkCodec::kNone)
932 {
933 // This frame is independent, since we clear everything in the
934 // prior frame to the BG color
935 frame->setRequiredFrame(SkCodec::kNone);
936 } else {
937 frame->setRequiredFrame(i - 1);
938 }
939 break;
940 }
941}
942
scroggo19b91532016-10-24 09:03:26 -0700943// FIXME: Move this method to close to doLZW().
Leon Scroggins III45565b62016-12-05 14:56:30 -0500944bool SkGIFLZWContext::prepareToDecode()
scroggo19b91532016-10-24 09:03:26 -0700945{
946 SkASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefined());
947
948 // Since we use a codesize of 1 more than the datasize, we need to ensure
scroggof9acbe22016-10-25 12:43:21 -0700949 // that our datasize is strictly less than the SK_MAX_DICTIONARY_ENTRY_BITS.
950 if (m_frameContext->dataSize() >= SK_MAX_DICTIONARY_ENTRY_BITS)
scroggo19b91532016-10-24 09:03:26 -0700951 return false;
952 clearCode = 1 << m_frameContext->dataSize();
953 avail = clearCode + 2;
954 oldcode = -1;
955 codesize = m_frameContext->dataSize() + 1;
956 codemask = (1 << codesize) - 1;
957 datum = bits = 0;
958 ipass = m_frameContext->interlaced() ? 1 : 0;
959 irow = 0;
960
961 // We want to know the longest sequence encodable by a dictionary with
scroggof9acbe22016-10-25 12:43:21 -0700962 // SK_MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base
scroggo19b91532016-10-24 09:03:26 -0700963 // values themselves at the beginning of the dictionary, as well as the need
964 // for a clear code or a termination code, we could use every entry to
965 // encode a series of multiple values. If the input value stream looked
966 // like "AAAAA..." (a long string of just one value), the first dictionary
967 // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus
scroggof9acbe22016-10-25 12:43:21 -0700968 // the longest sequence would be SK_MAX_DICTIONARY_ENTRIES + 1 values.
scroggo19b91532016-10-24 09:03:26 -0700969 //
970 // However, we have to account for reserved entries. The first |datasize|
971 // bits are reserved for the base values, and the next two entries are
972 // reserved for the clear code and termination code. In theory a GIF can
973 // set the datasize to 0, meaning we have just two reserved entries, making
scroggof9acbe22016-10-25 12:43:21 -0700974 // the longest sequence (SK_MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since
scroggo19b91532016-10-24 09:03:26 -0700975 // each value is a byte, this is also the number of bytes in the longest
976 // encodable sequence.
scroggof9acbe22016-10-25 12:43:21 -0700977 const size_t maxBytes = SK_MAX_DICTIONARY_ENTRIES - 1;
scroggo19b91532016-10-24 09:03:26 -0700978
979 // Now allocate the output buffer. We decode directly into this buffer
980 // until we have at least one row worth of data, then call outputRow().
981 // This means worst case we may have (row width - 1) bytes in the buffer
982 // and then decode a sequence |maxBytes| long to append.
983 rowBuffer.reset(m_frameContext->width() - 1 + maxBytes);
984 rowIter = rowBuffer.begin();
985 rowsRemaining = m_frameContext->height();
986
987 // Clearing the whole suffix table lets us be more tolerant of bad data.
988 for (int i = 0; i < clearCode; ++i) {
989 suffix[i] = i;
990 suffixLength[i] = 1;
991 }
992 return true;
993}
994