Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: Source/core/platform/image-decoders/gif/GIFImageReader.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
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
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Chris Saari <saari@netscape.com>
24 * Apple Computer
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40 /*
41 The Graphics Interchange Format(c) is the copyright property of CompuServe
42 Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
43 enhance, alter, modify or change in any way the definition of the format.
44
45 CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
46 license for the use of the Graphics Interchange Format(sm) in computer
47 software; computer software utilizing GIF(sm) must acknowledge ownership of the
48 Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
49 User and Technical Documentation. Computer software utilizing GIF, which is
50 distributed or may be distributed without User or Technical Documentation must
51 display to the screen or printer a message acknowledging ownership of the
52 Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
53 this case, the acknowledgement may be displayed in an opening screen or leading
54 banner, or a closing screen or trailing banner. A message such as the following
55 may be used:
56
57 "The Graphics Interchange Format(c) is the Copyright property of
58 CompuServe Incorporated. GIF(sm) is a Service Mark property of
59 CompuServe Incorporated."
60
61 For further information, please contact :
62
63 CompuServe Incorporated
64 Graphics Technology Department
65 5000 Arlington Center Boulevard
66 Columbus, Ohio 43220
67 U. S. A.
68
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
71 or revised. This service is offered free of charge; please provide us with your
72 mailing address.
73 */
74
75 #include "config.h"
76 #include "core/platform/image-decoders/gif/GIFImageReader.h"
77
78 #include <string.h>
79 #include "core/platform/graphics/ImageSource.h"
80
81 using WebCore::GIFImageDecoder;
82
83 // GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'.
84 //
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.
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.
89 // This buffer is only needed to copy left-over data from one GifWrite call to t he next
90 #define GETN(n, s) \
91 do { \
92 m_bytesToConsume = (n); \
93 m_state = (s); \
94 } while (0)
95
96 // Get a 16-bit value stored in little-endian format.
97 #define GETINT16(p) ((p)[1]<<8|(p)[0])
98
99 // Send the data to the display front-end.
100 bool GIFLZWContext::outputRow(GIFRow::const_iterator rowBegin)
101 {
102 int drowStart = irow;
103 int drowEnd = irow;
104
105 // Haeberli-inspired hack for interlaced GIFs: Replicate lines while
106 // displaying to diminish the "venetian-blind" effect as the image is
107 // loaded. Adjust pixel vertical positions to avoid the appearance of the
108 // image crawling up the screen as successive passes are drawn.
109 if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) {
110 unsigned rowDup = 0;
111 unsigned rowShift = 0;
112
113 switch (ipass) {
114 case 1:
115 rowDup = 7;
116 rowShift = 3;
117 break;
118 case 2:
119 rowDup = 3;
120 rowShift = 1;
121 break;
122 case 3:
123 rowDup = 1;
124 rowShift = 0;
125 break;
126 default:
127 break;
128 }
129
130 drowStart -= rowShift;
131 drowEnd = drowStart + rowDup;
132
133 // Extend if bottom edge isn't covered because of the shift upward.
134 if (((m_frameContext->height() - 1) - drowEnd) <= rowShift)
135 drowEnd = m_frameContext->height() - 1;
136
137 // Clamp first and last rows to upper and lower edge of image.
138 if (drowStart < 0)
139 drowStart = 0;
140
141 if ((unsigned)drowEnd >= m_frameContext->height())
142 drowEnd = m_frameContext->height() - 1;
143 }
144
145 // Protect against too much image data.
146 if ((unsigned)drowStart >= m_frameContext->height())
147 return true;
148
149 // CALLBACK: Let the client know we have decoded a row.
150 if (!m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin, m_frameCo ntext->width(),
151 drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass > 1))
152 return false;
153
154 if (!m_frameContext->interlaced())
155 irow++;
156 else {
157 do {
158 switch (ipass) {
159 case 1:
160 irow += 8;
161 if (irow >= m_frameContext->height()) {
162 ipass++;
163 irow = 4;
164 }
165 break;
166
167 case 2:
168 irow += 8;
169 if (irow >= m_frameContext->height()) {
170 ipass++;
171 irow = 2;
172 }
173 break;
174
175 case 3:
176 irow += 4;
177 if (irow >= m_frameContext->height()) {
178 ipass++;
179 irow = 1;
180 }
181 break;
182
183 case 4:
184 irow += 2;
185 if (irow >= m_frameContext->height()) {
186 ipass++;
187 irow = 0;
188 }
189 break;
190
191 default:
192 break;
193 }
194 } while (irow > (m_frameContext->height() - 1));
195 }
196 return true;
197 }
198
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.
201 // Otherwise, decoding failed; returns false in this case, which will always cau se the GIFImageReader to set the "decode failed" flag.
202 bool GIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
203 {
204 const size_t width = m_frameContext->width();
205
206 if (rowIter == rowBuffer.end())
207 return true;
208
209 for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) {
210 // Feed the next byte into the decoder's 32-bit input buffer.
211 datum += ((int) *ch) << bits;
212 bits += 8;
213
214 // Check for underflow of decoder's 32-bit input buffer.
215 while (bits >= codesize) {
216 // Get the leading variable-length symbol from the data stream.
217 int code = datum & codemask;
218 datum >>= codesize;
219 bits -= codesize;
220
221 // Reset the dictionary to its original state, if requested.
222 if (code == clearCode) {
223 codesize = m_frameContext->dataSize() + 1;
224 codemask = (1 << codesize) - 1;
225 avail = clearCode + 2;
226 oldcode = -1;
227 continue;
228 }
229
230 // Check for explicit end-of-stream code.
231 if (code == (clearCode + 1)) {
232 // end-of-stream should only appear after all image data.
233 if (!rowsRemaining)
234 return true;
235 return false;
236 }
237
238 const int tempCode = code;
239 unsigned short codeLength = 0;
240 if (code < avail) {
241 // This is a pre-existing code, so we already know what it
242 // encodes.
243 codeLength = suffixLength[code];
244 rowIter += codeLength;
245 } else if (code == avail && oldcode != -1) {
246 // This is a new code just being added to the dictionary.
247 // It must encode the contents of the previous code, plus
248 // the first character of the previous code again.
249 codeLength = suffixLength[oldcode] + 1;
250 rowIter += codeLength;
251 *--rowIter = firstchar;
252 code = oldcode;
253 } else {
254 // This is an invalid code. The dictionary is just initialized
255 // and the code is incomplete. We don't know how to handle
256 // this case.
257 return false;
258 }
259
260 while (code >= clearCode) {
261 *--rowIter = suffix[code];
262 code = prefix[code];
263 }
264
265 *--rowIter = firstchar = suffix[code];
266
267 // Define a new codeword in the dictionary as long as we've read
268 // more than one value from the stream.
269 if (avail < MAX_DICTIONARY_ENTRIES && oldcode != -1) {
270 prefix[avail] = oldcode;
271 suffix[avail] = firstchar;
272 suffixLength[avail] = suffixLength[oldcode] + 1;
273 ++avail;
274
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
277 // exceed the specified maximum codeword size.
278 if (!(avail & codemask) && avail < MAX_DICTIONARY_ENTRIES) {
279 ++codesize;
280 codemask += avail;
281 }
282 }
283 oldcode = tempCode;
284 rowIter += codeLength;
285
286 // Output as many rows as possible.
287 GIFRow::iterator rowBegin = rowBuffer.begin();
288 for (; rowBegin + width <= rowIter; rowBegin += width) {
289 if (!outputRow(rowBegin))
290 return false;
291 rowsRemaining--;
292 if (!rowsRemaining)
293 return true;
294 }
295
296 if (rowBegin != rowBuffer.begin()) {
297 // Move the remaining bytes to the beginning of the buffer.
298 const size_t bytesToCopy = rowIter - rowBegin;
299 memcpy(rowBuffer.begin(), rowBegin, bytesToCopy);
300 rowIter = rowBuffer.begin() + bytesToCopy;
301 }
302 }
303 }
304 return true;
305 }
306
307 void GIFColorMap::buildTable(const unsigned char* data, size_t length)
308 {
309 if (!m_isDefined || !m_table.isEmpty())
310 return;
311
312 RELEASE_ASSERT(m_position + m_colors * BYTES_PER_COLORMAP_ENTRY <= length);
313 const unsigned char* srcColormap = data + m_position;
314 m_table.resize(m_colors);
315 for (Table::iterator iter = m_table.begin(); iter != m_table.end(); ++iter) {
316 *iter = SkPackARGB32NoCheck(255, srcColormap[0], srcColormap[1], srcColo rmap[2]);
317 srcColormap += BYTES_PER_COLORMAP_ENTRY;
318 }
319 }
320
321 // Perform decoding for this frame. frameDecoded will be true if the entire fram e is decoded.
322 // Returns false if a decoding error occurred. This is a fatal error and causes the GIFImageReader to set the "decode failed" flag.
323 // 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.
324 bool GIFFrameContext::decode(const unsigned char* data, size_t length, WebCore:: GIFImageDecoder* client, bool* frameDecoded)
325 {
326 m_localColorMap.buildTable(data, length);
327
328 *frameDecoded = false;
329 if (!m_lzwContext) {
330 // Wait for more data to properly initialize GIFLZWContext.
331 if (!isDataSizeDefined() || !isHeaderDefined())
332 return true;
333
334 m_lzwContext = adoptPtr(new GIFLZWContext(client, this));
335 if (!m_lzwContext->prepareToDecode()) {
336 m_lzwContext.clear();
337 return false;
338 }
339
340 m_currentLzwBlock = 0;
341 }
342
343 // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode.
344 while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingR ows()) {
345 size_t blockPosition = m_lzwBlocks[m_currentLzwBlock].blockPosition;
346 size_t blockSize = m_lzwBlocks[m_currentLzwBlock].blockSize;
347 if (blockPosition + blockSize > length)
348 return false;
349 if (!m_lzwContext->doLZW(data + blockPosition, blockSize))
350 return false;
351 ++m_currentLzwBlock;
352 }
353
354 // If this frame is data complete then the previous loop must have completel y decoded all LZW blocks.
355 // There will be no more decoding for this frame so it's time to cleanup.
356 if (isComplete()) {
357 *frameDecoded = true;
358 m_lzwContext.clear();
359 }
360 return true;
361 }
362
363 // Decode a frame.
364 // This method uses GIFFrameContext:decode() to decode the frame; decoding error is reported to client as a critical failure.
365 // Return true if decoding has progressed. Return false if an error has occurred .
366 bool GIFImageReader::decode(size_t frameIndex)
367 {
368 m_globalColorMap.buildTable(data(0), m_data->size());
369
370 bool frameDecoded = false;
371 GIFFrameContext* currentFrame = m_frames[frameIndex].get();
372
373 return currentFrame->decode(data(0), m_data->size(), m_client, &frameDecoded )
374 && (!frameDecoded || m_client->frameComplete(frameIndex));
375 }
376
377 bool GIFImageReader::parse(GIFImageDecoder::GIFParseQuery query)
378 {
379 ASSERT(m_bytesRead <= m_data->size());
380
381 return parseData(m_bytesRead, m_data->size() - m_bytesRead, query);
382 }
383
384 // Parse incoming GIF data stream into internal data structures.
385 // Return true if parsing has progressed or there is not enough data.
386 // Return false if a fatal error is encountered.
387 bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder: :GIFParseQuery query)
388 {
389 if (!len) {
390 // No new data has come in since the last call, just ignore this call.
391 return true;
392 }
393
394 if (len < m_bytesToConsume)
395 return true;
396
397 // This loop reads as many components from |m_data| as possible.
398 // At the beginning of each iteration, dataPosition will be advanced by m_by tesToConsume to
399 // point to the next component. len will be decremented accordingly.
400 while (len >= m_bytesToConsume) {
401 const size_t currentComponentPosition = dataPosition;
402 const unsigned char* currentComponent = data(dataPosition);
403
404 // Mark the current component as consumed. Note that currentComponent wi ll remain pointed at this
405 // component until the next loop iteration.
406 dataPosition += m_bytesToConsume;
407 len -= m_bytesToConsume;
408
409 switch (m_state) {
410 case GIFLZW:
411 ASSERT(!m_frames.isEmpty());
412 // m_bytesToConsume is the current component size because it hasn't been updated.
413 m_frames.last()->addLzwBlock(currentComponentPosition, m_bytesToCons ume);
414 GETN(1, GIFSubBlock);
415 break;
416
417 case GIFLZWStart: {
418 ASSERT(!m_frames.isEmpty());
419 m_frames.last()->setDataSize(*currentComponent);
420 GETN(1, GIFSubBlock);
421 break;
422 }
423
424 case GIFType: {
425 // All GIF files begin with "GIF87a" or "GIF89a".
426 if (!strncmp((char*)currentComponent, "GIF89a", 6))
427 m_version = 89;
428 else if (!strncmp((char*)currentComponent, "GIF87a", 6))
429 m_version = 87;
430 else
431 return false;
432 GETN(7, GIFGlobalHeader);
433 break;
434 }
435
436 case GIFGlobalHeader: {
437 // This is the height and width of the "screen" or frame into which images are rendered. The
438 // individual images can be smaller than the screen size and located with an origin anywhere
439 // within the screen.
440 m_screenWidth = GETINT16(currentComponent);
441 m_screenHeight = GETINT16(currentComponent + 2);
442
443 // CALLBACK: Inform the decoderplugin of our size.
444 // Note: A subsequent frame might have dimensions larger than the "s creen" dimensions.
445 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
446 return false;
447
448 const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07 );
449
450 if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* g lobal map */
451 m_globalColorMap.setTablePositionAndSize(dataPosition, globalCol orMapColors);
452 GETN(BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, GIFGlobalC olormap);
453 break;
454 }
455
456 GETN(1, GIFImageStart);
457 break;
458 }
459
460 case GIFGlobalColormap: {
461 m_globalColorMap.setDefined();
462 GETN(1, GIFImageStart);
463 break;
464 }
465
466 case GIFImageStart: {
467 if (*currentComponent == '!') { // extension.
468 GETN(2, GIFExtension);
469 break;
470 }
471
472 if (*currentComponent == ',') { // image separator.
473 GETN(9, GIFImageHeader);
474 break;
475 }
476
477 // If we get anything other than ',' (image separator), '!'
478 // (extension), or ';' (trailer), there is extraneous data
479 // between blocks. The GIF87a spec tells us to keep reading
480 // until we find an image separator, but GIF89a says such
481 // a file is corrupt. We follow Mozilla's implementation and
482 // proceed as if the file were correctly terminated, so the
483 // GIF will display.
484 GETN(0, GIFDone);
485 break;
486 }
487
488 case GIFExtension: {
489 size_t bytesInBlock = currentComponent[1];
490 GIFState exceptionState = GIFSkipBlock;
491
492 switch (*currentComponent) {
493 case 0xf9:
494 exceptionState = GIFControlExtension;
495 // The GIF spec mandates that the GIFControlExtension header blo ck length is 4 bytes,
496 // and the parser for this block reads 4 bytes, so we must enfor ce that the buffer
497 // contains at least this many bytes. If the GIF specifies a dif ferent length, we
498 // allow that, so long as it's larger; the additional data will simply be ignored.
499 bytesInBlock = std::max(bytesInBlock, static_cast<size_t>(4));
500 break;
501
502 // The GIF spec also specifies the lengths of the following two exte nsions' headers
503 // (as 12 and 11 bytes, respectively). Because we ignore the plain t ext extension entirely
504 // and sanity-check the actual length of the application extension h eader before reading it,
505 // we allow GIFs to deviate from these values in either direction. T his is important for
506 // real-world compatibility, as GIFs in the wild exist with applicat ion extension headers
507 // that are both shorter and longer than 11 bytes.
508 case 0x01:
509 // ignoring plain text extension
510 break;
511
512 case 0xff:
513 exceptionState = GIFApplicationExtension;
514 break;
515
516 case 0xfe:
517 exceptionState = GIFConsumeComment;
518 break;
519 }
520
521 if (bytesInBlock)
522 GETN(bytesInBlock, exceptionState);
523 else
524 GETN(1, GIFImageStart);
525 break;
526 }
527
528 case GIFConsumeBlock: {
529 if (!*currentComponent)
530 GETN(1, GIFImageStart);
531 else
532 GETN(*currentComponent, GIFSkipBlock);
533 break;
534 }
535
536 case GIFSkipBlock: {
537 GETN(1, GIFConsumeBlock);
538 break;
539 }
540
541 case GIFControlExtension: {
542 addFrameIfNecessary();
543 GIFFrameContext* currentFrame = m_frames.last().get();
544 if (*currentComponent & 0x1)
545 currentFrame->setTransparentPixel(currentComponent[3]);
546
547 // We ignore the "user input" bit.
548
549 // NOTE: This relies on the values in the FrameDisposalMethod enum
550 // matching those in the GIF spec!
551 int disposalMethod = ((*currentComponent) >> 2) & 0x7;
552 if (disposalMethod < 4) {
553 currentFrame->setDisposalMethod(static_cast<WebCore::ImageFrame: :DisposalMethod>(disposalMethod));
554 } else if (disposalMethod == 4) {
555 // Some specs say that disposal method 3 is "overwrite previous" , others that setting
556 // the third bit of the field (i.e. method 4) is. We map both to the same value.
557 currentFrame->setDisposalMethod(WebCore::ImageFrame::DisposeOver writePrevious);
558 }
559 currentFrame->setDelayTime(GETINT16(currentComponent + 1) * 10);
560 GETN(1, GIFConsumeBlock);
561 break;
562 }
563
564 case GIFCommentExtension: {
565 if (*currentComponent)
566 GETN(*currentComponent, GIFConsumeComment);
567 else
568 GETN(1, GIFImageStart);
569 break;
570 }
571
572 case GIFConsumeComment: {
573 GETN(1, GIFCommentExtension);
574 break;
575 }
576
577 case GIFApplicationExtension: {
578 // Check for netscape application extension.
579 if (m_bytesToConsume == 11
580 && (!strncmp((char*)currentComponent, "NETSCAPE2.0", 11) || !str ncmp((char*)currentComponent, "ANIMEXTS1.0", 11)))
581 GETN(1, GIFNetscapeExtensionBlock);
582 else
583 GETN(1, GIFConsumeBlock);
584 break;
585 }
586
587 // Netscape-specific GIF extension: animation looping.
588 case GIFNetscapeExtensionBlock: {
589 // GIFConsumeNetscapeExtension always reads 3 bytes from the stream; we should at least wait for this amount.
590 if (*currentComponent)
591 GETN(std::max(3, static_cast<int>(*currentComponent)), GIFConsum eNetscapeExtension);
592 else
593 GETN(1, GIFImageStart);
594 break;
595 }
596
597 // Parse netscape-specific application extensions
598 case GIFConsumeNetscapeExtension: {
599 int netscapeExtension = currentComponent[0] & 7;
600
601 // Loop entire animation specified # of times. Only read the loop co unt during the first iteration.
602 if (netscapeExtension == 1) {
603 m_loopCount = GETINT16(currentComponent + 1);
604
605 // Zero loop count is infinite animation loop request.
606 if (!m_loopCount)
607 m_loopCount = WebCore::cAnimationLoopInfinite;
608
609 GETN(1, GIFNetscapeExtensionBlock);
610 } else if (netscapeExtension == 2) {
611 // Wait for specified # of bytes to enter buffer.
612
613 // Don't do this, this extension doesn't exist (isn't used at al l)
614 // and doesn't do anything, as our streaming/buffering takes car e of it all...
615 // See: http://semmix.pl/color/exgraf/eeg24.htm
616 GETN(1, GIFNetscapeExtensionBlock);
617 } else {
618 // 0,3-7 are yet to be defined netscape extension codes
619 return false;
620 }
621 break;
622 }
623
624 case GIFImageHeader: {
625 unsigned height, width, xOffset, yOffset;
626
627 /* Get image offsets, with respect to the screen origin */
628 xOffset = GETINT16(currentComponent);
629 yOffset = GETINT16(currentComponent + 2);
630
631 /* Get image width and height. */
632 width = GETINT16(currentComponent + 4);
633 height = GETINT16(currentComponent + 6);
634
635 /* Work around broken GIF files where the logical screen
636 * size has weird width or height. We assume that GIF87a
637 * files don't contain animations.
638 */
639 if (currentFrameIsFirstFrame()
640 && ((m_screenHeight < height) || (m_screenWidth < width) || (m_v ersion == 87))) {
641 m_screenHeight = height;
642 m_screenWidth = width;
643 xOffset = 0;
644 yOffset = 0;
645
646 // CALLBACK: Inform the decoderplugin of our size.
647 if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight ))
648 return false;
649 }
650
651 // Work around more broken GIF files that have zero image width or h eight
652 if (!height || !width) {
653 height = m_screenHeight;
654 width = m_screenWidth;
655 if (!height || !width)
656 return false;
657 }
658
659 if (query == GIFImageDecoder::GIFSizeQuery) {
660 // The decoder needs to stop. Hand back the number of bytes we c onsumed from
661 // buffer minus 9 (the amount we consumed to read the header).
662 setRemainingBytes(len + 9);
663 GETN(9, GIFImageHeader);
664 return true;
665 }
666
667 addFrameIfNecessary();
668 GIFFrameContext* currentFrame = m_frames.last().get();
669
670 currentFrame->setHeaderDefined();
671 currentFrame->setRect(xOffset, yOffset, width, height);
672 m_screenWidth = std::max(m_screenWidth, width);
673 m_screenHeight = std::max(m_screenHeight, height);
674 currentFrame->setInterlaced(currentComponent[8] & 0x40);
675
676 // Overlaying interlaced, transparent GIFs over
677 // existing image data using the Haeberli display hack
678 // requires saving the underlying image in order to
679 // avoid jaggies at the transparency edges. We are
680 // unprepared to deal with that, so don't display such
681 // images progressively. Which means only the first
682 // frame can be progressively displayed.
683 // FIXME: It is possible that a non-transparent frame
684 // can be interlaced and progressively displayed.
685 currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame());
686
687 const bool isLocalColormapDefined = currentComponent[8] & 0x80;
688 if (isLocalColormapDefined) {
689 // The three low-order bits of currentComponent[8] specify the b its per pixel.
690 const size_t numColors = 2 << (currentComponent[8] & 0x7);
691 currentFrame->localColorMap().setTablePositionAndSize(dataPositi on, numColors);
692 GETN(BYTES_PER_COLORMAP_ENTRY * numColors, GIFImageColormap);
693 break;
694 }
695
696 GETN(1, GIFLZWStart);
697 break;
698 }
699
700 case GIFImageColormap: {
701 ASSERT(!m_frames.isEmpty());
702 m_frames.last()->localColorMap().setDefined();
703 GETN(1, GIFLZWStart);
704 break;
705 }
706
707 case GIFSubBlock: {
708 const size_t bytesInBlock = *currentComponent;
709 if (bytesInBlock)
710 GETN(bytesInBlock, GIFLZW);
711 else {
712 // Finished parsing one frame; Process next frame.
713 ASSERT(!m_frames.isEmpty());
714 // Note that some broken GIF files do not have enough LZW blocks to fully
715 // decode all rows but we treat it as frame complete.
716 m_frames.last()->setComplete();
717 GETN(1, GIFImageStart);
718 }
719 break;
720 }
721
722 case GIFDone: {
723 m_parseCompleted = true;
724 return true;
725 }
726
727 default:
728 // We shouldn't ever get here.
729 return false;
730 break;
731 }
732 }
733
734 setRemainingBytes(len);
735 return true;
736 }
737
738 void GIFImageReader::setRemainingBytes(size_t remainingBytes)
739 {
740 ASSERT(remainingBytes <= m_data->size());
741 m_bytesRead = m_data->size() - remainingBytes;
742 }
743
744 void GIFImageReader::addFrameIfNecessary()
745 {
746 if (m_frames.isEmpty() || m_frames.last()->isComplete())
747 m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size())));
748 }
749
750 // FIXME: Move this method to close to doLZW().
751 bool GIFLZWContext::prepareToDecode()
752 {
753 ASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefine d());
754
755 // Since we use a codesize of 1 more than the datasize, we need to ensure
756 // that our datasize is strictly less than the MAX_DICTIONARY_ENTRY_BITS.
757 if (m_frameContext->dataSize() >= MAX_DICTIONARY_ENTRY_BITS)
758 return false;
759 clearCode = 1 << m_frameContext->dataSize();
760 avail = clearCode + 2;
761 oldcode = -1;
762 codesize = m_frameContext->dataSize() + 1;
763 codemask = (1 << codesize) - 1;
764 datum = bits = 0;
765 ipass = m_frameContext->interlaced() ? 1 : 0;
766 irow = 0;
767
768 // We want to know the longest sequence encodable by a dictionary with
769 // MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base
770 // values themselves at the beginning of the dictionary, as well as the need
771 // for a clear code or a termination code, we could use every entry to
772 // encode a series of multiple values. If the input value stream looked
773 // like "AAAAA..." (a long string of just one value), the first dictionary
774 // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus
775 // the longest sequence would be MAX_DICTIONARY_ENTRIES + 1 values.
776 //
777 // However, we have to account for reserved entries. The first |datasize|
778 // bits are reserved for the base values, and the next two entries are
779 // reserved for the clear code and termination code. In theory a GIF can
780 // set the datasize to 0, meaning we have just two reserved entries, making
781 // the longest sequence (MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since
782 // each value is a byte, this is also the number of bytes in the longest
783 // encodable sequence.
784 const size_t maxBytes = MAX_DICTIONARY_ENTRIES - 1;
785
786 // Now allocate the output buffer. We decode directly into this buffer
787 // until we have at least one row worth of data, then call outputRow().
788 // This means worst case we may have (row width - 1) bytes in the buffer
789 // and then decode a sequence |maxBytes| long to append.
790 rowBuffer.resize(m_frameContext->width() - 1 + maxBytes);
791 rowIter = rowBuffer.begin();
792 rowsRemaining = m_frameContext->height();
793
794 // Clearing the whole suffix table lets us be more tolerant of bad data.
795 for (int i = 0; i < clearCode; ++i) {
796 suffix[i] = i;
797 suffixLength[i] = 1;
798 }
799 return true;
800 }
OLDNEW
« no previous file with comments | « Source/core/platform/image-decoders/gif/GIFImageReader.h ('k') | Source/core/platform/image-decoders/ico/ICOImageDecoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698