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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 5000 Arlington Center Boulevard | 65 5000 Arlington Center Boulevard |
66 Columbus, Ohio 43220 | 66 Columbus, Ohio 43220 |
67 U. S. A. | 67 U. S. A. |
68 | 68 |
69 CompuServe Incorporated maintains a mailing list with all those individuals and | 69 CompuServe Incorporated maintains a mailing list with all those individuals and |
70 organizations who wish to receive copies of this document when it is corrected | 70 organizations who wish to receive copies of this document when it is corrected |
71 or revised. This service is offered free of charge; please provide us with your | 71 or revised. This service is offered free of charge; please provide us with your |
72 mailing address. | 72 mailing address. |
73 */ | 73 */ |
74 | 74 |
75 #include "GIFImageReader.h" | 75 #include "SkGifImageReader.h" |
76 #include "SkColorPriv.h" | 76 #include "SkColorPriv.h" |
77 #include "SkGifCodec.h" | 77 #include "SkGifCodec.h" |
78 | 78 |
79 #include <algorithm> | 79 #include <algorithm> |
80 #include <string.h> | 80 #include <string.h> |
81 | 81 |
82 | 82 |
83 // GETN(n, s) requests at least 'n' bytes available from 'q', at start of state
's'. | 83 // GETN(n, s) requests at least 'n' bytes available from 'q', at start of state
's'. |
84 // | 84 // |
85 // Note, the hold will never need to be bigger than 256 bytes to gather up in th
e hold, | 85 // Note, the hold will never need to be bigger than 256 bytes to gather up in th
e hold, |
86 // as each GIF block (except colormaps) can never be bigger than 256 bytes. | 86 // as each GIF block (except colormaps) can never be bigger than 256 bytes. |
87 // Colormaps are directly copied in the resp. global_colormap or dynamically all
ocated local_colormap. | 87 // Colormaps are directly copied in the resp. global_colormap or dynamically all
ocated local_colormap. |
88 // So a fixed buffer in GIFImageReader is good enough. | 88 // So a fixed buffer in SkGifImageReader is good enough. |
89 // This buffer is only needed to copy left-over data from one GifWrite call to t
he next | 89 // This buffer is only needed to copy left-over data from one GifWrite call to t
he next |
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 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 default: | 191 default: |
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 GIFImageReader 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 GIFLZWContext::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; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 } | 333 } |
334 srcColormap += BYTES_PER_COLORMAP_ENTRY; | 334 srcColormap += 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 < 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, MAX_COLORS)); |
340 return m_table; | 340 return m_table; |
341 } | 341 } |
342 | 342 |
343 sk_sp<SkColorTable> GIFImageReader::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 GIFFrameContext* frameContext = m_frames[index].get(); |
349 const GIFColorMap& localColorMap = frameContext->localColorMap(); | 349 const GIFColorMap& 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 GIFImageReader 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 GIFFrameContext::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 GIFLZWContext. |
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 GIFLZWContext(client, this)); |
(...skipping 19 matching lines...) Expand all Loading... |
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 GIFFrameContext:decode() to decode the frame; decoding error
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 GIFImageReader::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 GIFFrameContext* 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 GIFImageReader::parse(GIFImageReader::GIFParseQuery query) | 410 bool SkGifImageReader::parse(SkGifImageReader::GIFParseQuery 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 // GIFSizeQuery and GIFFrameCountQuery are negative, so this is only meaning
ful 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. |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 GETN(0, GIFDone); | 842 GETN(0, GIFDone); |
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 GIFImageReader::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<GIFFrameContext> frame(new GIFFrameContext(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 GIFFrameContext* prevFrameContext = m_frames[i - 1].get(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |