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

Side by Side Diff: src/codec/SkCodec_libgif.cpp

Issue 1301393010: Some codec code formatting cleanup. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 3 months 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
« no previous file with comments | « src/codec/SkBmpRLECodec.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodec_libgif.h" 8 #include "SkCodec_libgif.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkColorTable.h" 11 #include "SkColorTable.h"
12 #include "SkGifInterlaceIter.h" 12 #include "SkGifInterlaceIter.h"
13 #include "SkStream.h" 13 #include "SkStream.h"
14 #include "SkSwizzler.h" 14 #include "SkSwizzler.h"
15 #include "SkUtils.h" 15 #include "SkUtils.h"
16 16
17 /* 17 /*
18 * Checks the start of the stream to see if the image is a gif 18 * Checks the start of the stream to see if the image is a gif
19 */ 19 */
20 bool SkGifCodec::IsGif(SkStream* stream) { 20 bool SkGifCodec::IsGif(SkStream* stream) {
21 char buf[GIF_STAMP_LEN]; 21 char buf[GIF_STAMP_LEN];
22 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { 22 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
23 if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 || 23 if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 ||
24 memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 || 24 memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
25 memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) { 25 memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0)
26 {
26 return true; 27 return true;
27 } 28 }
28 } 29 }
29 return false; 30 return false;
30 } 31 }
31 32
32 /* 33 /*
33 * Warning reporting function 34 * Warning reporting function
34 */ 35 */
35 static void gif_warning(const char* msg) { 36 static void gif_warning(const char* msg) {
36 SkCodecPrintf("Gif Warning: %s\n", msg); 37 SkCodecPrintf("Gif Warning: %s\n", msg);
37 } 38 }
38 39
39 /* 40 /*
40 * Error function 41 * Error function
41 */ 42 */
42 static SkCodec::Result gif_error(const char* msg, 43 static SkCodec::Result gif_error(const char* msg, SkCodec::Result result = SkCod ec::kInvalidInput) {
43 SkCodec::Result result = SkCodec::kInvalidInput) {
44 SkCodecPrintf("Gif Error: %s\n", msg); 44 SkCodecPrintf("Gif Error: %s\n", msg);
45 return result; 45 return result;
46 } 46 }
47 47
48 48
49 /* 49 /*
50 * Read function that will be passed to gif_lib 50 * Read function that will be passed to gif_lib
51 */ 51 */
52 static int32_t read_bytes_callback(GifFileType* fileType, GifByteType* out, 52 static int32_t read_bytes_callback(GifFileType* fileType, GifByteType* out, int3 2_t size) {
53 int32_t size) {
54 SkStream* stream = (SkStream*) fileType->UserData; 53 SkStream* stream = (SkStream*) fileType->UserData;
55 return (int32_t) stream->read(out, size); 54 return (int32_t) stream->read(out, size);
56 } 55 }
57 56
58 /* 57 /*
59 * Open the gif file 58 * Open the gif file
60 */ 59 */
61 static GifFileType* open_gif(SkStream* stream) { 60 static GifFileType* open_gif(SkStream* stream) {
62 return DGifOpen(stream, read_bytes_callback, nullptr); 61 return DGifOpen(stream, read_bytes_callback, nullptr);
63 } 62 }
(...skipping 25 matching lines...) Expand all
89 // to check the most recent extension blocks first. 88 // to check the most recent extension blocks first.
90 for (int32_t i = image.ExtensionBlockCount - 1; i >= 0; i--) { 89 for (int32_t i = image.ExtensionBlockCount - 1; i >= 0; i--) {
91 // Get an extension block 90 // Get an extension block
92 const ExtensionBlock& extBlock = image.ExtensionBlocks[i]; 91 const ExtensionBlock& extBlock = image.ExtensionBlocks[i];
93 92
94 // Specifically, we need to check for a graphics control extension, 93 // Specifically, we need to check for a graphics control extension,
95 // which may contain transparency information. Also, note that a valid 94 // which may contain transparency information. Also, note that a valid
96 // graphics control extension is always four bytes. The fourth byte 95 // graphics control extension is always four bytes. The fourth byte
97 // is the transparent index (if it exists), so we need at least four 96 // is the transparent index (if it exists), so we need at least four
98 // bytes. 97 // bytes.
99 if (GRAPHICS_EXT_FUNC_CODE == extBlock.Function && 98 if (GRAPHICS_EXT_FUNC_CODE == extBlock.Function && extBlock.ByteCount >= 4) {
100 extBlock.ByteCount >= 4) {
101 99
102 // Check the transparent color flag which indicates whether a 100 // Check the transparent color flag which indicates whether a
103 // transparent index exists. It is the least significant bit of 101 // transparent index exists. It is the least significant bit of
104 // the first byte of the extension block. 102 // the first byte of the extension block.
105 if (1 == (extBlock.Bytes[0] & 1)) { 103 if (1 == (extBlock.Bytes[0] & 1)) {
106 104
107 // Use uint32_t to prevent sign extending 105 // Use uint32_t to prevent sign extending
108 return extBlock.Bytes[3]; 106 return extBlock.Bytes[3];
109 } 107 }
110 108
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 // the default. 160 // the default.
163 // Many gifs specify a color table index for transparent pixels. Every 161 // Many gifs specify a color table index for transparent pixels. Every
164 // other pixel is guaranteed to be opaque. Despite this, because of the 162 // other pixel is guaranteed to be opaque. Despite this, because of the
165 // possiblity of transparent pixels, we cannot assume that the image is 163 // possiblity of transparent pixels, we cannot assume that the image is
166 // opaque. We have the option to set the alpha type as kPremul or 164 // opaque. We have the option to set the alpha type as kPremul or
167 // kUnpremul. Both are valid since the alpha component will always be 165 // kUnpremul. Both are valid since the alpha component will always be
168 // 0xFF or the entire 32-bit pixel will be set to zero. We prefer 166 // 0xFF or the entire 32-bit pixel will be set to zero. We prefer
169 // kPremul because we support kPremul, and it is more efficient to 167 // kPremul because we support kPremul, and it is more efficient to
170 // use kPremul directly even when kUnpremul is supported. 168 // use kPremul directly even when kUnpremul is supported.
171 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 169 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
172 kIndex_8_SkColorType, kPremul_SkAlphaType); 170 kIndex_8_SkColorType, k Premul_SkAlphaType);
173 *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach ()); 171 *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach ());
174 } else { 172 } else {
175 SkASSERT(nullptr != gifOut); 173 SkASSERT(nullptr != gifOut);
176 streamDeleter.detach(); 174 streamDeleter.detach();
177 *gifOut = gif.detach(); 175 *gifOut = gif.detach();
178 } 176 }
179 return true; 177 return true;
180 } 178 }
181 179
182 /* 180 /*
183 * Assumes IsGif was called and returned true 181 * Assumes IsGif was called and returned true
184 * Creates a gif decoder 182 * Creates a gif decoder
185 * Reads enough of the stream to determine the image format 183 * Reads enough of the stream to determine the image format
186 */ 184 */
187 SkCodec* SkGifCodec::NewFromStream(SkStream* stream) { 185 SkCodec* SkGifCodec::NewFromStream(SkStream* stream) {
188 SkCodec* codec = nullptr; 186 SkCodec* codec = nullptr;
189 if (ReadHeader(stream, &codec, nullptr)) { 187 if (ReadHeader(stream, &codec, nullptr)) {
190 return codec; 188 return codec;
191 } 189 }
192 return nullptr; 190 return nullptr;
193 } 191 }
194 192
195 SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, 193 SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType * gif)
196 GifFileType* gif)
197 : INHERITED(srcInfo, stream) 194 : INHERITED(srcInfo, stream)
198 , fGif(gif) 195 , fGif(gif)
199 {} 196 {}
200 197
201 bool SkGifCodec::onRewind() { 198 bool SkGifCodec::onRewind() {
202 GifFileType* gifOut = nullptr; 199 GifFileType* gifOut = nullptr;
203 if (!ReadHeader(this->stream(), nullptr, &gifOut)) { 200 if (!ReadHeader(this->stream(), nullptr, &gifOut)) {
204 return false; 201 return false;
205 } 202 }
206 203
(...skipping 17 matching lines...) Expand all
224 221
225 // Check for valid input parameters 222 // Check for valid input parameters
226 if (opts.fSubset) { 223 if (opts.fSubset) {
227 // Subsets are not supported. 224 // Subsets are not supported.
228 return kUnimplemented; 225 return kUnimplemented;
229 } 226 }
230 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 227 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
231 return gif_error("Scaling not supported.\n", kInvalidScale); 228 return gif_error("Scaling not supported.\n", kInvalidScale);
232 } 229 }
233 if (!conversion_possible(dstInfo, this->getInfo())) { 230 if (!conversion_possible(dstInfo, this->getInfo())) {
234 return gif_error("Cannot convert input type to output type.\n", 231 return gif_error("Cannot convert input type to output type.\n", kInvalid Conversion);
235 kInvalidConversion);
236 } 232 }
237 233
238 // Use this as a container to hold information about any gif extension 234 // Use this as a container to hold information about any gif extension
239 // blocks. This generally stores transparency and animation instructions. 235 // blocks. This generally stores transparency and animation instructions.
240 SavedImage saveExt; 236 SavedImage saveExt;
241 SkAutoTCallVProc<SavedImage, FreeExtension> autoFreeExt(&saveExt); 237 SkAutoTCallVProc<SavedImage, FreeExtension> autoFreeExt(&saveExt);
242 saveExt.ExtensionBlocks = nullptr; 238 saveExt.ExtensionBlocks = nullptr;
243 saveExt.ExtensionBlockCount = 0; 239 saveExt.ExtensionBlockCount = 0;
244 GifByteType* extData; 240 GifByteType* extData;
245 int32_t extFunction; 241 int32_t extFunction;
246 242
247 // We will loop over components of gif images until we find an image. Once 243 // We will loop over components of gif images until we find an image. Once
248 // we find an image, we will decode and return it. While many gif files 244 // we find an image, we will decode and return it. While many gif files
249 // contain more than one image, we will simply decode the first image. 245 // contain more than one image, we will simply decode the first image.
250 const int32_t width = dstInfo.width(); 246 const int32_t width = dstInfo.width();
251 const int32_t height = dstInfo.height(); 247 const int32_t height = dstInfo.height();
252 GifRecordType recordType; 248 GifRecordType recordType;
253 do { 249 do {
254 // Get the current record type 250 // Get the current record type
255 if (GIF_ERROR == DGifGetRecordType(fGif, &recordType)) { 251 if (GIF_ERROR == DGifGetRecordType(fGif, &recordType)) {
256 return gif_error("DGifGetRecordType failed.\n", kInvalidInput); 252 return gif_error("DGifGetRecordType failed.\n", kInvalidInput);
257 } 253 }
258 254
259 switch (recordType) { 255 switch (recordType) {
260 case IMAGE_DESC_RECORD_TYPE: { 256 case IMAGE_DESC_RECORD_TYPE: {
261 // Read the image descriptor 257 // Read the image descriptor
262 if (GIF_ERROR == DGifGetImageDesc(fGif)) { 258 if (GIF_ERROR == DGifGetImageDesc(fGif)) {
263 return gif_error("DGifGetImageDesc failed.\n", 259 return gif_error("DGifGetImageDesc failed.\n", kInvalidInput );
264 kInvalidInput);
265 } 260 }
266 261
267 // If reading the image descriptor is successful, the image 262 // If reading the image descriptor is successful, the image
268 // count will be incremented 263 // count will be incremented
269 SkASSERT(fGif->ImageCount >= 1); 264 SkASSERT(fGif->ImageCount >= 1);
270 SavedImage* image = &fGif->SavedImages[fGif->ImageCount - 1]; 265 SavedImage* image = &fGif->SavedImages[fGif->ImageCount - 1];
271 266
272 // Process the descriptor 267 // Process the descriptor
273 const GifImageDesc& desc = image->ImageDesc; 268 const GifImageDesc& desc = image->ImageDesc;
274 int32_t imageLeft = desc.Left; 269 int32_t imageLeft = desc.Left;
275 int32_t imageTop = desc.Top; 270 int32_t imageTop = desc.Top;
276 int32_t innerWidth = desc.Width; 271 int32_t innerWidth = desc.Width;
277 int32_t innerHeight = desc.Height; 272 int32_t innerHeight = desc.Height;
278 // Fail on non-positive dimensions 273 // Fail on non-positive dimensions
279 if (innerWidth <= 0 || innerHeight <= 0) { 274 if (innerWidth <= 0 || innerHeight <= 0) {
280 return gif_error("Invalid dimensions for inner image.\n", 275 return gif_error("Invalid dimensions for inner image.\n", kI nvalidInput);
281 kInvalidInput);
282 } 276 }
283 // Treat the following cases as warnings and try to fix 277 // Treat the following cases as warnings and try to fix
284 if (innerWidth > width) { 278 if (innerWidth > width) {
285 gif_warning("Inner image too wide, shrinking.\n"); 279 gif_warning("Inner image too wide, shrinking.\n");
286 innerWidth = width; 280 innerWidth = width;
287 imageLeft = 0; 281 imageLeft = 0;
288 } else if (imageLeft + innerWidth > width) { 282 } else if (imageLeft + innerWidth > width) {
289 gif_warning("Shifting inner image to left to fit.\n"); 283 gif_warning("Shifting inner image to left to fit.\n");
290 imageLeft = width - innerWidth; 284 imageLeft = width - innerWidth;
291 } else if (imageLeft < 0) { 285 } else if (imageLeft < 0) {
(...skipping 28 matching lines...) Expand all
320 uint32_t colorCount = 0; 314 uint32_t colorCount = 0;
321 // Allocate maximum storage to deal with invalid indices safely 315 // Allocate maximum storage to deal with invalid indices safely
322 const uint32_t maxColors = 256; 316 const uint32_t maxColors = 256;
323 ColorMapObject* colorMap = fGif->Image.ColorMap; 317 ColorMapObject* colorMap = fGif->Image.ColorMap;
324 // If there is no local color table, use the global color table 318 // If there is no local color table, use the global color table
325 if (nullptr == colorMap) { 319 if (nullptr == colorMap) {
326 colorMap = fGif->SColorMap; 320 colorMap = fGif->SColorMap;
327 } 321 }
328 if (nullptr != colorMap) { 322 if (nullptr != colorMap) {
329 colorCount = colorMap->ColorCount; 323 colorCount = colorMap->ColorCount;
330 SkASSERT(colorCount == 324 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPi xel)));
331 (unsigned) (1 << (colorMap->BitsPerPixel)));
332 SkASSERT(colorCount <= 256); 325 SkASSERT(colorCount <= 256);
333 for (uint32_t i = 0; i < colorCount; i++) { 326 for (uint32_t i = 0; i < colorCount; i++) {
334 colorTable[i] = SkPackARGB32(0xFF, 327 colorTable[i] = SkPackARGB32(0xFF,
335 colorMap->Colors[i].Red, 328 colorMap->Colors[i].Red,
336 colorMap->Colors[i].Green, 329 colorMap->Colors[i].Green,
337 colorMap->Colors[i].Blue); 330 colorMap->Colors[i].Blue);
338 } 331 }
339 } 332 }
340 333
341 // This is used to fill unspecified pixels in the image data. 334 // This is used to fill unspecified pixels in the image data.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 // This allows for predictable, safe behavior. 370 // This allows for predictable, safe behavior.
378 for (uint32_t i = colorCount; i < maxColors; i++) { 371 for (uint32_t i = colorCount; i < maxColors; i++) {
379 colorTable[i] = colorTable[fillIndex]; 372 colorTable[i] = colorTable[fillIndex];
380 } 373 }
381 374
382 // Check if image is only a subset of the image frame 375 // Check if image is only a subset of the image frame
383 SkAutoTDelete<SkSwizzler> swizzler(nullptr); 376 SkAutoTDelete<SkSwizzler> swizzler(nullptr);
384 if (innerWidth < width || innerHeight < height) { 377 if (innerWidth < width || innerHeight < height) {
385 378
386 // Modify the destination info 379 // Modify the destination info
387 const SkImageInfo subsetDstInfo = 380 const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth, innerHeight);
388 dstInfo.makeWH(innerWidth, innerHeight);
389 381
390 // Fill the destination with the fill color 382 // Fill the destination with the fill color
391 // FIXME: This may not be the behavior that we want for 383 // FIXME: This may not be the behavior that we want for
392 // animated gifs where we draw on top of the 384 // animated gifs where we draw on top of the
393 // previous frame. 385 // previous frame.
394 if (!skipBackground) { 386 if (!skipBackground) {
395 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, 387 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fill Index, colorTable);
396 fillIndex, colorTable);
397 } 388 }
398 389
399 // Modify the dst pointer 390 // Modify the dst pointer
400 const int32_t dstBytesPerPixel = 391 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(ds tColorType);
401 SkColorTypeBytesPerPixel(dstColorType);
402 dst = SkTAddOffset<void*>(dst, 392 dst = SkTAddOffset<void*>(dst,
403 dstRowBytes * imageTop + 393 dstRowBytes * imageTop +
404 dstBytesPerPixel * imageLeft); 394 dstBytesPerPixel * imageLeft);
405 395
406 // Create the subset swizzler 396 // Create the subset swizzler
407 swizzler.reset(SkSwizzler::CreateSwizzler( 397 swizzler.reset(SkSwizzler::CreateSwizzler(
408 SkSwizzler::kIndex, colorTable, subsetDstInfo, 398 SkSwizzler::kIndex, colorTable, subsetDstInfo,
409 zeroInit, this->getInfo())); 399 zeroInit, this->getInfo()));
410 } else { 400 } else {
411 // Create the fully dimensional swizzler 401 // Create the fully dimensional swizzler
412 swizzler.reset(SkSwizzler::CreateSwizzler( 402 swizzler.reset(SkSwizzler::CreateSwizzler(
413 SkSwizzler::kIndex, colorTable, dstInfo, 403 SkSwizzler::kIndex, colorTable, dstInfo,
414 zeroInit, this->getInfo())); 404 zeroInit, this->getInfo()));
415 } 405 }
416 406
417 // Stores output from dgiflib and input to the swizzler 407 // Stores output from dgiflib and input to the swizzler
418 SkAutoTDeleteArray<uint8_t> buffer(new uint8_t[innerWidth]); 408 SkAutoTDeleteArray<uint8_t> buffer(new uint8_t[innerWidth]);
419 409
420 // Check the interlace flag and iterate over rows of the input 410 // Check the interlace flag and iterate over rows of the input
421 if (fGif->Image.Interlace) { 411 if (fGif->Image.Interlace) {
422 // In interlace mode, the rows of input are rearranged in 412 // In interlace mode, the rows of input are rearranged in
423 // the output image. We use an iterator to take care of 413 // the output image. We use an iterator to take care of
424 // the rearranging. 414 // the rearranging.
425 SkGifInterlaceIter iter(innerHeight); 415 SkGifInterlaceIter iter(innerHeight);
426 for (int32_t y = 0; y < innerHeight; y++) { 416 for (int32_t y = 0; y < innerHeight; y++) {
427 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), 417 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi dth)) {
428 innerWidth)) {
429 // Recover from error by filling remainder of image 418 // Recover from error by filling remainder of image
430 if (!skipBackground) { 419 if (!skipBackground) {
431 memset(buffer.get(), fillIndex, innerWidth); 420 memset(buffer.get(), fillIndex, innerWidth);
432 for (; y < innerHeight; y++) { 421 for (; y < innerHeight; y++) {
433 void* dstRow = SkTAddOffset<void>(dst, 422 void* dstRow = SkTAddOffset<void>(dst,
434 dstRowBytes * iter.nextY()); 423 dstRowByte s * iter.nextY());
435 swizzler->swizzle(dstRow, buffer.get()); 424 swizzler->swizzle(dstRow, buffer.get());
436 } 425 }
437 } 426 }
438 return gif_error(SkStringPrintf( 427 return gif_error(SkStringPrintf(
439 "Could not decode line %d of %d.\n", 428 "Could not decode line %d of %d.\n",
440 y, height - 1).c_str(), kIncompleteInput); 429 y, height - 1).c_str(), kIncompleteInput);
441 } 430 }
442 void* dstRow = SkTAddOffset<void>( 431 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * ite r.nextY());
443 dst, dstRowBytes * iter.nextY());
444 swizzler->swizzle(dstRow, buffer.get()); 432 swizzler->swizzle(dstRow, buffer.get());
445 } 433 }
446 } else { 434 } else {
447 // Standard mode 435 // Standard mode
448 void* dstRow = dst; 436 void* dstRow = dst;
449 for (int32_t y = 0; y < innerHeight; y++) { 437 for (int32_t y = 0; y < innerHeight; y++) {
450 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), 438 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi dth)) {
451 innerWidth)) {
452 if (!skipBackground) { 439 if (!skipBackground) {
453 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, 440 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes,
454 innerHeight - y, fillIndex, colorTable); 441 innerHeight - y, fillIndex, col orTable);
455 } 442 }
456 return gif_error(SkStringPrintf( 443 return gif_error(SkStringPrintf(
457 "Could not decode line %d of %d.\n", 444 "Could not decode line %d of %d.\n",
458 y, height - 1).c_str(), kIncompleteInput); 445 y, height - 1).c_str(), kIncompleteInput);
459 } 446 }
460 swizzler->swizzle(dstRow, buffer.get()); 447 swizzler->swizzle(dstRow, buffer.get());
461 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 448 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
462 } 449 }
463 } 450 }
464 451
(...skipping 18 matching lines...) Expand all
483 // displayed in the same frame together. I will 470 // displayed in the same frame together. I will
484 // currently leave this unimplemented until I find a 471 // currently leave this unimplemented until I find a
485 // test case that expects this behavior. 472 // test case that expects this behavior.
486 return kSuccess; 473 return kSuccess;
487 } 474 }
488 475
489 // Extensions are used to specify special properties of the image 476 // Extensions are used to specify special properties of the image
490 // such as transparency or animation. 477 // such as transparency or animation.
491 case EXTENSION_RECORD_TYPE: 478 case EXTENSION_RECORD_TYPE:
492 // Read extension data 479 // Read extension data
493 if (GIF_ERROR == 480 if (GIF_ERROR == DGifGetExtension(fGif, &extFunction, &extData)) {
494 DGifGetExtension(fGif, &extFunction, &extData)) { 481 return gif_error("Could not get extension.\n", kIncompleteIn put);
495 return gif_error("Could not get extension.\n",
496 kIncompleteInput);
497 } 482 }
498 483
499 // Create an extension block with our data 484 // Create an extension block with our data
500 while (nullptr != extData) { 485 while (nullptr != extData) {
501 // Add a single block 486 // Add a single block
502 if (GIF_ERROR == 487 if (GIF_ERROR == GifAddExtensionBlock(&saveExt.ExtensionBloc kCount,
503 GifAddExtensionBlock(&saveExt.ExtensionBlockCount, 488 &saveExt.ExtensionBloc ks,
504 &saveExt.ExtensionBlocks, extFunction, extData[0], 489 extFunction, extData[0 ], &extData[1]))
505 &extData[1])) { 490 {
506 return gif_error("Could not add extension block.\n", 491 return gif_error("Could not add extension block.\n", kIn completeInput);
507 kIncompleteInput);
508 } 492 }
509 // Move to the next block 493 // Move to the next block
510 if (GIF_ERROR == DGifGetExtensionNext(fGif, &extData)) { 494 if (GIF_ERROR == DGifGetExtensionNext(fGif, &extData)) {
511 return gif_error("Could not get next extension.\n", 495 return gif_error("Could not get next extension.\n", kInc ompleteInput);
512 kIncompleteInput);
513 } 496 }
514 } 497 }
515 break; 498 break;
516 499
517 // Signals the end of the gif file 500 // Signals the end of the gif file
518 case TERMINATE_RECORD_TYPE: 501 case TERMINATE_RECORD_TYPE:
519 break; 502 break;
520 503
521 default: 504 default:
522 // giflib returns an error code if the record type is not known. 505 // giflib returns an error code if the record type is not known.
523 // We should catch this error immediately. 506 // We should catch this error immediately.
524 SkASSERT(false); 507 SkASSERT(false);
525 break; 508 break;
526 } 509 }
527 } while (TERMINATE_RECORD_TYPE != recordType); 510 } while (TERMINATE_RECORD_TYPE != recordType);
528 511
529 return gif_error("Could not find any images to decode in gif file.\n", 512 return gif_error("Could not find any images to decode in gif file.\n", kInva lidInput);
530 kInvalidInput);
531 } 513 }
OLDNEW
« no previous file with comments | « src/codec/SkBmpRLECodec.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698