| 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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 | 344 |
| 345 // If this frame is data complete then the previous loop must have completel
y decoded all LZW blocks. | 345 // If this frame is data complete then the previous loop must have completel
y decoded all LZW blocks. |
| 346 // There will be no more decoding for this frame so it's time to cleanup. | 346 // There will be no more decoding for this frame so it's time to cleanup. |
| 347 if (isComplete()) { | 347 if (isComplete()) { |
| 348 *frameDecoded = true; | 348 *frameDecoded = true; |
| 349 m_lzwContext.clear(); | 349 m_lzwContext.clear(); |
| 350 } | 350 } |
| 351 return true; | 351 return true; |
| 352 } | 352 } |
| 353 | 353 |
| 354 // Decode all frames before haltAtFrame. | 354 // Decode a frame. |
| 355 // This method uses GIFFrameContext:decode() to decode each frame; decoding erro
r is reported to client as a critical failure. | 355 // This method uses GIFFrameContext:decode() to decode the frame; decoding error
is reported to client as a critical failure. |
| 356 // Return true if decoding has progressed. Return false if an error has occurred
. | 356 // Return true if decoding has progressed. Return false if an error has occurred
. |
| 357 bool GIFImageReader::decode(GIFImageDecoder::GIFQuery query, unsigned haltAtFram
e) | 357 bool GIFImageReader::decode(size_t frameIndex) |
| 358 { |
| 359 bool frameDecoded = false; |
| 360 GIFFrameContext* currentFrame = m_frames[frameIndex].get(); |
| 361 |
| 362 return currentFrame->decode(data(0), m_data->size(), m_client, &frameDecoded
) |
| 363 && (!frameDecoded || m_client->frameComplete(frameIndex)); |
| 364 } |
| 365 |
| 366 bool GIFImageReader::parse(GIFImageDecoder::GIFParseQuery query) |
| 358 { | 367 { |
| 359 ASSERT(m_bytesRead <= m_data->size()); | 368 ASSERT(m_bytesRead <= m_data->size()); |
| 360 | 369 |
| 361 if (!parse(m_bytesRead, m_data->size() - m_bytesRead, query == GIFImageDecod
er::GIFSizeQuery)) | 370 return parseData(m_bytesRead, m_data->size() - m_bytesRead, query); |
| 362 return false; | |
| 363 | |
| 364 if (query != GIFImageDecoder::GIFFullQuery) | |
| 365 return true; | |
| 366 | |
| 367 while (m_currentDecodingFrame < std::min(m_frames.size(), static_cast<size_t
>(haltAtFrame))) { | |
| 368 bool frameDecoded = false; | |
| 369 GIFFrameContext* currentFrame = m_frames[m_currentDecodingFrame].get(); | |
| 370 | |
| 371 if (!currentFrame->decode(data(0), m_data->size(), m_client, &frameDecod
ed)) | |
| 372 return false; | |
| 373 | |
| 374 // We need more data to continue decoding. | |
| 375 if (!frameDecoded) | |
| 376 break; | |
| 377 | |
| 378 if (!m_client->frameComplete(m_currentDecodingFrame, currentFrame->delay
Time, currentFrame->disposalMethod)) | |
| 379 return false; | |
| 380 ++m_currentDecodingFrame; | |
| 381 } | |
| 382 | |
| 383 // All frames decoded. | |
| 384 if (m_currentDecodingFrame == m_frames.size() && m_parseCompleted) | |
| 385 m_client->gifComplete(); | |
| 386 return true; | |
| 387 } | 371 } |
| 388 | 372 |
| 389 // Parse incoming GIF data stream into internal data structures. | 373 // Parse incoming GIF data stream into internal data structures. |
| 390 // Return true if parsing has progressed or there is not enough data. | 374 // Return true if parsing has progressed or there is not enough data. |
| 391 // Return false if a fatal error is encountered. | 375 // Return false if a fatal error is encountered. |
| 392 bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly) | 376 bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder:
:GIFParseQuery query) |
| 393 { | 377 { |
| 394 if (!len) { | 378 if (!len) { |
| 395 // No new data has come in since the last call, just ignore this call. | 379 // No new data has come in since the last call, just ignore this call. |
| 396 return true; | 380 return true; |
| 397 } | 381 } |
| 398 | 382 |
| 399 if (len < m_bytesToConsume) | 383 if (len < m_bytesToConsume) |
| 400 return true; | 384 return true; |
| 401 | 385 |
| 402 // This loop reads as many components from |m_data| as possible. | 386 // This loop reads as many components from |m_data| as possible. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // individual images can be smaller than the screen size and located
with an origin anywhere | 427 // individual images can be smaller than the screen size and located
with an origin anywhere |
| 444 // within the screen. | 428 // within the screen. |
| 445 m_screenWidth = GETINT16(currentComponent); | 429 m_screenWidth = GETINT16(currentComponent); |
| 446 m_screenHeight = GETINT16(currentComponent + 2); | 430 m_screenHeight = GETINT16(currentComponent + 2); |
| 447 | 431 |
| 448 // CALLBACK: Inform the decoderplugin of our size. | 432 // CALLBACK: Inform the decoderplugin of our size. |
| 449 // Note: A subsequent frame might have dimensions larger than the "s
creen" dimensions. | 433 // Note: A subsequent frame might have dimensions larger than the "s
creen" dimensions. |
| 450 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) | 434 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) |
| 451 return false; | 435 return false; |
| 452 | 436 |
| 453 m_screenBgcolor = currentComponent[5]; | |
| 454 m_globalColormapSize = 2 << (currentComponent[4] & 0x07); | 437 m_globalColormapSize = 2 << (currentComponent[4] & 0x07); |
| 455 | 438 |
| 456 if ((currentComponent[4] & 0x80) && m_globalColormapSize > 0) { /* g
lobal map */ | 439 if ((currentComponent[4] & 0x80) && m_globalColormapSize > 0) { /* g
lobal map */ |
| 457 // Get the global colormap | 440 // Get the global colormap |
| 458 const size_t globalColormapBytes = 3 * m_globalColormapSize; | 441 const size_t globalColormapBytes = 3 * m_globalColormapSize; |
| 459 m_globalColormapPosition = dataPosition; | 442 m_globalColormapPosition = dataPosition; |
| 460 | 443 |
| 461 if (len < globalColormapBytes) { | 444 if (len < globalColormapBytes) { |
| 462 // Wait until we have enough bytes to consume the entire col
ormap at once. | 445 // Wait until we have enough bytes to consume the entire col
ormap at once. |
| 463 GETN(globalColormapBytes, GIFGlobalColormap); | 446 GETN(globalColormapBytes, GIFGlobalColormap); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 } | 651 } |
| 669 | 652 |
| 670 // Work around more broken GIF files that have zero image width or h
eight | 653 // Work around more broken GIF files that have zero image width or h
eight |
| 671 if (!height || !width) { | 654 if (!height || !width) { |
| 672 height = m_screenHeight; | 655 height = m_screenHeight; |
| 673 width = m_screenWidth; | 656 width = m_screenWidth; |
| 674 if (!height || !width) | 657 if (!height || !width) |
| 675 return false; | 658 return false; |
| 676 } | 659 } |
| 677 | 660 |
| 678 if (parseSizeOnly) { | 661 if (query == GIFImageDecoder::GIFSizeQuery) { |
| 679 // The decoder needs to stop. Hand back the number of bytes we c
onsumed from | 662 // The decoder needs to stop. Hand back the number of bytes we c
onsumed from |
| 680 // buffer minus 9 (the amount we consumed to read the header). | 663 // buffer minus 9 (the amount we consumed to read the header). |
| 681 setRemainingBytes(len + 9); | 664 setRemainingBytes(len + 9); |
| 682 GETN(9, GIFImageHeader); | 665 GETN(9, GIFImageHeader); |
| 683 return true; | 666 return true; |
| 684 } | 667 } |
| 685 | 668 |
| 686 addFrameIfNecessary(); | 669 addFrameIfNecessary(); |
| 687 GIFFrameContext* currentFrame = m_frames.last().get(); | 670 GIFFrameContext* currentFrame = m_frames.last().get(); |
| 688 | 671 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 rowPosition = 0; | 798 rowPosition = 0; |
| 816 rowsRemaining = m_frameContext->height; | 799 rowsRemaining = m_frameContext->height; |
| 817 | 800 |
| 818 // Clearing the whole suffix table lets us be more tolerant of bad data. | 801 // Clearing the whole suffix table lets us be more tolerant of bad data. |
| 819 suffix.fill(0); | 802 suffix.fill(0); |
| 820 for (int i = 0; i < clearCode; i++) | 803 for (int i = 0; i < clearCode; i++) |
| 821 suffix[i] = i; | 804 suffix[i] = i; |
| 822 stackp = 0; | 805 stackp = 0; |
| 823 return true; | 806 return true; |
| 824 } | 807 } |
| OLD | NEW |