1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 The Graphics Interchange Format(c) is the copyright property of CompuServe
8 Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
9 enhance, alter, modify or change in any way the definition of the format.
10
11 CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
12 license for the use of the Graphics Interchange Format(sm) in computer
13 software; computer software utilizing GIF(sm) must acknowledge ownership of the
14 Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
15 User and Technical Documentation. Computer software utilizing GIF, which is
16 distributed or may be distributed without User or Technical Documentation must
17 display to the screen or printer a message acknowledging ownership of the
18 Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
19 this case, the acknowledgement may be displayed in an opening screen or leading
20 banner, or a closing screen or trailing banner. A message such as the following
21 may be used:
22
23 "The Graphics Interchange Format(c) is the Copyright property of
24 CompuServe Incorporated. GIF(sm) is a Service Mark property of
25 CompuServe Incorporated."
26
27 For further information, please contact :
28
29 CompuServe Incorporated
30 Graphics Technology Department
31 5000 Arlington Center Boulevard
32 Columbus, Ohio 43220
33 U. S. A.
34
35 CompuServe Incorporated maintains a mailing list with all those individuals and
36 organizations who wish to receive copies of this document when it is corrected
37 or revised. This service is offered free of charge; please provide us with your
38 mailing address.
39 */
40
41 #include "nsGIFDecoder2.h"
42
43 #include <stddef.h>
44
45 #include "imgFrame.h"
46 #include "mozilla/EndianUtils.h"
47 #include "RasterImage.h"
48 #include "SurfacePipeFactory.h"
49
50 #include "gfxColor.h"
51 #include "gfxPlatform.h"
52 #include "qcms.h"
53 #include <algorithm>
54 #include "mozilla/Telemetry.h"
55
56 using namespace mozilla::gfx;
57
58 using std::max;
59
60 namespace mozilla {
61 namespace image {
62
63 //////////////////////////////////////////////////////////////////////
64 // GIF Decoder Implementation
65
66 static const size_t GIF_HEADER_LEN = 6;
67 static const size_t GIF_SCREEN_DESCRIPTOR_LEN = 7;
68 static const size_t BLOCK_HEADER_LEN = 1;
69 static const size_t SUB_BLOCK_HEADER_LEN = 1;
70 static const size_t EXTENSION_HEADER_LEN = 2;
71 static const size_t GRAPHIC_CONTROL_EXTENSION_LEN = 4;
72 static const size_t APPLICATION_EXTENSION_LEN = 11;
73 static const size_t IMAGE_DESCRIPTOR_LEN = 9;
74
75 // Masks for reading color table information from packed fields in the screen
76 // descriptor and image descriptor blocks.
77 static const uint8_t PACKED_FIELDS_COLOR_TABLE_BIT = 0x80;
78 static const uint8_t PACKED_FIELDS_INTERLACED_BIT = 0x40;
79 static const uint8_t PACKED_FIELDS_TABLE_DEPTH_MASK = 0x07;
80
nsGIFDecoder2(RasterImage * aImage)81 nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage)
82 : Decoder(aImage),
83 mLexer(Transition::To(State::GIF_HEADER, GIF_HEADER_LEN),
84 Transition::TerminateSuccess()),
85 mOldColor(0),
86 mCurrentFrameIndex(-1),
87 mColorTablePos(0),
88 mColormap(nullptr),
89 mColormapSize(0),
90 mColorMask('\0'),
91 mGIFOpen(false),
92 mSawTransparency(false),
93 mSwizzleFn(nullptr) {
94 // Clear out the structure, excluding the arrays. Ensure that the global
95 // colormap is initialized as opaque.
96 memset(&mGIFStruct, 0, sizeof(mGIFStruct));
97 memset(mGIFStruct.global_colormap, 0xFF, sizeof(mGIFStruct.global_colormap));
98
99 // Each color table will need to be unpacked.
100 mSwizzleFn = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::OS_RGBA);
101 MOZ_ASSERT(mSwizzleFn);
102 }
103
~nsGIFDecoder2()104 nsGIFDecoder2::~nsGIFDecoder2() { free(mGIFStruct.local_colormap); }
105
FinishInternal()106 nsresult nsGIFDecoder2::FinishInternal() {
107 MOZ_ASSERT(!HasError(), "Shouldn't call FinishInternal after error!");
108
109 // If the GIF got cut off, handle it anyway
110 if (!IsMetadataDecode() && mGIFOpen) {
111 if (mCurrentFrameIndex == mGIFStruct.images_decoded) {
112 EndImageFrame();
113 }
114 PostDecodeDone(mGIFStruct.loop_count);
115 mGIFOpen = false;
116 }
117
118 return NS_OK;
119 }
120
FlushImageData()121 void nsGIFDecoder2::FlushImageData() {
122 Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect();
123 if (!invalidRect) {
124 return;
125 }
126
127 PostInvalidation(invalidRect->mInputSpaceRect,
128 Some(invalidRect->mOutputSpaceRect));
129 }
130
131 //******************************************************************************
132 // GIF decoder callback methods. Part of public API for GIF2
133 //******************************************************************************
134
135 //******************************************************************************
BeginGIF()136 void nsGIFDecoder2::BeginGIF() {
137 if (mGIFOpen) {
138 return;
139 }
140
141 mGIFOpen = true;
142
143 PostSize(mGIFStruct.screen_width, mGIFStruct.screen_height);
144 }
145
CheckForTransparency(const IntRect & aFrameRect)146 bool nsGIFDecoder2::CheckForTransparency(const IntRect& aFrameRect) {
147 // Check if the image has a transparent color in its palette.
148 if (mGIFStruct.is_transparent) {
149 PostHasTransparency();
150 return true;
151 }
152
153 if (mGIFStruct.images_decoded > 0) {
154 return false; // We only care about first frame padding below.
155 }
156
157 // If we need padding on the first frame, that means we don't draw into part
158 // of the image at all. Report that as transparency.
159 IntRect imageRect(0, 0, mGIFStruct.screen_width, mGIFStruct.screen_height);
160 if (!imageRect.IsEqualEdges(aFrameRect)) {
161 PostHasTransparency();
162 mSawTransparency = true; // Make sure we don't optimize it away.
163 return true;
164 }
165
166 return false;
167 }
168
169 //******************************************************************************
BeginImageFrame(const IntRect & aFrameRect,uint16_t aDepth,bool aIsInterlaced)170 nsresult nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect,
171 uint16_t aDepth, bool aIsInterlaced) {
172 MOZ_ASSERT(HasSize());
173
174 bool hasTransparency = CheckForTransparency(aFrameRect);
175
176 // Make sure there's no animation if we're downscaling.
177 MOZ_ASSERT_IF(Size() != OutputSize(), !GetImageMetadata().HasAnimation());
178
179 Maybe<AnimationParams> animParams;
180 if (!IsFirstFrameDecode()) {
181 animParams.emplace(aFrameRect,
182 FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time),
183 uint32_t(mGIFStruct.images_decoded), BlendMethod::OVER,
184 DisposalMethod(mGIFStruct.disposal_method));
185 }
186
187 SurfacePipeFlags pipeFlags =
188 aIsInterlaced ? SurfacePipeFlags::DEINTERLACE : SurfacePipeFlags();
189
190 gfx::SurfaceFormat format;
191 if (mGIFStruct.images_decoded == 0) {
192 // The first frame may be displayed progressively.
193 pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
194
195 // Only allow opaque surfaces if we are decoding a single image without
196 // transparency. For an animation, there isn't much benefit to RGBX given
197 // the current frame is constantly changing, and there are many risks
198 // since BlendAnimationFilter is able to clear rows of data.
199 format = hasTransparency || animParams ? SurfaceFormat::OS_RGBA
200 : SurfaceFormat::OS_RGBX;
201 } else {
202 format = SurfaceFormat::OS_RGBA;
203 }
204
205 Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
206 this, Size(), OutputSize(), aFrameRect, format, format, animParams,
207 mTransform, pipeFlags);
208 mCurrentFrameIndex = mGIFStruct.images_decoded;
209
210 if (!pipe) {
211 mPipe = SurfacePipe();
212 return NS_ERROR_FAILURE;
213 }
214
215 mPipe = std::move(*pipe);
216 return NS_OK;
217 }
218
219 //******************************************************************************
EndImageFrame()220 void nsGIFDecoder2::EndImageFrame() {
221 Opacity opacity = Opacity::SOME_TRANSPARENCY;
222
223 if (mGIFStruct.images_decoded == 0) {
224 // We need to send invalidations for the first frame.
225 FlushImageData();
226
227 // The first frame was preallocated with alpha; if it wasn't transparent, we
228 // should fix that. We can also mark it opaque unconditionally if we didn't
229 // actually see any transparent pixels - this test is only valid for the
230 // first frame.
231 if (!mGIFStruct.is_transparent && !mSawTransparency) {
232 opacity = Opacity::FULLY_OPAQUE;
233 }
234 }
235
236 // Unconditionally increment images_decoded, because we unconditionally
237 // append frames in BeginImageFrame(). This ensures that images_decoded
238 // always refers to the frame in mImage we're currently decoding,
239 // even if some of them weren't decoded properly and thus are blank.
240 mGIFStruct.images_decoded++;
241
242 // Reset graphic control extension parameters that we shouldn't reuse
243 // between frames.
244 mGIFStruct.delay_time = 0;
245
246 // Tell the superclass we finished a frame
247 PostFrameStop(opacity);
248
249 // Reset the transparent pixel
250 if (mOldColor) {
251 mColormap[mGIFStruct.tpixel] = mOldColor;
252 mOldColor = 0;
253 }
254
255 mColormap = nullptr;
256 mColormapSize = 0;
257 mCurrentFrameIndex = -1;
258 }
259
260 template <typename PixelSize>
ColormapIndexToPixel(uint8_t aIndex)261 PixelSize nsGIFDecoder2::ColormapIndexToPixel(uint8_t aIndex) {
262 MOZ_ASSERT(sizeof(PixelSize) == sizeof(uint32_t));
263
264 // Retrieve the next color, clamping to the size of the colormap.
265 uint32_t color = mColormap[aIndex & mColorMask];
266
267 // Check for transparency.
268 if (mGIFStruct.is_transparent) {
269 mSawTransparency = mSawTransparency || color == 0;
270 }
271
272 return color;
273 }
274
275 template <>
ColormapIndexToPixel(uint8_t aIndex)276 uint8_t nsGIFDecoder2::ColormapIndexToPixel<uint8_t>(uint8_t aIndex) {
277 return aIndex & mColorMask;
278 }
279
280 template <typename PixelSize>
YieldPixels(const uint8_t * aData,size_t aLength,size_t * aBytesReadOut,PixelSize * aPixelBlock,int32_t aBlockSize)281 Tuple<int32_t, Maybe<WriteState>> nsGIFDecoder2::YieldPixels(
282 const uint8_t* aData, size_t aLength, size_t* aBytesReadOut,
283 PixelSize* aPixelBlock, int32_t aBlockSize) {
284 MOZ_ASSERT(aData);
285 MOZ_ASSERT(aBytesReadOut);
286 MOZ_ASSERT(mGIFStruct.stackp >= mGIFStruct.stack);
287
288 // Advance to the next byte we should read.
289 const uint8_t* data = aData + *aBytesReadOut;
290
291 int32_t written = 0;
292 while (aBlockSize > written) {
293 // If we don't have any decoded data to yield, try to read some input and
294 // produce some.
295 if (mGIFStruct.stackp == mGIFStruct.stack) {
296 while (mGIFStruct.bits < mGIFStruct.codesize &&
297 *aBytesReadOut < aLength) {
298 // Feed the next byte into the decoder's 32-bit input buffer.
299 mGIFStruct.datum += int32_t(*data) << mGIFStruct.bits;
300 mGIFStruct.bits += 8;
301 data += 1;
302 *aBytesReadOut += 1;
303 }
304
305 if (mGIFStruct.bits < mGIFStruct.codesize) {
306 return MakeTuple(written, Some(WriteState::NEED_MORE_DATA));
307 }
308
309 // Get the leading variable-length symbol from the data stream.
310 int code = mGIFStruct.datum & mGIFStruct.codemask;
311 mGIFStruct.datum >>= mGIFStruct.codesize;
312 mGIFStruct.bits -= mGIFStruct.codesize;
313
314 const int clearCode = ClearCode();
315
316 // Reset the dictionary to its original state, if requested
317 if (code == clearCode) {
318 mGIFStruct.codesize = mGIFStruct.datasize + 1;
319 mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1;
320 mGIFStruct.avail = clearCode + 2;
321 mGIFStruct.oldcode = -1;
322 return MakeTuple(written, Some(WriteState::NEED_MORE_DATA));
323 }
324
325 // Check for explicit end-of-stream code. It should only appear after all
326 // image data, but if that was the case we wouldn't be in this function,
327 // so this is always an error condition.
328 if (code == (clearCode + 1)) {
329 return MakeTuple(written, Some(WriteState::FAILURE));
330 }
331
332 if (mGIFStruct.oldcode == -1) {
333 if (code >= MAX_BITS) {
334 // The code's too big; something's wrong.
335 return MakeTuple(written, Some(WriteState::FAILURE));
336 }
337
338 mGIFStruct.firstchar = mGIFStruct.oldcode = code;
339
340 // Yield a pixel at the appropriate index in the colormap.
341 mGIFStruct.pixels_remaining--;
342 aPixelBlock[written++] =
343 ColormapIndexToPixel<PixelSize>(mGIFStruct.suffix[code]);
344 continue;
345 }
346
347 int incode = code;
348 if (code >= mGIFStruct.avail) {
349 *mGIFStruct.stackp++ = mGIFStruct.firstchar;
350 code = mGIFStruct.oldcode;
351
352 if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) {
353 // Stack overflow; something's wrong.
354 return MakeTuple(written, Some(WriteState::FAILURE));
355 }
356 }
357
358 while (code >= clearCode) {
359 if ((code >= MAX_BITS) || (code == mGIFStruct.prefix[code])) {
360 return MakeTuple(written, Some(WriteState::FAILURE));
361 }
362
363 *mGIFStruct.stackp++ = mGIFStruct.suffix[code];
364 code = mGIFStruct.prefix[code];
365
366 if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) {
367 // Stack overflow; something's wrong.
368 return MakeTuple(written, Some(WriteState::FAILURE));
369 }
370 }
371
372 *mGIFStruct.stackp++ = mGIFStruct.firstchar = mGIFStruct.suffix[code];
373
374 // Define a new codeword in the dictionary.
375 if (mGIFStruct.avail < 4096) {
376 mGIFStruct.prefix[mGIFStruct.avail] = mGIFStruct.oldcode;
377 mGIFStruct.suffix[mGIFStruct.avail] = mGIFStruct.firstchar;
378 mGIFStruct.avail++;
379
380 // If we've used up all the codewords of a given length increase the
381 // length of codewords by one bit, but don't exceed the specified
382 // maximum codeword size of 12 bits.
383 if (((mGIFStruct.avail & mGIFStruct.codemask) == 0) &&
384 (mGIFStruct.avail < 4096)) {
385 mGIFStruct.codesize++;
386 mGIFStruct.codemask += mGIFStruct.avail;
387 }
388 }
389
390 mGIFStruct.oldcode = incode;
391 }
392
393 if (MOZ_UNLIKELY(mGIFStruct.stackp <= mGIFStruct.stack)) {
394 MOZ_ASSERT_UNREACHABLE("No decoded data but we didn't return early?");
395 return MakeTuple(written, Some(WriteState::FAILURE));
396 }
397
398 // Yield a pixel at the appropriate index in the colormap.
399 mGIFStruct.pixels_remaining--;
400 aPixelBlock[written++] =
401 ColormapIndexToPixel<PixelSize>(*--mGIFStruct.stackp);
402 }
403
404 return MakeTuple(written, Maybe<WriteState>());
405 }
406
407 /// Expand the colormap from RGB to Packed ARGB as needed by Cairo.
408 /// And apply any LCMS transformation.
ConvertColormap(uint32_t * aColormap,uint32_t aColors)409 void nsGIFDecoder2::ConvertColormap(uint32_t* aColormap, uint32_t aColors) {
410 if (!aColors) {
411 return;
412 }
413
414 // Apply CMS transformation if enabled and available
415 if (mCMSMode == CMSMode::All) {
416 qcms_transform* transform = GetCMSsRGBTransform(SurfaceFormat::R8G8B8);
417 if (transform) {
418 qcms_transform_data(transform, aColormap, aColormap, aColors);
419 }
420 }
421
422 // Expand color table from RGB to BGRA.
423 MOZ_ASSERT(mSwizzleFn);
424 uint8_t* data = reinterpret_cast<uint8_t*>(aColormap);
425 mSwizzleFn(data, data, aColors);
426 #if MOZ_BIG_ENDIAN()
427 SwizzleRow(SurfaceFormat::A8R8G8B8, SurfaceFormat::B8G8R8A8)(data, data, aColors);
428 #endif
429 }
430
DoDecode(SourceBufferIterator & aIterator,IResumable * aOnResume)431 LexerResult nsGIFDecoder2::DoDecode(SourceBufferIterator& aIterator,
432 IResumable* aOnResume) {
433 MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
434
435 return mLexer.Lex(
436 aIterator, aOnResume,
437 [=](State aState, const char* aData, size_t aLength) {
438 switch (aState) {
439 case State::GIF_HEADER:
440 return ReadGIFHeader(aData);
441 case State::SCREEN_DESCRIPTOR:
442 return ReadScreenDescriptor(aData);
443 case State::GLOBAL_COLOR_TABLE:
444 return ReadGlobalColorTable(aData, aLength);
445 case State::FINISHED_GLOBAL_COLOR_TABLE:
446 return FinishedGlobalColorTable();
447 case State::BLOCK_HEADER:
448 return ReadBlockHeader(aData);
449 case State::EXTENSION_HEADER:
450 return ReadExtensionHeader(aData);
451 case State::GRAPHIC_CONTROL_EXTENSION:
452 return ReadGraphicControlExtension(aData);
453 case State::APPLICATION_IDENTIFIER:
454 return ReadApplicationIdentifier(aData);
455 case State::NETSCAPE_EXTENSION_SUB_BLOCK:
456 return ReadNetscapeExtensionSubBlock(aData);
457 case State::NETSCAPE_EXTENSION_DATA:
458 return ReadNetscapeExtensionData(aData);
459 case State::IMAGE_DESCRIPTOR:
460 return ReadImageDescriptor(aData);
461 case State::FINISH_IMAGE_DESCRIPTOR:
462 return FinishImageDescriptor(aData);
463 case State::LOCAL_COLOR_TABLE:
464 return ReadLocalColorTable(aData, aLength);
465 case State::FINISHED_LOCAL_COLOR_TABLE:
466 return FinishedLocalColorTable();
467 case State::IMAGE_DATA_BLOCK:
468 return ReadImageDataBlock(aData);
469 case State::IMAGE_DATA_SUB_BLOCK:
470 return ReadImageDataSubBlock(aData);
471 case State::LZW_DATA:
472 return ReadLZWData(aData, aLength);
473 case State::SKIP_LZW_DATA:
474 return Transition::ContinueUnbuffered(State::SKIP_LZW_DATA);
475 case State::FINISHED_LZW_DATA:
476 return Transition::To(State::IMAGE_DATA_SUB_BLOCK,
477 SUB_BLOCK_HEADER_LEN);
478 case State::SKIP_SUB_BLOCKS:
479 return SkipSubBlocks(aData);
480 case State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS:
481 return Transition::ContinueUnbuffered(
482 State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS);
483 case State::FINISHED_SKIPPING_DATA:
484 return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
485 default:
486 MOZ_CRASH("Unknown State");
487 }
488 });
489 }
490
ReadGIFHeader(const char * aData)491 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadGIFHeader(
492 const char* aData) {
493 // We retrieve the version here but because many GIF encoders set header
494 // fields incorrectly, we barely use it; features which should only appear in
495 // GIF89a are always accepted.
496 if (strncmp(aData, "GIF87a", GIF_HEADER_LEN) == 0) {
497 mGIFStruct.version = 87;
498 } else if (strncmp(aData, "GIF89a", GIF_HEADER_LEN) == 0) {
499 mGIFStruct.version = 89;
500 } else {
501 return Transition::TerminateFailure();
502 }
503
504 return Transition::To(State::SCREEN_DESCRIPTOR, GIF_SCREEN_DESCRIPTOR_LEN);
505 }
506
ReadScreenDescriptor(const char * aData)507 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadScreenDescriptor(
508 const char* aData) {
509 mGIFStruct.screen_width = LittleEndian::readUint16(aData + 0);
510 mGIFStruct.screen_height = LittleEndian::readUint16(aData + 2);
511
512 const uint8_t packedFields = aData[4];
513
514 // XXX: Should we be capturing these values even if there is no global color
515 // table?
516 mGIFStruct.global_colormap_depth =
517 (packedFields & PACKED_FIELDS_TABLE_DEPTH_MASK) + 1;
518 mGIFStruct.global_colormap_count = 1 << mGIFStruct.global_colormap_depth;
519
520 // We ignore several fields in the header. We don't care about the 'sort
521 // flag', which indicates if the global color table's entries are sorted in
522 // order of importance - if we need to render this image for a device with a
523 // narrower color gamut than GIF supports we'll handle that at a different
524 // layer. We have no use for the pixel aspect ratio as well. Finally, we
525 // intentionally ignore the background color index, as implementing that
526 // feature would not be web compatible - when a GIF image frame doesn't cover
527 // the entire area of the image, the area that's not covered should always be
528 // transparent.
529
530 if (packedFields & PACKED_FIELDS_COLOR_TABLE_BIT) {
531 MOZ_ASSERT(mColorTablePos == 0);
532
533 // We read the global color table in unbuffered mode since it can be quite
534 // large and it'd be preferable to avoid unnecessary copies.
535 const size_t globalColorTableSize = 3 * mGIFStruct.global_colormap_count;
536 return Transition::ToUnbuffered(State::FINISHED_GLOBAL_COLOR_TABLE,
537 State::GLOBAL_COLOR_TABLE,
538 globalColorTableSize);
539 }
540
541 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
542 }
543
ReadGlobalColorTable(const char * aData,size_t aLength)544 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadGlobalColorTable(
545 const char* aData, size_t aLength) {
546 uint8_t* dest =
547 reinterpret_cast<uint8_t*>(mGIFStruct.global_colormap) + mColorTablePos;
548 memcpy(dest, aData, aLength);
549 mColorTablePos += aLength;
550 return Transition::ContinueUnbuffered(State::GLOBAL_COLOR_TABLE);
551 }
552
553 LexerTransition<nsGIFDecoder2::State>
FinishedGlobalColorTable()554 nsGIFDecoder2::FinishedGlobalColorTable() {
555 ConvertColormap(mGIFStruct.global_colormap, mGIFStruct.global_colormap_count);
556 mColorTablePos = 0;
557 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
558 }
559
ReadBlockHeader(const char * aData)560 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadBlockHeader(
561 const char* aData) {
562 // Determine what type of block we're dealing with.
563 switch (aData[0]) {
564 case GIF_EXTENSION_INTRODUCER:
565 return Transition::To(State::EXTENSION_HEADER, EXTENSION_HEADER_LEN);
566
567 case GIF_IMAGE_SEPARATOR:
568 return Transition::To(State::IMAGE_DESCRIPTOR, IMAGE_DESCRIPTOR_LEN);
569
570 case GIF_TRAILER:
571 FinishInternal();
572 return Transition::TerminateSuccess();
573
574 default:
575 // If we get anything other than GIF_IMAGE_SEPARATOR,
576 // GIF_EXTENSION_INTRODUCER, or GIF_TRAILER, there is extraneous data
577 // between blocks. The GIF87a spec tells us to keep reading until we find
578 // an image separator, but GIF89a says such a file is corrupt. We follow
579 // GIF89a and bail out.
580
581 if (mGIFStruct.images_decoded > 0) {
582 // The file is corrupt, but we successfully decoded some frames, so we
583 // may as well consider the decode successful and display them.
584 FinishInternal();
585 return Transition::TerminateSuccess();
586 }
587
588 // No images decoded; there is nothing to display.
589 return Transition::TerminateFailure();
590 }
591 }
592
ReadExtensionHeader(const char * aData)593 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadExtensionHeader(
594 const char* aData) {
595 const uint8_t label = aData[0];
596 const uint8_t extensionHeaderLength = aData[1];
597
598 // If the extension header is zero length, just treat it as a block terminator
599 // and move on to the next block immediately.
600 if (extensionHeaderLength == 0) {
601 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
602 }
603
604 switch (label) {
605 case GIF_GRAPHIC_CONTROL_LABEL:
606 // The GIF spec mandates that the Control Extension header block length is
607 // 4 bytes, and the parser for this block reads 4 bytes, so we must
608 // enforce that the buffer contains at least this many bytes. If the GIF
609 // specifies a different length, we allow that, so long as it's larger;
610 // the additional data will simply be ignored.
611 return Transition::To(
612 State::GRAPHIC_CONTROL_EXTENSION,
613 max<uint8_t>(extensionHeaderLength, GRAPHIC_CONTROL_EXTENSION_LEN));
614
615 case GIF_APPLICATION_EXTENSION_LABEL:
616 // Again, the spec specifies that an application extension header is 11
617 // bytes, but for compatibility with GIFs in the wild, we allow deviation
618 // from the spec. This is important for real-world compatibility, as GIFs
619 // in the wild exist with application extension headers that are both
620 // shorter and longer than 11 bytes. However, we only try to actually
621 // interpret the application extension if the length is correct;
622 // otherwise, we just skip the block unconditionally.
623 return extensionHeaderLength == APPLICATION_EXTENSION_LEN
624 ? Transition::To(State::APPLICATION_IDENTIFIER,
625 extensionHeaderLength)
626 : Transition::ToUnbuffered(
627 State::FINISHED_SKIPPING_DATA,
628 State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
629 extensionHeaderLength);
630
631 default:
632 // Skip over any other type of extension block, including comment and
633 // plain text blocks.
634 return Transition::ToUnbuffered(State::FINISHED_SKIPPING_DATA,
635 State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
636 extensionHeaderLength);
637 }
638 }
639
640 LexerTransition<nsGIFDecoder2::State>
ReadGraphicControlExtension(const char * aData)641 nsGIFDecoder2::ReadGraphicControlExtension(const char* aData) {
642 mGIFStruct.is_transparent = aData[0] & 0x1;
643 mGIFStruct.tpixel = uint8_t(aData[3]);
644 mGIFStruct.disposal_method = (aData[0] >> 2) & 0x7;
645
646 if (mGIFStruct.disposal_method == 4) {
647 // Some encoders (and apparently some specs) represent
648 // DisposalMethod::RESTORE_PREVIOUS as 4, but 3 is used in the canonical
649 // spec and is more popular, so we normalize to 3.
650 mGIFStruct.disposal_method = 3;
651 } else if (mGIFStruct.disposal_method > 4) {
652 // This GIF is using a disposal method which is undefined in the spec.
653 // Treat it as DisposalMethod::NOT_SPECIFIED.
654 mGIFStruct.disposal_method = 0;
655 }
656
657 DisposalMethod method = DisposalMethod(mGIFStruct.disposal_method);
658 if (method == DisposalMethod::CLEAR_ALL || method == DisposalMethod::CLEAR) {
659 // We may have to display the background under this image during animation
660 // playback, so we regard it as transparent.
661 PostHasTransparency();
662 }
663
664 mGIFStruct.delay_time = LittleEndian::readUint16(aData + 1) * 10;
665 if (!HasAnimation() && mGIFStruct.delay_time > 0) {
666 PostIsAnimated(FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time));
667 }
668
669 return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
670 }
671
ReadApplicationIdentifier(const char * aData)672 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadApplicationIdentifier(
673 const char* aData) {
674 if ((strncmp(aData, "NETSCAPE2.0", 11) == 0) ||
675 (strncmp(aData, "ANIMEXTS1.0", 11) == 0)) {
676 // This is a Netscape application extension block.
677 return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
678 SUB_BLOCK_HEADER_LEN);
679 }
680
681 // This is an application extension we don't care about. Just skip it.
682 return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
683 }
684
685 LexerTransition<nsGIFDecoder2::State>
ReadNetscapeExtensionSubBlock(const char * aData)686 nsGIFDecoder2::ReadNetscapeExtensionSubBlock(const char* aData) {
687 const uint8_t blockLength = aData[0];
688 if (blockLength == 0) {
689 // We hit the block terminator.
690 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
691 }
692
693 // We consume a minimum of 3 bytes in accordance with the specs for the
694 // Netscape application extension block, such as they are.
695 const size_t extensionLength = max<uint8_t>(blockLength, 3);
696 return Transition::To(State::NETSCAPE_EXTENSION_DATA, extensionLength);
697 }
698
ReadNetscapeExtensionData(const char * aData)699 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadNetscapeExtensionData(
700 const char* aData) {
701 // Documentation for NETSCAPE2.0 / ANIMEXTS1.0 extensions can be found at:
702 // https://wiki.whatwg.org/wiki/GIF
703 static const uint8_t NETSCAPE_LOOPING_EXTENSION_SUB_BLOCK_ID = 1;
704 static const uint8_t NETSCAPE_BUFFERING_EXTENSION_SUB_BLOCK_ID = 2;
705
706 const uint8_t subBlockID = aData[0] & 7;
707 switch (subBlockID) {
708 case NETSCAPE_LOOPING_EXTENSION_SUB_BLOCK_ID:
709 // This is looping extension.
710 mGIFStruct.loop_count = LittleEndian::readUint16(aData + 1);
711 // Zero loop count is infinite animation loop request.
712 if (mGIFStruct.loop_count == 0) {
713 mGIFStruct.loop_count = -1;
714 }
715
716 return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
717 SUB_BLOCK_HEADER_LEN);
718
719 case NETSCAPE_BUFFERING_EXTENSION_SUB_BLOCK_ID:
720 // We allow, but ignore, this extension.
721 return Transition::To(State::NETSCAPE_EXTENSION_SUB_BLOCK,
722 SUB_BLOCK_HEADER_LEN);
723
724 default:
725 return Transition::TerminateFailure();
726 }
727 }
728
ReadImageDescriptor(const char * aData)729 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDescriptor(
730 const char* aData) {
731 // On the first frame, we don't need to yield, and none of the other checks
732 // below apply, so we can just jump right into FinishImageDescriptor().
733 if (mGIFStruct.images_decoded == 0) {
734 return FinishImageDescriptor(aData);
735 }
736
737 if (!HasAnimation()) {
738 // We should've already called PostIsAnimated(); this must be a corrupt
739 // animated image with a first frame timeout of zero. Signal that we're
740 // animated now, before the first-frame decode early exit below, so that
741 // RasterImage can detect that this happened.
742 PostIsAnimated(FrameTimeout::FromRawMilliseconds(0));
743 }
744
745 if (IsFirstFrameDecode()) {
746 // We're about to get a second frame, but we only want the first. Stop
747 // decoding now.
748 FinishInternal();
749 return Transition::TerminateSuccess();
750 }
751
752 MOZ_ASSERT(Size() == OutputSize(), "Downscaling an animated image?");
753
754 // Yield to allow access to the previous frame before we start a new one.
755 return Transition::ToAfterYield(State::FINISH_IMAGE_DESCRIPTOR);
756 }
757
FinishImageDescriptor(const char * aData)758 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishImageDescriptor(
759 const char* aData) {
760 IntRect frameRect;
761
762 // Get image offsets with respect to the screen origin.
763 frameRect.SetRect(
764 LittleEndian::readUint16(aData + 0), LittleEndian::readUint16(aData + 2),
765 LittleEndian::readUint16(aData + 4), LittleEndian::readUint16(aData + 6));
766
767 if (!mGIFStruct.images_decoded) {
768 // Work around GIF files where
769 // * at least one of the logical screen dimensions is smaller than the
770 // same dimension in the first image, or
771 // * GIF87a files where the first image's dimensions do not match the
772 // logical screen dimensions.
773 if (mGIFStruct.screen_height < frameRect.Height() ||
774 mGIFStruct.screen_width < frameRect.Width() ||
775 mGIFStruct.version == 87) {
776 mGIFStruct.screen_height = frameRect.Height();
777 mGIFStruct.screen_width = frameRect.Width();
778 frameRect.MoveTo(0, 0);
779 }
780
781 // Create the image container with the right size.
782 BeginGIF();
783 if (HasError()) {
784 // Setting the size led to an error.
785 return Transition::TerminateFailure();
786 }
787
788 // If we're doing a metadata decode, we're done.
789 if (IsMetadataDecode()) {
790 CheckForTransparency(frameRect);
791 FinishInternal();
792 return Transition::TerminateSuccess();
793 }
794 }
795
796 // Work around broken GIF files that have zero frame width or height; in this
797 // case, we'll treat the frame as having the same size as the overall image.
798 if (frameRect.Height() == 0 || frameRect.Width() == 0) {
799 frameRect.SetHeight(mGIFStruct.screen_height);
800 frameRect.SetWidth(mGIFStruct.screen_width);
801
802 // If that still resulted in zero frame width or height, give up.
803 if (frameRect.Height() == 0 || frameRect.Width() == 0) {
804 return Transition::TerminateFailure();
805 }
806 }
807
808 // Determine |depth| (log base 2 of the number of colors in the palette).
809 bool haveLocalColorTable = false;
810 uint16_t depth = 0;
811 uint8_t packedFields = aData[8];
812
813 if (packedFields & PACKED_FIELDS_COLOR_TABLE_BIT) {
814 // Get the palette depth from the local color table.
815 depth = (packedFields & PACKED_FIELDS_TABLE_DEPTH_MASK) + 1;
816 haveLocalColorTable = true;
817 } else {
818 // Get the palette depth from the global color table.
819 depth = mGIFStruct.global_colormap_depth;
820 }
821
822 // If the transparent color index is greater than the number of colors in the
823 // color table, we may need a higher color depth than |depth| would specify.
824 // Our internal representation of the image will instead use |realDepth|,
825 // which is the smallest color depth that can accommodate the existing palette
826 // *and* the transparent color index.
827 uint16_t realDepth = depth;
828 while (mGIFStruct.tpixel >= (1 << realDepth) && realDepth < 8) {
829 realDepth++;
830 }
831
832 // Create a mask used to ensure that color values fit within the colormap.
833 mColorMask = 0xFF >> (8 - realDepth);
834
835 // Determine if this frame is interlaced or not.
836 const bool isInterlaced = packedFields & PACKED_FIELDS_INTERLACED_BIT;
837
838 // Create the SurfacePipe we'll use to write output for this frame.
839 if (NS_FAILED(BeginImageFrame(frameRect, realDepth, isInterlaced))) {
840 return Transition::TerminateFailure();
841 }
842
843 // Clear state from last image.
844 mGIFStruct.pixels_remaining =
845 int64_t(frameRect.Width()) * int64_t(frameRect.Height());
846
847 if (haveLocalColorTable) {
848 // We have a local color table, so prepare to read it into the palette of
849 // the current frame.
850 mGIFStruct.local_colormap_size = 1 << depth;
851
852 if (!mColormap) {
853 // Ensure our current colormap buffer is large enough to hold the new one.
854 mColormapSize = sizeof(uint32_t) << realDepth;
855 if (mGIFStruct.local_colormap_buffer_size < mColormapSize) {
856 if (mGIFStruct.local_colormap) {
857 free(mGIFStruct.local_colormap);
858 }
859 mGIFStruct.local_colormap_buffer_size = mColormapSize;
860 mGIFStruct.local_colormap =
861 static_cast<uint32_t*>(moz_xmalloc(mColormapSize));
862 // Ensure the local colormap is initialized as opaque.
863 memset(mGIFStruct.local_colormap, 0xFF, mColormapSize);
864 } else {
865 mColormapSize = mGIFStruct.local_colormap_buffer_size;
866 }
867
868 mColormap = mGIFStruct.local_colormap;
869 }
870
871 MOZ_ASSERT(mColormap);
872
873 const size_t size = 3 << depth;
874 if (mColormapSize > size) {
875 // Clear the part of the colormap which will be unused with this palette.
876 // If a GIF references an invalid palette entry, ensure the entry is
877 // opaque white. This is needed for Skia as if it isn't, RGBX surfaces
878 // will cause blending issues with Skia.
879 memset(reinterpret_cast<uint8_t*>(mColormap) + size, 0xFF,
880 mColormapSize - size);
881 }
882
883 MOZ_ASSERT(mColorTablePos == 0);
884
885 // We read the local color table in unbuffered mode since it can be quite
886 // large and it'd be preferable to avoid unnecessary copies.
887 return Transition::ToUnbuffered(State::FINISHED_LOCAL_COLOR_TABLE,
888 State::LOCAL_COLOR_TABLE, size);
889 }
890
891 // There's no local color table; copy the global color table into the palette
892 // of the current frame.
893 if (mColormap) {
894 memcpy(mColormap, mGIFStruct.global_colormap, mColormapSize);
895 } else {
896 mColormap = mGIFStruct.global_colormap;
897 }
898
899 return Transition::To(State::IMAGE_DATA_BLOCK, BLOCK_HEADER_LEN);
900 }
901
ReadLocalColorTable(const char * aData,size_t aLength)902 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadLocalColorTable(
903 const char* aData, size_t aLength) {
904 uint8_t* dest = reinterpret_cast<uint8_t*>(mColormap) + mColorTablePos;
905 memcpy(dest, aData, aLength);
906 mColorTablePos += aLength;
907 return Transition::ContinueUnbuffered(State::LOCAL_COLOR_TABLE);
908 }
909
FinishedLocalColorTable()910 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::FinishedLocalColorTable() {
911 ConvertColormap(mColormap, mGIFStruct.local_colormap_size);
912 mColorTablePos = 0;
913 return Transition::To(State::IMAGE_DATA_BLOCK, BLOCK_HEADER_LEN);
914 }
915
ReadImageDataBlock(const char * aData)916 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDataBlock(
917 const char* aData) {
918 // Make sure the transparent pixel is transparent in the colormap.
919 if (mGIFStruct.is_transparent) {
920 // Save the old value so we can restore it later.
921 if (mColormap == mGIFStruct.global_colormap) {
922 mOldColor = mColormap[mGIFStruct.tpixel];
923 }
924 mColormap[mGIFStruct.tpixel] = 0;
925 }
926
927 // Initialize the LZW decoder.
928 mGIFStruct.datasize = uint8_t(aData[0]);
929 if (mGIFStruct.datasize > MAX_LZW_BITS) {
930 return Transition::TerminateFailure();
931 }
932 const int clearCode = ClearCode();
933 if (clearCode >= MAX_BITS) {
934 return Transition::TerminateFailure();
935 }
936
937 mGIFStruct.avail = clearCode + 2;
938 mGIFStruct.oldcode = -1;
939 mGIFStruct.codesize = mGIFStruct.datasize + 1;
940 mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1;
941 mGIFStruct.datum = mGIFStruct.bits = 0;
942
943 // Initialize the tables.
944 for (int i = 0; i < clearCode; i++) {
945 mGIFStruct.suffix[i] = i;
946 }
947
948 mGIFStruct.stackp = mGIFStruct.stack;
949
950 // Begin reading image data sub-blocks.
951 return Transition::To(State::IMAGE_DATA_SUB_BLOCK, SUB_BLOCK_HEADER_LEN);
952 }
953
ReadImageDataSubBlock(const char * aData)954 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadImageDataSubBlock(
955 const char* aData) {
956 const uint8_t subBlockLength = aData[0];
957 if (subBlockLength == 0) {
958 // We hit the block terminator.
959 EndImageFrame();
960 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
961 }
962
963 if (mGIFStruct.pixels_remaining == 0) {
964 // We've already written to the entire image; we should've hit the block
965 // terminator at this point. This image is corrupt, but we'll tolerate it.
966
967 if (subBlockLength == GIF_TRAILER) {
968 // This GIF is missing the block terminator for the final block; we'll put
969 // up with it.
970 FinishInternal();
971 return Transition::TerminateSuccess();
972 }
973
974 // We're not at the end of the image, so just skip the extra data.
975 return Transition::ToUnbuffered(State::FINISHED_LZW_DATA,
976 State::SKIP_LZW_DATA, subBlockLength);
977 }
978
979 // Handle the standard case: there's data in the sub-block and pixels left to
980 // fill in the image. We read the sub-block unbuffered so we can get pixels on
981 // the screen as soon as possible.
982 return Transition::ToUnbuffered(State::FINISHED_LZW_DATA, State::LZW_DATA,
983 subBlockLength);
984 }
985
ReadLZWData(const char * aData,size_t aLength)986 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::ReadLZWData(
987 const char* aData, size_t aLength) {
988 const uint8_t* data = reinterpret_cast<const uint8_t*>(aData);
989 size_t length = aLength;
990
991 while (mGIFStruct.pixels_remaining > 0 &&
992 (length > 0 || mGIFStruct.bits >= mGIFStruct.codesize)) {
993 size_t bytesRead = 0;
994
995 auto result = mPipe.WritePixelBlocks<uint32_t>(
996 [&](uint32_t* aPixelBlock, int32_t aBlockSize) {
997 return YieldPixels<uint32_t>(data, length, &bytesRead, aPixelBlock,
998 aBlockSize);
999 });
1000
1001 if (MOZ_UNLIKELY(bytesRead > length)) {
1002 MOZ_ASSERT_UNREACHABLE("Overread?");
1003 bytesRead = length;
1004 }
1005
1006 // Advance our position in the input based upon what YieldPixel() consumed.
1007 data += bytesRead;
1008 length -= bytesRead;
1009
1010 switch (result) {
1011 case WriteState::NEED_MORE_DATA:
1012 continue;
1013
1014 case WriteState::FINISHED:
1015 NS_WARNING_ASSERTION(mGIFStruct.pixels_remaining <= 0,
1016 "too many pixels");
1017 mGIFStruct.pixels_remaining = 0;
1018 break;
1019
1020 case WriteState::FAILURE:
1021 return Transition::TerminateFailure();
1022 }
1023 }
1024
1025 // We're done, but keep going until we consume all the data in the sub-block.
1026 return Transition::ContinueUnbuffered(State::LZW_DATA);
1027 }
1028
SkipSubBlocks(const char * aData)1029 LexerTransition<nsGIFDecoder2::State> nsGIFDecoder2::SkipSubBlocks(
1030 const char* aData) {
1031 // In the SKIP_SUB_BLOCKS state we skip over data sub-blocks that we're not
1032 // interested in. Blocks consist of a block header (which can be up to 255
1033 // bytes in length) and a series of data sub-blocks. Each data sub-block
1034 // consists of a single byte length value, followed by the data itself. A data
1035 // sub-block with a length of zero terminates the overall block.
1036 // SKIP_SUB_BLOCKS reads a sub-block length value. If it's zero, we've arrived
1037 // at the next block. Otherwise, we enter the SKIP_DATA_THEN_SKIP_SUB_BLOCKS
1038 // state to skip over the sub-block data and return to SKIP_SUB_BLOCKS at the
1039 // start of the next sub-block.
1040
1041 const uint8_t nextSubBlockLength = aData[0];
1042 if (nextSubBlockLength == 0) {
1043 // We hit the block terminator, so the sequence of data sub-blocks is over;
1044 // begin processing another block.
1045 return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
1046 }
1047
1048 // Skip to the next sub-block length value.
1049 return Transition::ToUnbuffered(State::FINISHED_SKIPPING_DATA,
1050 State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
1051 nextSubBlockLength);
1052 }
1053
SpeedHistogram() const1054 Maybe<Telemetry::HistogramID> nsGIFDecoder2::SpeedHistogram() const {
1055 return Some(Telemetry::IMAGE_DECODE_SPEED_GIF);
1056 }
1057
1058 } // namespace image
1059 } // namespace mozilla
1060