| OLD | NEW |
| 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" |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 // If there is a transparent index, we also use this as | 375 // If there is a transparent index, we also use this as |
| 376 // the fill index. | 376 // the fill index. |
| 377 fillIndex = transIndex; | 377 fillIndex = transIndex; |
| 378 } else if (fillIndex >= colorCount) { | 378 } else if (fillIndex >= colorCount) { |
| 379 // If the fill index is invalid, we default to 0. This | 379 // If the fill index is invalid, we default to 0. This |
| 380 // behavior is unspecified but matches SkImageDecoder. | 380 // behavior is unspecified but matches SkImageDecoder. |
| 381 fillIndex = 0; | 381 fillIndex = 0; |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 | 384 |
| 385 // Check if we can skip filling the background of the image. We | |
| 386 // may be able to if the memory is zero initialized. | |
| 387 bool skipBackground = | |
| 388 ((kN32_SkColorType == dstColorType && colorTable[fillInd
ex] == 0) || | |
| 389 (kIndex_8_SkColorType == dstColorType && fillIndex == 0)
) && | |
| 390 kYes_ZeroInitialized == zeroInit; | |
| 391 | |
| 392 | |
| 393 // Fill in the color table for indices greater than color count. | 385 // Fill in the color table for indices greater than color count. |
| 394 // This allows for predictable, safe behavior. | 386 // This allows for predictable, safe behavior. |
| 395 for (uint32_t i = colorCount; i < maxColors; i++) { | 387 for (uint32_t i = colorCount; i < maxColors; i++) { |
| 396 colorTable[i] = colorTable[fillIndex]; | 388 colorTable[i] = colorTable[fillIndex]; |
| 397 } | 389 } |
| 398 | 390 |
| 399 // Check if image is only a subset of the image frame | 391 // Check if image is only a subset of the image frame |
| 400 SkAutoTDelete<SkSwizzler> swizzler(nullptr); | 392 SkAutoTDelete<SkSwizzler> swizzler(nullptr); |
| 401 if (innerWidth < width || innerHeight < height) { | 393 if (innerWidth < width || innerHeight < height) { |
| 402 | 394 |
| 403 // Modify the destination info | 395 // Modify the destination info |
| 404 const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth,
innerHeight); | 396 const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth,
innerHeight); |
| 405 | 397 |
| 406 // Fill the destination with the fill color | 398 // Fill the destination with the fill color |
| 407 // FIXME: This may not be the behavior that we want for | 399 // FIXME: This may not be the behavior that we want for |
| 408 // animated gifs where we draw on top of the | 400 // animated gifs where we draw on top of the |
| 409 // previous frame. | 401 // previous frame. |
| 410 if (!skipBackground) { | 402 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fillInde
x, colorTable, |
| 411 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fill
Index, colorTable); | 403 zeroInit); |
| 412 } | |
| 413 | 404 |
| 414 // Modify the dst pointer | 405 // Modify the dst pointer |
| 415 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(ds
tColorType); | 406 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(ds
tColorType); |
| 416 dst = SkTAddOffset<void*>(dst, | 407 dst = SkTAddOffset<void*>(dst, |
| 417 dstRowBytes * imageTop + | 408 dstRowBytes * imageTop + |
| 418 dstBytesPerPixel * imageLeft); | 409 dstBytesPerPixel * imageLeft); |
| 419 | 410 |
| 420 // Create the subset swizzler | 411 // Create the subset swizzler |
| 421 swizzler.reset(SkSwizzler::CreateSwizzler( | 412 swizzler.reset(SkSwizzler::CreateSwizzler( |
| 422 SkSwizzler::kIndex, colorTable, subsetDstInfo, | 413 SkSwizzler::kIndex, colorTable, subsetDstInfo, |
| 423 zeroInit, this->getInfo())); | 414 zeroInit, this->getInfo())); |
| 424 } else { | 415 } else { |
| 425 // Create the fully dimensional swizzler | 416 // Create the fully dimensional swizzler |
| 426 swizzler.reset(SkSwizzler::CreateSwizzler( | 417 swizzler.reset(SkSwizzler::CreateSwizzler( |
| 427 SkSwizzler::kIndex, colorTable, dstInfo, | 418 SkSwizzler::kIndex, colorTable, dstInfo, |
| 428 zeroInit, this->getInfo())); | 419 zeroInit, this->getInfo())); |
| 429 } | 420 } |
| 430 | 421 |
| 431 // Stores output from dgiflib and input to the swizzler | 422 // Stores output from dgiflib and input to the swizzler |
| 432 SkAutoTDeleteArray<uint8_t> buffer(new uint8_t[innerWidth]); | 423 SkAutoTDeleteArray<uint8_t> buffer(new uint8_t[innerWidth]); |
| 433 | 424 |
| 434 // Check the interlace flag and iterate over rows of the input | 425 // Check the interlace flag and iterate over rows of the input |
| 435 if (fGif->Image.Interlace) { | 426 if (fGif->Image.Interlace) { |
| 436 for (int32_t y = 0; y < innerHeight; y++) { | 427 for (int32_t y = 0; y < innerHeight; y++) { |
| 437 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { | 428 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { |
| 438 // Recover from error by filling remainder of image | 429 // Recover from error by filling remainder of image |
| 439 if (!skipBackground) { | 430 memset(buffer.get(), fillIndex, innerWidth); |
| 440 memset(buffer.get(), fillIndex, innerWidth); | 431 for (; y < innerHeight; y++) { |
| 441 for (; y < innerHeight; y++) { | 432 void* dstRow = SkTAddOffset<void>(dst, dstRowByt
es * |
| 442 void* dstRow = SkTAddOffset<void>(dst, dstRo
wBytes * | 433 get_output_row_interlaced(y, innerHeight
)); |
| 443 get_output_row_interlaced(y, innerHe
ight)); | 434 swizzler->swizzle(dstRow, buffer.get()); |
| 444 swizzler->swizzle(dstRow, buffer.get()); | |
| 445 } | |
| 446 } | 435 } |
| 447 return gif_error(SkStringPrintf( | 436 return gif_error(SkStringPrintf( |
| 448 "Could not decode line %d of %d.\n", | 437 "Could not decode line %d of %d.\n", |
| 449 y, height - 1).c_str(), kIncompleteInput); | 438 y, height - 1).c_str(), kIncompleteInput); |
| 450 } | 439 } |
| 451 void* dstRow = SkTAddOffset<void>(dst, | 440 void* dstRow = SkTAddOffset<void>(dst, |
| 452 dstRowBytes * get_output_row_interlaced(y, inner
Height)); | 441 dstRowBytes * get_output_row_interlaced(y, inner
Height)); |
| 453 swizzler->swizzle(dstRow, buffer.get()); | 442 swizzler->swizzle(dstRow, buffer.get()); |
| 454 } | 443 } |
| 455 } else { | 444 } else { |
| 456 // Standard mode | 445 // Standard mode |
| 457 void* dstRow = dst; | 446 void* dstRow = dst; |
| 458 for (int32_t y = 0; y < innerHeight; y++) { | 447 for (int32_t y = 0; y < innerHeight; y++) { |
| 459 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { | 448 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { |
| 460 if (!skipBackground) { | 449 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, inner
Height - y, |
| 461 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, | 450 fillIndex, colorTable, zeroInit); |
| 462 innerHeight - y, fillIndex, col
orTable); | |
| 463 } | |
| 464 return gif_error(SkStringPrintf( | 451 return gif_error(SkStringPrintf( |
| 465 "Could not decode line %d of %d.\n", | 452 "Could not decode line %d of %d.\n", |
| 466 y, height - 1).c_str(), kIncompleteInput); | 453 y, height - 1).c_str(), kIncompleteInput); |
| 467 } | 454 } |
| 468 swizzler->swizzle(dstRow, buffer.get()); | 455 swizzler->swizzle(dstRow, buffer.get()); |
| 469 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 456 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 470 } | 457 } |
| 471 } | 458 } |
| 472 | 459 |
| 473 // FIXME: Gif files may have multiple images stored in a single | 460 // FIXME: Gif files may have multiple images stored in a single |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 default: | 512 default: |
| 526 // giflib returns an error code if the record type is not known. | 513 // giflib returns an error code if the record type is not known. |
| 527 // We should catch this error immediately. | 514 // We should catch this error immediately. |
| 528 SkASSERT(false); | 515 SkASSERT(false); |
| 529 break; | 516 break; |
| 530 } | 517 } |
| 531 } while (TERMINATE_RECORD_TYPE != recordType); | 518 } while (TERMINATE_RECORD_TYPE != recordType); |
| 532 | 519 |
| 533 return gif_error("Could not find any images to decode in gif file.\n", kInva
lidInput); | 520 return gif_error("Could not find any images to decode in gif file.\n", kInva
lidInput); |
| 534 } | 521 } |
| OLD | NEW |