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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 #define GETN(n, s) \ | 90 #define GETN(n, s) \ |
91 do { \ | 91 do { \ |
92 m_bytesToConsume = (n); \ | 92 m_bytesToConsume = (n); \ |
93 m_state = (s); \ | 93 m_state = (s); \ |
94 } while (0) | 94 } while (0) |
95 | 95 |
96 // Get a 16-bit value stored in little-endian format. | 96 // Get a 16-bit value stored in little-endian format. |
97 #define GETINT16(p) ((p)[1]<<8|(p)[0]) | 97 #define GETINT16(p) ((p)[1]<<8|(p)[0]) |
98 | 98 |
99 // Send the data to the display front-end. | 99 // Send the data to the display front-end. |
100 bool GIFLZWContext::outputRow(const unsigned char* rowBegin) | 100 bool SkGIFLZWContext::outputRow(const unsigned char* rowBegin) |
101 { | 101 { |
102 int drowStart = irow; | 102 int drowStart = irow; |
103 int drowEnd = irow; | 103 int drowEnd = irow; |
104 | 104 |
105 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while | 105 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while |
106 // displaying to diminish the "venetian-blind" effect as the image is | 106 // displaying to diminish the "venetian-blind" effect as the image is |
107 // loaded. Adjust pixel vertical positions to avoid the appearance of the | 107 // loaded. Adjust pixel vertical positions to avoid the appearance of the |
108 // image crawling up the screen as successive passes are drawn. | 108 // image crawling up the screen as successive passes are drawn. |
109 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() &&
ipass < 4) { | 109 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() &&
ipass < 4) { |
110 unsigned rowDup = 0; | 110 unsigned rowDup = 0; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 break; | 192 break; |
193 } | 193 } |
194 } while (irow > (m_frameContext->height() - 1)); | 194 } while (irow > (m_frameContext->height() - 1)); |
195 } | 195 } |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
199 // Perform Lempel-Ziv-Welch decoding. | 199 // Perform Lempel-Ziv-Welch decoding. |
200 // Returns true if decoding was successful. In this case the block will have bee
n completely consumed and/or rowsRemaining will be 0. | 200 // Returns true if decoding was successful. In this case the block will have bee
n completely consumed and/or rowsRemaining will be 0. |
201 // Otherwise, decoding failed; returns false in this case, which will always cau
se the SkGifImageReader to set the "decode failed" flag. | 201 // Otherwise, decoding failed; returns false in this case, which will always cau
se the SkGifImageReader to set the "decode failed" flag. |
202 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) | 202 bool SkGIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock) |
203 { | 203 { |
204 const size_t width = m_frameContext->width(); | 204 const size_t width = m_frameContext->width(); |
205 | 205 |
206 if (rowIter == rowBuffer.end()) | 206 if (rowIter == rowBuffer.end()) |
207 return true; | 207 return true; |
208 | 208 |
209 for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) { | 209 for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) { |
210 // Feed the next byte into the decoder's 32-bit input buffer. | 210 // Feed the next byte into the decoder's 32-bit input buffer. |
211 datum += ((int) *ch) << bits; | 211 datum += ((int) *ch) << bits; |
212 bits += 8; | 212 bits += 8; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 | 259 |
260 while (code >= clearCode) { | 260 while (code >= clearCode) { |
261 *--rowIter = suffix[code]; | 261 *--rowIter = suffix[code]; |
262 code = prefix[code]; | 262 code = prefix[code]; |
263 } | 263 } |
264 | 264 |
265 *--rowIter = firstchar = suffix[code]; | 265 *--rowIter = firstchar = suffix[code]; |
266 | 266 |
267 // Define a new codeword in the dictionary as long as we've read | 267 // Define a new codeword in the dictionary as long as we've read |
268 // more than one value from the stream. | 268 // more than one value from the stream. |
269 if (avail < MAX_DICTIONARY_ENTRIES && oldcode != -1) { | 269 if (avail < SK_MAX_DICTIONARY_ENTRIES && oldcode != -1) { |
270 prefix[avail] = oldcode; | 270 prefix[avail] = oldcode; |
271 suffix[avail] = firstchar; | 271 suffix[avail] = firstchar; |
272 suffixLength[avail] = suffixLength[oldcode] + 1; | 272 suffixLength[avail] = suffixLength[oldcode] + 1; |
273 ++avail; | 273 ++avail; |
274 | 274 |
275 // If we've used up all the codewords of a given length | 275 // If we've used up all the codewords of a given length |
276 // increase the length of codewords by one bit, but don't | 276 // increase the length of codewords by one bit, but don't |
277 // exceed the specified maximum codeword size. | 277 // exceed the specified maximum codeword size. |
278 if (!(avail & codemask) && avail < MAX_DICTIONARY_ENTRIES) { | 278 if (!(avail & codemask) && avail < SK_MAX_DICTIONARY_ENTRIES) { |
279 ++codesize; | 279 ++codesize; |
280 codemask += avail; | 280 codemask += avail; |
281 } | 281 } |
282 } | 282 } |
283 oldcode = tempCode; | 283 oldcode = tempCode; |
284 rowIter += codeLength; | 284 rowIter += codeLength; |
285 | 285 |
286 // Output as many rows as possible. | 286 // Output as many rows as possible. |
287 unsigned char* rowBegin = rowBuffer.begin(); | 287 unsigned char* rowBegin = rowBuffer.begin(); |
288 for (; rowBegin + width <= rowIter; rowBegin += width) { | 288 for (; rowBegin + width <= rowIter; rowBegin += width) { |
289 if (!outputRow(rowBegin)) | 289 if (!outputRow(rowBegin)) |
290 return false; | 290 return false; |
291 rowsRemaining--; | 291 rowsRemaining--; |
292 if (!rowsRemaining) | 292 if (!rowsRemaining) |
293 return true; | 293 return true; |
294 } | 294 } |
295 | 295 |
296 if (rowBegin != rowBuffer.begin()) { | 296 if (rowBegin != rowBuffer.begin()) { |
297 // Move the remaining bytes to the beginning of the buffer. | 297 // Move the remaining bytes to the beginning of the buffer. |
298 const size_t bytesToCopy = rowIter - rowBegin; | 298 const size_t bytesToCopy = rowIter - rowBegin; |
299 memcpy(&rowBuffer.front(), rowBegin, bytesToCopy); | 299 memcpy(&rowBuffer.front(), rowBegin, bytesToCopy); |
300 rowIter = rowBuffer.begin() + bytesToCopy; | 300 rowIter = rowBuffer.begin() + bytesToCopy; |
301 } | 301 } |
302 } | 302 } |
303 } | 303 } |
304 return true; | 304 return true; |
305 } | 305 } |
306 | 306 |
307 sk_sp<SkColorTable> GIFColorMap::buildTable(SkColorType colorType, size_t transp
arentPixel) const | 307 sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkColorType colorType, size_t tran
sparentPixel) const |
308 { | 308 { |
309 if (!m_isDefined) | 309 if (!m_isDefined) |
310 return nullptr; | 310 return nullptr; |
311 | 311 |
312 const PackColorProc proc = choose_pack_color_proc(false, colorType); | 312 const PackColorProc proc = choose_pack_color_proc(false, colorType); |
313 if (m_table) { | 313 if (m_table) { |
314 if (transparentPixel > (unsigned) m_table->count() | 314 if (transparentPixel > (unsigned) m_table->count() |
315 || m_table->operator[](transparentPixel) == SK_ColorTRANSPARENT)
{ | 315 || m_table->operator[](transparentPixel) == SK_ColorTRANSPARENT)
{ |
316 if (proc == m_packColorProc) { | 316 if (proc == m_packColorProc) { |
317 // This SkColorTable has already been built with the same transp
arent color and | 317 // This SkColorTable has already been built with the same transp
arent color and |
318 // packing proc. Reuse it. | 318 // packing proc. Reuse it. |
319 return m_table; | 319 return m_table; |
320 } | 320 } |
321 } | 321 } |
322 } | 322 } |
323 m_packColorProc = proc; | 323 m_packColorProc = proc; |
324 | 324 |
325 SkASSERT(m_colors <= MAX_COLORS); | 325 SkASSERT(m_colors <= SK_MAX_COLORS); |
326 const uint8_t* srcColormap = m_rawData->bytes(); | 326 const uint8_t* srcColormap = m_rawData->bytes(); |
327 SkPMColor colorStorage[MAX_COLORS]; | 327 SkPMColor colorStorage[SK_MAX_COLORS]; |
328 for (size_t i = 0; i < m_colors; i++) { | 328 for (size_t i = 0; i < m_colors; i++) { |
329 if (i == transparentPixel) { | 329 if (i == transparentPixel) { |
330 colorStorage[i] = SK_ColorTRANSPARENT; | 330 colorStorage[i] = SK_ColorTRANSPARENT; |
331 } else { | 331 } else { |
332 colorStorage[i] = proc(255, srcColormap[0], srcColormap[1], srcColor
map[2]); | 332 colorStorage[i] = proc(255, srcColormap[0], srcColormap[1], srcColor
map[2]); |
333 } | 333 } |
334 srcColormap += BYTES_PER_COLORMAP_ENTRY; | 334 srcColormap += SK_BYTES_PER_COLORMAP_ENTRY; |
335 } | 335 } |
336 for (size_t i = m_colors; i < MAX_COLORS; i++) { | 336 for (size_t i = m_colors; i < SK_MAX_COLORS; i++) { |
337 colorStorage[i] = SK_ColorTRANSPARENT; | 337 colorStorage[i] = SK_ColorTRANSPARENT; |
338 } | 338 } |
339 m_table = sk_sp<SkColorTable>(new SkColorTable(colorStorage, MAX_COLORS)); | 339 m_table = sk_sp<SkColorTable>(new SkColorTable(colorStorage, SK_MAX_COLORS))
; |
340 return m_table; | 340 return m_table; |
341 } | 341 } |
342 | 342 |
343 sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, size_
t index) const { | 343 sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, size_
t index) const { |
344 if (index >= m_frames.size()) { | 344 if (index >= m_frames.size()) { |
345 return nullptr; | 345 return nullptr; |
346 } | 346 } |
347 | 347 |
348 const GIFFrameContext* frameContext = m_frames[index].get(); | 348 const SkGIFFrameContext* frameContext = m_frames[index].get(); |
349 const GIFColorMap& localColorMap = frameContext->localColorMap(); | 349 const SkGIFColorMap& localColorMap = frameContext->localColorMap(); |
350 if (localColorMap.isDefined()) { | 350 if (localColorMap.isDefined()) { |
351 return localColorMap.buildTable(colorType, frameContext->transparentPixe
l()); | 351 return localColorMap.buildTable(colorType, frameContext->transparentPixe
l()); |
352 } | 352 } |
353 if (m_globalColorMap.isDefined()) { | 353 if (m_globalColorMap.isDefined()) { |
354 return m_globalColorMap.buildTable(colorType, frameContext->transparentP
ixel()); | 354 return m_globalColorMap.buildTable(colorType, frameContext->transparentP
ixel()); |
355 } | 355 } |
356 return nullptr; | 356 return nullptr; |
357 } | 357 } |
358 | 358 |
359 // Perform decoding for this frame. frameComplete will be true if the entire fra
me is decoded. | 359 // Perform decoding for this frame. frameComplete will be true if the entire fra
me is decoded. |
360 // Returns false if a decoding error occurred. This is a fatal error and causes
the SkGifImageReader to set the "decode failed" flag. | 360 // Returns false if a decoding error occurred. This is a fatal error and causes
the SkGifImageReader to set the "decode failed" flag. |
361 // 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. | 361 // 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. |
362 bool GIFFrameContext::decode(SkGifCodec* client, bool* frameComplete) | 362 bool SkGIFFrameContext::decode(SkGifCodec* client, bool* frameComplete) |
363 { | 363 { |
364 *frameComplete = false; | 364 *frameComplete = false; |
365 if (!m_lzwContext) { | 365 if (!m_lzwContext) { |
366 // Wait for more data to properly initialize GIFLZWContext. | 366 // Wait for more data to properly initialize SkGIFLZWContext. |
367 if (!isDataSizeDefined() || !isHeaderDefined()) | 367 if (!isDataSizeDefined() || !isHeaderDefined()) |
368 return true; | 368 return true; |
369 | 369 |
370 m_lzwContext.reset(new GIFLZWContext(client, this)); | 370 m_lzwContext.reset(new SkGIFLZWContext(client, this)); |
371 if (!m_lzwContext->prepareToDecode()) { | 371 if (!m_lzwContext->prepareToDecode()) { |
372 m_lzwContext.reset(); | 372 m_lzwContext.reset(); |
373 return false; | 373 return false; |
374 } | 374 } |
375 | 375 |
376 m_currentLzwBlock = 0; | 376 m_currentLzwBlock = 0; |
377 } | 377 } |
378 | 378 |
379 // Some bad GIFs have extra blocks beyond the last row, which we don't want
to decode. | 379 // Some bad GIFs have extra blocks beyond the last row, which we don't want
to decode. |
380 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingR
ows()) { | 380 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingR
ows()) { |
381 if (!m_lzwContext->doLZW(reinterpret_cast<const unsigned char*>(m_lzwBlo
cks[m_currentLzwBlock]->data()), | 381 if (!m_lzwContext->doLZW(reinterpret_cast<const unsigned char*>(m_lzwBlo
cks[m_currentLzwBlock]->data()), |
382 m_lzwBlo
cks[m_currentLzwBlock]->size())) { | 382 m_lzwBlo
cks[m_currentLzwBlock]->size())) { |
383 return false; | 383 return false; |
384 } | 384 } |
385 ++m_currentLzwBlock; | 385 ++m_currentLzwBlock; |
386 } | 386 } |
387 | 387 |
388 // If this frame is data complete then the previous loop must have completel
y decoded all LZW blocks. | 388 // If this frame is data complete then the previous loop must have completel
y decoded all LZW blocks. |
389 // There will be no more decoding for this frame so it's time to cleanup. | 389 // There will be no more decoding for this frame so it's time to cleanup. |
390 if (isComplete()) { | 390 if (isComplete()) { |
391 *frameComplete = true; | 391 *frameComplete = true; |
392 m_lzwContext.reset(); | 392 m_lzwContext.reset(); |
393 } | 393 } |
394 return true; | 394 return true; |
395 } | 395 } |
396 | 396 |
397 // Decode a frame. | 397 // Decode a frame. |
398 // This method uses GIFFrameContext:decode() to decode the frame; decoding error
is reported to client as a critical failure. | 398 // This method uses SkGIFFrameContext:decode() to decode the frame; decoding err
or is reported to client as a critical failure. |
399 // Return true if decoding has progressed. Return false if an error has occurred
. | 399 // Return true if decoding has progressed. Return false if an error has occurred
. |
400 bool SkGifImageReader::decode(size_t frameIndex, bool* frameComplete) | 400 bool SkGifImageReader::decode(size_t frameIndex, bool* frameComplete) |
401 { | 401 { |
402 GIFFrameContext* currentFrame = m_frames[frameIndex].get(); | 402 SkGIFFrameContext* currentFrame = m_frames[frameIndex].get(); |
403 | 403 |
404 return currentFrame->decode(m_client, frameComplete); | 404 return currentFrame->decode(m_client, frameComplete); |
405 } | 405 } |
406 | 406 |
407 // Parse incoming GIF data stream into internal data structures. | 407 // Parse incoming GIF data stream into internal data structures. |
408 // Return true if parsing has progressed or there is not enough data. | 408 // Return true if parsing has progressed or there is not enough data. |
409 // Return false if a fatal error is encountered. | 409 // Return false if a fatal error is encountered. |
410 bool SkGifImageReader::parse(SkGifImageReader::GIFParseQuery query) | 410 bool SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query) |
411 { | 411 { |
412 if (m_parseCompleted) { | 412 if (m_parseCompleted) { |
413 return true; | 413 return true; |
414 } | 414 } |
415 | 415 |
416 // GIFSizeQuery and GIFFrameCountQuery are negative, so this is only meaning
ful when >= 0. | 416 // SkGIFSizeQuery and SkGIFFrameCountQuery are negative, so this is only mea
ningful when >= 0. |
417 const int lastFrameToParse = (int) query; | 417 const int lastFrameToParse = (int) query; |
418 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse | 418 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameToParse |
419 && m_frames[lastFrameToParse]->isComplete()) { | 419 && m_frames[lastFrameToParse]->isComplete()) { |
420 // We have already parsed this frame. | 420 // We have already parsed this frame. |
421 return true; | 421 return true; |
422 } | 422 } |
423 | 423 |
424 while (true) { | 424 while (true) { |
425 const size_t bytesBuffered = m_streamBuffer.buffer(m_bytesToConsume); | 425 const size_t bytesBuffered = m_streamBuffer.buffer(m_bytesToConsume); |
426 if (bytesBuffered < m_bytesToConsume) { | 426 if (bytesBuffered < m_bytesToConsume) { |
427 // The stream does not yet have enough data. Mark that we need less
next time around, | 427 // The stream does not yet have enough data. Mark that we need less
next time around, |
428 // and return. | 428 // and return. |
429 m_bytesToConsume -= bytesBuffered; | 429 m_bytesToConsume -= bytesBuffered; |
430 return true; | 430 return true; |
431 } | 431 } |
432 | 432 |
433 switch (m_state) { | 433 switch (m_state) { |
434 case GIFLZW: | 434 case SkGIFLZW: |
435 SkASSERT(!m_frames.empty()); | 435 SkASSERT(!m_frames.empty()); |
436 // FIXME: All this copying might be wasteful for e.g. SkMemoryStream | 436 // FIXME: All this copying might be wasteful for e.g. SkMemoryStream |
437 m_frames.back()->addLzwBlock(m_streamBuffer.get(), m_streamBuffer.by
tesBuffered()); | 437 m_frames.back()->addLzwBlock(m_streamBuffer.get(), m_streamBuffer.by
tesBuffered()); |
438 GETN(1, GIFSubBlock); | 438 GETN(1, SkGIFSubBlock); |
439 break; | 439 break; |
440 | 440 |
441 case GIFLZWStart: { | 441 case SkGIFLZWStart: { |
442 SkASSERT(!m_frames.empty()); | 442 SkASSERT(!m_frames.empty()); |
443 m_frames.back()->setDataSize(this->getOneByte()); | 443 m_frames.back()->setDataSize(this->getOneByte()); |
444 GETN(1, GIFSubBlock); | 444 GETN(1, SkGIFSubBlock); |
445 break; | 445 break; |
446 } | 446 } |
447 | 447 |
448 case GIFType: { | 448 case SkGIFType: { |
449 const char* currentComponent = m_streamBuffer.get(); | 449 const char* currentComponent = m_streamBuffer.get(); |
450 | 450 |
451 // All GIF files begin with "GIF87a" or "GIF89a". | 451 // All GIF files begin with "GIF87a" or "GIF89a". |
452 if (!memcmp(currentComponent, "GIF89a", 6)) | 452 if (!memcmp(currentComponent, "GIF89a", 6)) |
453 m_version = 89; | 453 m_version = 89; |
454 else if (!memcmp(currentComponent, "GIF87a", 6)) | 454 else if (!memcmp(currentComponent, "GIF87a", 6)) |
455 m_version = 87; | 455 m_version = 87; |
456 else { | 456 else { |
457 // This prevents attempting to continue reading this invalid str
eam. | 457 // This prevents attempting to continue reading this invalid str
eam. |
458 GETN(0, GIFDone); | 458 GETN(0, SkGIFDone); |
459 return false; | 459 return false; |
460 } | 460 } |
461 GETN(7, GIFGlobalHeader); | 461 GETN(7, SkGIFGlobalHeader); |
462 break; | 462 break; |
463 } | 463 } |
464 | 464 |
465 case GIFGlobalHeader: { | 465 case SkGIFGlobalHeader: { |
466 const unsigned char* currentComponent = | 466 const unsigned char* currentComponent = |
467 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); | 467 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); |
468 | 468 |
469 // This is the height and width of the "screen" or frame into which | 469 // This is the height and width of the "screen" or frame into which |
470 // images are rendered. The individual images can be smaller than | 470 // images are rendered. The individual images can be smaller than |
471 // the screen size and located with an origin anywhere within the | 471 // the screen size and located with an origin anywhere within the |
472 // screen. | 472 // screen. |
473 // Note that we don't inform the client of the size yet, as it might | 473 // Note that we don't inform the client of the size yet, as it might |
474 // change after we read the first frame's image header. | 474 // change after we read the first frame's image header. |
475 m_screenWidth = GETINT16(currentComponent); | 475 m_screenWidth = GETINT16(currentComponent); |
476 m_screenHeight = GETINT16(currentComponent + 2); | 476 m_screenHeight = GETINT16(currentComponent + 2); |
477 | 477 |
478 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07
); | 478 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07
); |
479 | 479 |
480 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g
lobal map */ | 480 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g
lobal map */ |
481 m_globalColorMap.setNumColors(globalColorMapColors); | 481 m_globalColorMap.setNumColors(globalColorMapColors); |
482 GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalC
olormap); | 482 GETN(SK_BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, SkGIFGl
obalColormap); |
483 break; | 483 break; |
484 } | 484 } |
485 | 485 |
486 GETN(1, GIFImageStart); | 486 GETN(1, SkGIFImageStart); |
487 break; | 487 break; |
488 } | 488 } |
489 | 489 |
490 case GIFGlobalColormap: { | 490 case SkGIFGlobalColormap: { |
491 m_globalColorMap.setRawData(m_streamBuffer.get(), m_streamBuffer.byt
esBuffered()); | 491 m_globalColorMap.setRawData(m_streamBuffer.get(), m_streamBuffer.byt
esBuffered()); |
492 GETN(1, GIFImageStart); | 492 GETN(1, SkGIFImageStart); |
493 break; | 493 break; |
494 } | 494 } |
495 | 495 |
496 case GIFImageStart: { | 496 case SkGIFImageStart: { |
497 const char currentComponent = m_streamBuffer.get()[0]; | 497 const char currentComponent = m_streamBuffer.get()[0]; |
498 | 498 |
499 if (currentComponent == '!') { // extension. | 499 if (currentComponent == '!') { // extension. |
500 GETN(2, GIFExtension); | 500 GETN(2, SkGIFExtension); |
501 break; | 501 break; |
502 } | 502 } |
503 | 503 |
504 if (currentComponent == ',') { // image separator. | 504 if (currentComponent == ',') { // image separator. |
505 GETN(9, GIFImageHeader); | 505 GETN(9, SkGIFImageHeader); |
506 break; | 506 break; |
507 } | 507 } |
508 | 508 |
509 // If we get anything other than ',' (image separator), '!' | 509 // If we get anything other than ',' (image separator), '!' |
510 // (extension), or ';' (trailer), there is extraneous data | 510 // (extension), or ';' (trailer), there is extraneous data |
511 // between blocks. The GIF87a spec tells us to keep reading | 511 // between blocks. The GIF87a spec tells us to keep reading |
512 // until we find an image separator, but GIF89a says such | 512 // until we find an image separator, but GIF89a says such |
513 // a file is corrupt. We follow Mozilla's implementation and | 513 // a file is corrupt. We follow Mozilla's implementation and |
514 // proceed as if the file were correctly terminated, so the | 514 // proceed as if the file were correctly terminated, so the |
515 // GIF will display. | 515 // GIF will display. |
516 GETN(0, GIFDone); | 516 GETN(0, SkGIFDone); |
517 break; | 517 break; |
518 } | 518 } |
519 | 519 |
520 case GIFExtension: { | 520 case SkGIFExtension: { |
521 const unsigned char* currentComponent = | 521 const unsigned char* currentComponent = |
522 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); | 522 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); |
523 | 523 |
524 size_t bytesInBlock = currentComponent[1]; | 524 size_t bytesInBlock = currentComponent[1]; |
525 GIFState exceptionState = GIFSkipBlock; | 525 SkGIFState exceptionState = SkGIFSkipBlock; |
526 | 526 |
527 switch (*currentComponent) { | 527 switch (*currentComponent) { |
528 case 0xf9: | 528 case 0xf9: |
529 exceptionState = GIFControlExtension; | |
530 // The GIF spec mandates that the GIFControlExtension header blo
ck length is 4 bytes, | 529 // The GIF spec mandates that the GIFControlExtension header blo
ck length is 4 bytes, |
| 530 exceptionState = SkGIFControlExtension; |
531 // and the parser for this block reads 4 bytes, so we must enfor
ce that the buffer | 531 // and the parser for this block reads 4 bytes, so we must enfor
ce that the buffer |
532 // contains at least this many bytes. If the GIF specifies a dif
ferent length, we | 532 // contains at least this many bytes. If the GIF specifies a dif
ferent length, we |
533 // allow that, so long as it's larger; the additional data will
simply be ignored. | 533 // allow that, so long as it's larger; the additional data will
simply be ignored. |
534 bytesInBlock = std::max(bytesInBlock, static_cast<size_t>(4)); | 534 bytesInBlock = std::max(bytesInBlock, static_cast<size_t>(4)); |
535 break; | 535 break; |
536 | 536 |
537 // The GIF spec also specifies the lengths of the following two exte
nsions' headers | 537 // The GIF spec also specifies the lengths of the following two exte
nsions' headers |
538 // (as 12 and 11 bytes, respectively). Because we ignore the plain t
ext extension entirely | 538 // (as 12 and 11 bytes, respectively). Because we ignore the plain t
ext extension entirely |
539 // and sanity-check the actual length of the application extension h
eader before reading it, | 539 // and sanity-check the actual length of the application extension h
eader before reading it, |
540 // we allow GIFs to deviate from these values in either direction. T
his is important for | 540 // we allow GIFs to deviate from these values in either direction. T
his is important for |
541 // real-world compatibility, as GIFs in the wild exist with applicat
ion extension headers | 541 // real-world compatibility, as GIFs in the wild exist with applicat
ion extension headers |
542 // that are both shorter and longer than 11 bytes. | 542 // that are both shorter and longer than 11 bytes. |
543 case 0x01: | 543 case 0x01: |
544 // ignoring plain text extension | 544 // ignoring plain text extension |
545 break; | 545 break; |
546 | 546 |
547 case 0xff: | 547 case 0xff: |
548 exceptionState = GIFApplicationExtension; | 548 exceptionState = SkGIFApplicationExtension; |
549 break; | 549 break; |
550 | 550 |
551 case 0xfe: | 551 case 0xfe: |
552 exceptionState = GIFConsumeComment; | 552 exceptionState = SkGIFConsumeComment; |
553 break; | 553 break; |
554 } | 554 } |
555 | 555 |
556 if (bytesInBlock) | 556 if (bytesInBlock) |
557 GETN(bytesInBlock, exceptionState); | 557 GETN(bytesInBlock, exceptionState); |
558 else | 558 else |
559 GETN(1, GIFImageStart); | 559 GETN(1, SkGIFImageStart); |
560 break; | 560 break; |
561 } | 561 } |
562 | 562 |
563 case GIFConsumeBlock: { | 563 case SkGIFConsumeBlock: { |
564 const unsigned char currentComponent = this->getOneByte(); | 564 const unsigned char currentComponent = this->getOneByte(); |
565 if (!currentComponent) | 565 if (!currentComponent) |
566 GETN(1, GIFImageStart); | 566 GETN(1, SkGIFImageStart); |
567 else | 567 else |
568 GETN(currentComponent, GIFSkipBlock); | 568 GETN(currentComponent, SkGIFSkipBlock); |
569 break; | 569 break; |
570 } | 570 } |
571 | 571 |
572 case GIFSkipBlock: { | 572 case SkGIFSkipBlock: { |
573 GETN(1, GIFConsumeBlock); | 573 GETN(1, SkGIFConsumeBlock); |
574 break; | 574 break; |
575 } | 575 } |
576 | 576 |
577 case GIFControlExtension: { | 577 case SkGIFControlExtension: { |
578 const unsigned char* currentComponent = | 578 const unsigned char* currentComponent = |
579 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); | 579 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); |
580 | 580 |
581 addFrameIfNecessary(); | 581 addFrameIfNecessary(); |
582 GIFFrameContext* currentFrame = m_frames.back().get(); | 582 SkGIFFrameContext* currentFrame = m_frames.back().get(); |
583 if (*currentComponent & 0x1) | 583 if (*currentComponent & 0x1) |
584 currentFrame->setTransparentPixel(currentComponent[3]); | 584 currentFrame->setTransparentPixel(currentComponent[3]); |
585 | 585 |
586 // We ignore the "user input" bit. | 586 // We ignore the "user input" bit. |
587 | 587 |
588 // NOTE: This relies on the values in the FrameDisposalMethod enum | 588 // NOTE: This relies on the values in the FrameDisposalMethod enum |
589 // matching those in the GIF spec! | 589 // matching those in the GIF spec! |
590 int rawDisposalMethod = ((*currentComponent) >> 2) & 0x7; | 590 int rawDisposalMethod = ((*currentComponent) >> 2) & 0x7; |
591 switch (rawDisposalMethod) { | 591 switch (rawDisposalMethod) { |
592 case 1: | 592 case 1: |
593 case 2: | 593 case 2: |
594 case 3: | 594 case 3: |
595 currentFrame->setDisposalMethod((SkCodecAnimation::DisposalMetho
d) rawDisposalMethod); | 595 currentFrame->setDisposalMethod((SkCodecAnimation::DisposalMetho
d) rawDisposalMethod); |
596 break; | 596 break; |
597 case 4: | 597 case 4: |
598 // Some specs say that disposal method 3 is "overwrite previous"
, others that setting | 598 // Some specs say that disposal method 3 is "overwrite previous"
, others that setting |
599 // the third bit of the field (i.e. method 4) is. We map both to
the same value. | 599 // the third bit of the field (i.e. method 4) is. We map both to
the same value. |
600 currentFrame->setDisposalMethod(SkCodecAnimation::RestorePreviou
s_DisposalMethod); | 600 currentFrame->setDisposalMethod(SkCodecAnimation::RestorePreviou
s_DisposalMethod); |
601 break; | 601 break; |
602 default: | 602 default: |
603 // Other values use the default. | 603 // Other values use the default. |
604 currentFrame->setDisposalMethod(SkCodecAnimation::Keep_DisposalM
ethod); | 604 currentFrame->setDisposalMethod(SkCodecAnimation::Keep_DisposalM
ethod); |
605 break; | 605 break; |
606 } | 606 } |
607 currentFrame->setDelayTime(GETINT16(currentComponent + 1) * 10); | 607 currentFrame->setDelayTime(GETINT16(currentComponent + 1) * 10); |
608 GETN(1, GIFConsumeBlock); | 608 GETN(1, SkGIFConsumeBlock); |
609 break; | 609 break; |
610 } | 610 } |
611 | 611 |
612 case GIFCommentExtension: { | 612 case SkGIFCommentExtension: { |
613 const unsigned char currentComponent = this->getOneByte(); | 613 const unsigned char currentComponent = this->getOneByte(); |
614 if (currentComponent) | 614 if (currentComponent) |
615 GETN(currentComponent, GIFConsumeComment); | 615 GETN(currentComponent, SkGIFConsumeComment); |
616 else | 616 else |
617 GETN(1, GIFImageStart); | 617 GETN(1, SkGIFImageStart); |
618 break; | 618 break; |
619 } | 619 } |
620 | 620 |
621 case GIFConsumeComment: { | 621 case SkGIFConsumeComment: { |
622 GETN(1, GIFCommentExtension); | 622 GETN(1, SkGIFCommentExtension); |
623 break; | 623 break; |
624 } | 624 } |
625 | 625 |
626 case GIFApplicationExtension: { | 626 case SkGIFApplicationExtension: { |
627 // Check for netscape application extension. | 627 // Check for netscape application extension. |
628 if (m_streamBuffer.bytesBuffered() == 11) { | 628 if (m_streamBuffer.bytesBuffered() == 11) { |
629 const unsigned char* currentComponent = | 629 const unsigned char* currentComponent = |
630 reinterpret_cast<const unsigned char*>(m_streamBuffer.get())
; | 630 reinterpret_cast<const unsigned char*>(m_streamBuffer.get())
; |
631 | 631 |
632 if (!memcmp(currentComponent, "NETSCAPE2.0", 11) || !memcmp(curr
entComponent, "ANIMEXTS1.0", 11)) | 632 if (!memcmp(currentComponent, "NETSCAPE2.0", 11) || !memcmp(curr
entComponent, "ANIMEXTS1.0", 11)) |
633 GETN(1, GIFNetscapeExtensionBlock); | 633 GETN(1, SkGIFNetscapeExtensionBlock); |
634 } | 634 } |
635 | 635 |
636 if (m_state != GIFNetscapeExtensionBlock) | 636 if (m_state != SkGIFNetscapeExtensionBlock) |
637 GETN(1, GIFConsumeBlock); | 637 GETN(1, SkGIFConsumeBlock); |
638 break; | 638 break; |
639 } | 639 } |
640 | 640 |
641 // Netscape-specific GIF extension: animation looping. | 641 // Netscape-specific GIF extension: animation looping. |
642 case GIFNetscapeExtensionBlock: { | 642 case SkGIFNetscapeExtensionBlock: { |
643 const int currentComponent = this->getOneByte(); | 643 const int currentComponent = this->getOneByte(); |
644 // GIFConsumeNetscapeExtension always reads 3 bytes from the stream;
we should at least wait for this amount. | 644 // SkGIFConsumeNetscapeExtension always reads 3 bytes from the strea
m; we should at least wait for this amount. |
645 if (currentComponent) | 645 if (currentComponent) |
646 GETN(std::max(3, currentComponent), GIFConsumeNetscapeExtension)
; | 646 GETN(std::max(3, currentComponent), SkGIFConsumeNetscapeExtensio
n); |
647 else | 647 else |
648 GETN(1, GIFImageStart); | 648 GETN(1, SkGIFImageStart); |
649 break; | 649 break; |
650 } | 650 } |
651 | 651 |
652 // Parse netscape-specific application extensions | 652 // Parse netscape-specific application extensions |
653 case GIFConsumeNetscapeExtension: { | 653 case SkGIFConsumeNetscapeExtension: { |
654 const unsigned char* currentComponent = | 654 const unsigned char* currentComponent = |
655 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); | 655 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); |
656 | 656 |
657 int netscapeExtension = currentComponent[0] & 7; | 657 int netscapeExtension = currentComponent[0] & 7; |
658 | 658 |
659 // Loop entire animation specified # of times. Only read the loop co
unt during the first iteration. | 659 // Loop entire animation specified # of times. Only read the loop co
unt during the first iteration. |
660 if (netscapeExtension == 1) { | 660 if (netscapeExtension == 1) { |
661 m_loopCount = GETINT16(currentComponent + 1); | 661 m_loopCount = GETINT16(currentComponent + 1); |
662 | 662 |
663 // Zero loop count is infinite animation loop request. | 663 // Zero loop count is infinite animation loop request. |
664 if (!m_loopCount) | 664 if (!m_loopCount) |
665 m_loopCount = SkCodecAnimation::kAnimationLoopInfinite; | 665 m_loopCount = SkCodecAnimation::kAnimationLoopInfinite; |
666 | 666 |
667 GETN(1, GIFNetscapeExtensionBlock); | 667 GETN(1, SkGIFNetscapeExtensionBlock); |
668 } else if (netscapeExtension == 2) { | 668 } else if (netscapeExtension == 2) { |
669 // Wait for specified # of bytes to enter buffer. | 669 // Wait for specified # of bytes to enter buffer. |
670 | 670 |
671 // Don't do this, this extension doesn't exist (isn't used at al
l) | 671 // Don't do this, this extension doesn't exist (isn't used at al
l) |
672 // and doesn't do anything, as our streaming/buffering takes car
e of it all... | 672 // and doesn't do anything, as our streaming/buffering takes car
e of it all... |
673 // See: http://semmix.pl/color/exgraf/eeg24.htm | 673 // See: http://semmix.pl/color/exgraf/eeg24.htm |
674 GETN(1, GIFNetscapeExtensionBlock); | 674 GETN(1, SkGIFNetscapeExtensionBlock); |
675 } else { | 675 } else { |
676 // 0,3-7 are yet to be defined netscape extension codes | 676 // 0,3-7 are yet to be defined netscape extension codes |
677 // This prevents attempting to continue reading this invalid str
eam. | 677 // This prevents attempting to continue reading this invalid str
eam. |
678 GETN(0, GIFDone); | 678 GETN(0, SkGIFDone); |
679 return false; | 679 return false; |
680 } | 680 } |
681 break; | 681 break; |
682 } | 682 } |
683 | 683 |
684 case GIFImageHeader: { | 684 case SkGIFImageHeader: { |
685 unsigned height, width, xOffset, yOffset; | 685 unsigned height, width, xOffset, yOffset; |
686 const unsigned char* currentComponent = | 686 const unsigned char* currentComponent = |
687 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); | 687 reinterpret_cast<const unsigned char*>(m_streamBuffer.get()); |
688 | 688 |
689 /* Get image offsets, with respect to the screen origin */ | 689 /* Get image offsets, with respect to the screen origin */ |
690 xOffset = GETINT16(currentComponent); | 690 xOffset = GETINT16(currentComponent); |
691 yOffset = GETINT16(currentComponent + 2); | 691 yOffset = GETINT16(currentComponent + 2); |
692 | 692 |
693 /* Get image width and height. */ | 693 /* Get image width and height. */ |
694 width = GETINT16(currentComponent + 4); | 694 width = GETINT16(currentComponent + 4); |
(...skipping 21 matching lines...) Expand all Loading... |
716 // We choose to return false early, so we will not create an | 716 // We choose to return false early, so we will not create an |
717 // SkCodec. | 717 // SkCodec. |
718 | 718 |
719 // Work around more broken GIF files that have zero image width or | 719 // Work around more broken GIF files that have zero image width or |
720 // height. | 720 // height. |
721 if (!height || !width) { | 721 if (!height || !width) { |
722 height = m_screenHeight; | 722 height = m_screenHeight; |
723 width = m_screenWidth; | 723 width = m_screenWidth; |
724 if (!height || !width) { | 724 if (!height || !width) { |
725 // This prevents attempting to continue reading this invalid
stream. | 725 // This prevents attempting to continue reading this invalid
stream. |
726 GETN(0, GIFDone); | 726 GETN(0, SkGIFDone); |
727 return false; | 727 return false; |
728 } | 728 } |
729 } | 729 } |
730 | 730 |
731 const bool isLocalColormapDefined = currentComponent[8] & 0x80; | 731 const bool isLocalColormapDefined = currentComponent[8] & 0x80; |
732 // The three low-order bits of currentComponent[8] specify the bits
per pixel. | 732 // The three low-order bits of currentComponent[8] specify the bits
per pixel. |
733 const size_t numColors = 2 << (currentComponent[8] & 0x7); | 733 const size_t numColors = 2 << (currentComponent[8] & 0x7); |
734 if (currentFrameIsFirstFrame()) { | 734 if (currentFrameIsFirstFrame()) { |
735 bool hasTransparentPixel; | 735 bool hasTransparentPixel; |
736 if (m_frames.size() == 0) { | 736 if (m_frames.size() == 0) { |
(...skipping 24 matching lines...) Expand all Loading... |
761 m_firstFrameSupportsIndex8 = true; | 761 m_firstFrameSupportsIndex8 = true; |
762 } else { | 762 } else { |
763 const bool frameIsSubset = xOffset > 0 || yOffset > 0 | 763 const bool frameIsSubset = xOffset > 0 || yOffset > 0 |
764 || xOffset + width < m_screenWidth | 764 || xOffset + width < m_screenWidth |
765 || yOffset + height < m_screenHeight; | 765 || yOffset + height < m_screenHeight; |
766 m_firstFrameHasAlpha = frameIsSubset; | 766 m_firstFrameHasAlpha = frameIsSubset; |
767 m_firstFrameSupportsIndex8 = !frameIsSubset; | 767 m_firstFrameSupportsIndex8 = !frameIsSubset; |
768 } | 768 } |
769 } | 769 } |
770 | 770 |
771 if (query == GIFSizeQuery) { | 771 if (query == SkGIFSizeQuery) { |
772 // The decoder needs to stop, so we return here, before | 772 // The decoder needs to stop, so we return here, before |
773 // flushing the buffer. Next time through, we'll be in the same | 773 // flushing the buffer. Next time through, we'll be in the same |
774 // state, requiring the same amount in the buffer. | 774 // state, requiring the same amount in the buffer. |
775 m_bytesToConsume = 0; | 775 m_bytesToConsume = 0; |
776 return true; | 776 return true; |
777 } | 777 } |
778 | 778 |
779 addFrameIfNecessary(); | 779 addFrameIfNecessary(); |
780 GIFFrameContext* currentFrame = m_frames.back().get(); | 780 SkGIFFrameContext* currentFrame = m_frames.back().get(); |
781 | 781 |
782 currentFrame->setHeaderDefined(); | 782 currentFrame->setHeaderDefined(); |
783 | 783 |
784 currentFrame->setRect(xOffset, yOffset, width, height); | 784 currentFrame->setRect(xOffset, yOffset, width, height); |
785 currentFrame->setInterlaced(currentComponent[8] & 0x40); | 785 currentFrame->setInterlaced(currentComponent[8] & 0x40); |
786 | 786 |
787 // Overlaying interlaced, transparent GIFs over | 787 // Overlaying interlaced, transparent GIFs over |
788 // existing image data using the Haeberli display hack | 788 // existing image data using the Haeberli display hack |
789 // requires saving the underlying image in order to | 789 // requires saving the underlying image in order to |
790 // avoid jaggies at the transparency edges. We are | 790 // avoid jaggies at the transparency edges. We are |
791 // unprepared to deal with that, so don't display such | 791 // unprepared to deal with that, so don't display such |
792 // images progressively. Which means only the first | 792 // images progressively. Which means only the first |
793 // frame can be progressively displayed. | 793 // frame can be progressively displayed. |
794 // FIXME: It is possible that a non-transparent frame | 794 // FIXME: It is possible that a non-transparent frame |
795 // can be interlaced and progressively displayed. | 795 // can be interlaced and progressively displayed. |
796 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame()); | 796 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame()); |
797 | 797 |
798 if (isLocalColormapDefined) { | 798 if (isLocalColormapDefined) { |
799 currentFrame->localColorMap().setNumColors(numColors); | 799 currentFrame->localColorMap().setNumColors(numColors); |
800 GETN(BYTES_PER_COLORMAP_ENTRY * numColors, GIFImageColormap); | 800 GETN(SK_BYTES_PER_COLORMAP_ENTRY * numColors, SkGIFImageColormap
); |
801 break; | 801 break; |
802 } | 802 } |
803 | 803 |
804 GETN(1, GIFLZWStart); | 804 GETN(1, SkGIFLZWStart); |
805 break; | 805 break; |
806 } | 806 } |
807 | 807 |
808 case GIFImageColormap: { | 808 case SkGIFImageColormap: { |
809 SkASSERT(!m_frames.empty()); | 809 SkASSERT(!m_frames.empty()); |
810 m_frames.back()->localColorMap().setRawData(m_streamBuffer.get(), m_
streamBuffer.bytesBuffered()); | 810 m_frames.back()->localColorMap().setRawData(m_streamBuffer.get(), m_
streamBuffer.bytesBuffered()); |
811 GETN(1, GIFLZWStart); | 811 GETN(1, SkGIFLZWStart); |
812 break; | 812 break; |
813 } | 813 } |
814 | 814 |
815 case GIFSubBlock: { | 815 case SkGIFSubBlock: { |
816 const size_t bytesInBlock = this->getOneByte(); | 816 const size_t bytesInBlock = this->getOneByte(); |
817 if (bytesInBlock) | 817 if (bytesInBlock) |
818 GETN(bytesInBlock, GIFLZW); | 818 GETN(bytesInBlock, SkGIFLZW); |
819 else { | 819 else { |
820 // Finished parsing one frame; Process next frame. | 820 // Finished parsing one frame; Process next frame. |
821 SkASSERT(!m_frames.empty()); | 821 SkASSERT(!m_frames.empty()); |
822 // Note that some broken GIF files do not have enough LZW blocks
to fully | 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. | 823 // decode all rows but we treat it as frame complete. |
824 m_frames.back()->setComplete(); | 824 m_frames.back()->setComplete(); |
825 GETN(1, GIFImageStart); | 825 GETN(1, SkGIFImageStart); |
826 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameTo
Parse) { | 826 if (lastFrameToParse >= 0 && (int) m_frames.size() > lastFrameTo
Parse) { |
827 m_streamBuffer.flush(); | 827 m_streamBuffer.flush(); |
828 return true; | 828 return true; |
829 } | 829 } |
830 } | 830 } |
831 break; | 831 break; |
832 } | 832 } |
833 | 833 |
834 case GIFDone: { | 834 case SkGIFDone: { |
835 m_parseCompleted = true; | 835 m_parseCompleted = true; |
836 return true; | 836 return true; |
837 } | 837 } |
838 | 838 |
839 default: | 839 default: |
840 // We shouldn't ever get here. | 840 // We shouldn't ever get here. |
841 // This prevents attempting to continue reading this invalid stream. | 841 // This prevents attempting to continue reading this invalid stream. |
842 GETN(0, GIFDone); | 842 GETN(0, SkGIFDone); |
843 return false; | 843 return false; |
844 break; | 844 break; |
845 } // switch | 845 } // switch |
846 m_streamBuffer.flush(); | 846 m_streamBuffer.flush(); |
847 } | 847 } |
848 | 848 |
849 return true; | 849 return true; |
850 } | 850 } |
851 | 851 |
852 void SkGifImageReader::addFrameIfNecessary() | 852 void SkGifImageReader::addFrameIfNecessary() |
853 { | 853 { |
854 if (m_frames.empty() || m_frames.back()->isComplete()) { | 854 if (m_frames.empty() || m_frames.back()->isComplete()) { |
855 const size_t i = m_frames.size(); | 855 const size_t i = m_frames.size(); |
856 std::unique_ptr<GIFFrameContext> frame(new GIFFrameContext(i)); | 856 std::unique_ptr<SkGIFFrameContext> frame(new SkGIFFrameContext(i)); |
857 if (0 == i) { | 857 if (0 == i) { |
858 frame->setRequiredFrame(SkCodec::kNone); | 858 frame->setRequiredFrame(SkCodec::kNone); |
859 } else { | 859 } else { |
860 // FIXME: We could correct these after decoding (i.e. some frames ma
y turn out to be | 860 // FIXME: We could correct these after decoding (i.e. some frames ma
y turn out to be |
861 // independent although we did not determine that here). | 861 // independent although we did not determine that here). |
862 const GIFFrameContext* prevFrameContext = m_frames[i - 1].get(); | 862 const SkGIFFrameContext* prevFrameContext = m_frames[i - 1].get(); |
863 switch (prevFrameContext->getDisposalMethod()) { | 863 switch (prevFrameContext->getDisposalMethod()) { |
864 case SkCodecAnimation::Keep_DisposalMethod: | 864 case SkCodecAnimation::Keep_DisposalMethod: |
865 frame->setRequiredFrame(i - 1); | 865 frame->setRequiredFrame(i - 1); |
866 break; | 866 break; |
867 case SkCodecAnimation::RestorePrevious_DisposalMethod: | 867 case SkCodecAnimation::RestorePrevious_DisposalMethod: |
868 frame->setRequiredFrame(prevFrameContext->getRequiredFrame()
); | 868 frame->setRequiredFrame(prevFrameContext->getRequiredFrame()
); |
869 break; | 869 break; |
870 case SkCodecAnimation::RestoreBGColor_DisposalMethod: | 870 case SkCodecAnimation::RestoreBGColor_DisposalMethod: |
871 // If the prior frame covers the whole image | 871 // If the prior frame covers the whole image |
872 if (prevFrameContext->frameRect() == SkIRect::MakeWH(m_scree
nWidth, | 872 if (prevFrameContext->frameRect() == SkIRect::MakeWH(m_scree
nWidth, |
873 m_scree
nHeight) | 873 m_scree
nHeight) |
874 // Or the prior frame was independent | 874 // Or the prior frame was independent |
875 || prevFrameContext->getRequiredFrame() == SkCodec::
kNone) | 875 || prevFrameContext->getRequiredFrame() == SkCodec::
kNone) |
876 { | 876 { |
877 // This frame is independent, since we clear everything | 877 // This frame is independent, since we clear everything |
878 // prior frame to the BG color | 878 // prior frame to the BG color |
879 frame->setRequiredFrame(SkCodec::kNone); | 879 frame->setRequiredFrame(SkCodec::kNone); |
880 } else { | 880 } else { |
881 frame->setRequiredFrame(i - 1); | 881 frame->setRequiredFrame(i - 1); |
882 } | 882 } |
883 break; | 883 break; |
884 } | 884 } |
885 } | 885 } |
886 m_frames.push_back(std::move(frame)); | 886 m_frames.push_back(std::move(frame)); |
887 } | 887 } |
888 } | 888 } |
889 | 889 |
890 // FIXME: Move this method to close to doLZW(). | 890 // FIXME: Move this method to close to doLZW(). |
891 bool GIFLZWContext::prepareToDecode() | 891 bool SkGIFLZWContext::prepareToDecode() |
892 { | 892 { |
893 SkASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefi
ned()); | 893 SkASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefi
ned()); |
894 | 894 |
895 // Since we use a codesize of 1 more than the datasize, we need to ensure | 895 // Since we use a codesize of 1 more than the datasize, we need to ensure |
896 // that our datasize is strictly less than the MAX_DICTIONARY_ENTRY_BITS. | 896 // that our datasize is strictly less than the SK_MAX_DICTIONARY_ENTRY_BITS. |
897 if (m_frameContext->dataSize() >= MAX_DICTIONARY_ENTRY_BITS) | 897 if (m_frameContext->dataSize() >= SK_MAX_DICTIONARY_ENTRY_BITS) |
898 return false; | 898 return false; |
899 clearCode = 1 << m_frameContext->dataSize(); | 899 clearCode = 1 << m_frameContext->dataSize(); |
900 avail = clearCode + 2; | 900 avail = clearCode + 2; |
901 oldcode = -1; | 901 oldcode = -1; |
902 codesize = m_frameContext->dataSize() + 1; | 902 codesize = m_frameContext->dataSize() + 1; |
903 codemask = (1 << codesize) - 1; | 903 codemask = (1 << codesize) - 1; |
904 datum = bits = 0; | 904 datum = bits = 0; |
905 ipass = m_frameContext->interlaced() ? 1 : 0; | 905 ipass = m_frameContext->interlaced() ? 1 : 0; |
906 irow = 0; | 906 irow = 0; |
907 | 907 |
908 // We want to know the longest sequence encodable by a dictionary with | 908 // We want to know the longest sequence encodable by a dictionary with |
909 // MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base | 909 // SK_MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the ba
se |
910 // values themselves at the beginning of the dictionary, as well as the need | 910 // values themselves at the beginning of the dictionary, as well as the need |
911 // for a clear code or a termination code, we could use every entry to | 911 // for a clear code or a termination code, we could use every entry to |
912 // encode a series of multiple values. If the input value stream looked | 912 // encode a series of multiple values. If the input value stream looked |
913 // like "AAAAA..." (a long string of just one value), the first dictionary | 913 // like "AAAAA..." (a long string of just one value), the first dictionary |
914 // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus | 914 // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus |
915 // the longest sequence would be MAX_DICTIONARY_ENTRIES + 1 values. | 915 // the longest sequence would be SK_MAX_DICTIONARY_ENTRIES + 1 values. |
916 // | 916 // |
917 // However, we have to account for reserved entries. The first |datasize| | 917 // However, we have to account for reserved entries. The first |datasize| |
918 // bits are reserved for the base values, and the next two entries are | 918 // bits are reserved for the base values, and the next two entries are |
919 // reserved for the clear code and termination code. In theory a GIF can | 919 // reserved for the clear code and termination code. In theory a GIF can |
920 // set the datasize to 0, meaning we have just two reserved entries, making | 920 // set the datasize to 0, meaning we have just two reserved entries, making |
921 // the longest sequence (MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since | 921 // the longest sequence (SK_MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Sin
ce |
922 // each value is a byte, this is also the number of bytes in the longest | 922 // each value is a byte, this is also the number of bytes in the longest |
923 // encodable sequence. | 923 // encodable sequence. |
924 const size_t maxBytes = MAX_DICTIONARY_ENTRIES - 1; | 924 const size_t maxBytes = SK_MAX_DICTIONARY_ENTRIES - 1; |
925 | 925 |
926 // Now allocate the output buffer. We decode directly into this buffer | 926 // Now allocate the output buffer. We decode directly into this buffer |
927 // until we have at least one row worth of data, then call outputRow(). | 927 // until we have at least one row worth of data, then call outputRow(). |
928 // This means worst case we may have (row width - 1) bytes in the buffer | 928 // This means worst case we may have (row width - 1) bytes in the buffer |
929 // and then decode a sequence |maxBytes| long to append. | 929 // and then decode a sequence |maxBytes| long to append. |
930 rowBuffer.reset(m_frameContext->width() - 1 + maxBytes); | 930 rowBuffer.reset(m_frameContext->width() - 1 + maxBytes); |
931 rowIter = rowBuffer.begin(); | 931 rowIter = rowBuffer.begin(); |
932 rowsRemaining = m_frameContext->height(); | 932 rowsRemaining = m_frameContext->height(); |
933 | 933 |
934 // Clearing the whole suffix table lets us be more tolerant of bad data. | 934 // Clearing the whole suffix table lets us be more tolerant of bad data. |
935 for (int i = 0; i < clearCode; ++i) { | 935 for (int i = 0; i < clearCode; ++i) { |
936 suffix[i] = i; | 936 suffix[i] = i; |
937 suffixLength[i] = 1; | 937 suffixLength[i] = 1; |
938 } | 938 } |
939 return true; | 939 return true; |
940 } | 940 } |
941 | 941 |
OLD | NEW |