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