| 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 |