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 |