| 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 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 // If there is a transparent index, we also use this as | 351 // If there is a transparent index, we also use this as |
| 352 // the fill index. | 352 // the fill index. |
| 353 fillIndex = transIndex; | 353 fillIndex = transIndex; |
| 354 } else if (fillIndex >= colorCount) { | 354 } else if (fillIndex >= colorCount) { |
| 355 // If the fill index is invalid, we default to 0. This | 355 // If the fill index is invalid, we default to 0. This |
| 356 // behavior is unspecified but matches SkImageDecoder. | 356 // behavior is unspecified but matches SkImageDecoder. |
| 357 fillIndex = 0; | 357 fillIndex = 0; |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 // Check if we can skip filling the background of the image. We | |
| 362 // may be able to if the memory is zero initialized. | |
| 363 bool skipBackground = | |
| 364 ((kN32_SkColorType == dstColorType && colorTable[fillInd
ex] == 0) || | |
| 365 (kIndex_8_SkColorType == dstColorType && fillIndex == 0)
) && | |
| 366 kYes_ZeroInitialized == zeroInit; | |
| 367 | |
| 368 | |
| 369 // Fill in the color table for indices greater than color count. | 361 // Fill in the color table for indices greater than color count. |
| 370 // This allows for predictable, safe behavior. | 362 // This allows for predictable, safe behavior. |
| 371 for (uint32_t i = colorCount; i < maxColors; i++) { | 363 for (uint32_t i = colorCount; i < maxColors; i++) { |
| 372 colorTable[i] = colorTable[fillIndex]; | 364 colorTable[i] = colorTable[fillIndex]; |
| 373 } | 365 } |
| 374 | 366 |
| 375 // Check if image is only a subset of the image frame | 367 // Check if image is only a subset of the image frame |
| 376 SkAutoTDelete<SkSwizzler> swizzler(nullptr); | 368 SkAutoTDelete<SkSwizzler> swizzler(nullptr); |
| 377 if (innerWidth < width || innerHeight < height) { | 369 if (innerWidth < width || innerHeight < height) { |
| 378 | 370 |
| 379 // Modify the destination info | 371 // Modify the destination info |
| 380 const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth,
innerHeight); | 372 const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth,
innerHeight); |
| 381 | 373 |
| 382 // Fill the destination with the fill color | 374 // Fill the destination with the fill color |
| 383 // FIXME: This may not be the behavior that we want for | 375 // FIXME: This may not be the behavior that we want for |
| 384 // animated gifs where we draw on top of the | 376 // animated gifs where we draw on top of the |
| 385 // previous frame. | 377 // previous frame. |
| 386 if (!skipBackground) { | 378 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fillInde
x, colorTable, |
| 387 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fill
Index, colorTable); | 379 zeroInit); |
| 388 } | |
| 389 | 380 |
| 390 // Modify the dst pointer | 381 // Modify the dst pointer |
| 391 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(ds
tColorType); | 382 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(ds
tColorType); |
| 392 dst = SkTAddOffset<void*>(dst, | 383 dst = SkTAddOffset<void*>(dst, |
| 393 dstRowBytes * imageTop + | 384 dstRowBytes * imageTop + |
| 394 dstBytesPerPixel * imageLeft); | 385 dstBytesPerPixel * imageLeft); |
| 395 | 386 |
| 396 // Create the subset swizzler | 387 // Create the subset swizzler |
| 397 swizzler.reset(SkSwizzler::CreateSwizzler( | 388 swizzler.reset(SkSwizzler::CreateSwizzler( |
| 398 SkSwizzler::kIndex, colorTable, subsetDstInfo, | 389 SkSwizzler::kIndex, colorTable, subsetDstInfo, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 409 | 400 |
| 410 // Check the interlace flag and iterate over rows of the input | 401 // Check the interlace flag and iterate over rows of the input |
| 411 if (fGif->Image.Interlace) { | 402 if (fGif->Image.Interlace) { |
| 412 // In interlace mode, the rows of input are rearranged in | 403 // In interlace mode, the rows of input are rearranged in |
| 413 // the output image. We use an iterator to take care of | 404 // the output image. We use an iterator to take care of |
| 414 // the rearranging. | 405 // the rearranging. |
| 415 SkGifInterlaceIter iter(innerHeight); | 406 SkGifInterlaceIter iter(innerHeight); |
| 416 for (int32_t y = 0; y < innerHeight; y++) { | 407 for (int32_t y = 0; y < innerHeight; y++) { |
| 417 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { | 408 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { |
| 418 // Recover from error by filling remainder of image | 409 // Recover from error by filling remainder of image |
| 419 if (!skipBackground) { | 410 memset(buffer.get(), fillIndex, innerWidth); |
| 420 memset(buffer.get(), fillIndex, innerWidth); | 411 for (; y < innerHeight; y++) { |
| 421 for (; y < innerHeight; y++) { | 412 void* dstRow = SkTAddOffset<void>(dst, dstRowByt
es * iter.nextY()); |
| 422 void* dstRow = SkTAddOffset<void>(dst, | 413 swizzler->swizzle(dstRow, buffer.get()); |
| 423 dstRowByte
s * iter.nextY()); | |
| 424 swizzler->swizzle(dstRow, buffer.get()); | |
| 425 } | |
| 426 } | 414 } |
| 427 return gif_error(SkStringPrintf( | 415 return gif_error(SkStringPrintf( |
| 428 "Could not decode line %d of %d.\n", | 416 "Could not decode line %d of %d.\n", |
| 429 y, height - 1).c_str(), kIncompleteInput); | 417 y, height - 1).c_str(), kIncompleteInput); |
| 430 } | 418 } |
| 431 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * ite
r.nextY()); | 419 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * ite
r.nextY()); |
| 432 swizzler->swizzle(dstRow, buffer.get()); | 420 swizzler->swizzle(dstRow, buffer.get()); |
| 433 } | 421 } |
| 434 } else { | 422 } else { |
| 435 // Standard mode | 423 // Standard mode |
| 436 void* dstRow = dst; | 424 void* dstRow = dst; |
| 437 for (int32_t y = 0; y < innerHeight; y++) { | 425 for (int32_t y = 0; y < innerHeight; y++) { |
| 438 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { | 426 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWi
dth)) { |
| 439 if (!skipBackground) { | 427 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, inner
Height - y, |
| 440 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, | 428 fillIndex, colorTable, zeroInit); |
| 441 innerHeight - y, fillIndex, col
orTable); | |
| 442 } | |
| 443 return gif_error(SkStringPrintf( | 429 return gif_error(SkStringPrintf( |
| 444 "Could not decode line %d of %d.\n", | 430 "Could not decode line %d of %d.\n", |
| 445 y, height - 1).c_str(), kIncompleteInput); | 431 y, height - 1).c_str(), kIncompleteInput); |
| 446 } | 432 } |
| 447 swizzler->swizzle(dstRow, buffer.get()); | 433 swizzler->swizzle(dstRow, buffer.get()); |
| 448 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 434 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 449 } | 435 } |
| 450 } | 436 } |
| 451 | 437 |
| 452 // FIXME: Gif files may have multiple images stored in a single | 438 // FIXME: Gif files may have multiple images stored in a single |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 default: | 490 default: |
| 505 // giflib returns an error code if the record type is not known. | 491 // giflib returns an error code if the record type is not known. |
| 506 // We should catch this error immediately. | 492 // We should catch this error immediately. |
| 507 SkASSERT(false); | 493 SkASSERT(false); |
| 508 break; | 494 break; |
| 509 } | 495 } |
| 510 } while (TERMINATE_RECORD_TYPE != recordType); | 496 } while (TERMINATE_RECORD_TYPE != recordType); |
| 511 | 497 |
| 512 return gif_error("Could not find any images to decode in gif file.\n", kInva
lidInput); | 498 return gif_error("Could not find any images to decode in gif file.\n", kInva
lidInput); |
| 513 } | 499 } |
| OLD | NEW |