| Index: src/codec/SkCodec_libgif.cpp
|
| diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp
|
| index e6d1141669b69ee122053a61b80bcf643b54b6ea..f72150a19bea6fdb363a30f27c1720f757c4334f 100644
|
| --- a/src/codec/SkCodec_libgif.cpp
|
| +++ b/src/codec/SkCodec_libgif.cpp
|
| @@ -96,31 +96,6 @@ static uint32_t find_trans_index(const SavedImage& image) {
|
| return SK_MaxU32;
|
| }
|
|
|
| -static inline uint32_t ceil_div(uint32_t a, uint32_t b) {
|
| - return (a + b - 1) / b;
|
| -}
|
| -
|
| -/*
|
| - * Gets the output row corresponding to the encoded row for interlaced gifs
|
| - */
|
| -static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) {
|
| - SkASSERT(encodedRow < height);
|
| - // First pass
|
| - if (encodedRow * 8 < height) {
|
| - return encodedRow * 8;
|
| - }
|
| - // Second pass
|
| - if (encodedRow * 4 < height) {
|
| - return 4 + 8 * (encodedRow - ceil_div(height, 8));
|
| - }
|
| - // Third pass
|
| - if (encodedRow * 2 < height) {
|
| - return 2 + 4 * (encodedRow - ceil_div(height, 4));
|
| - }
|
| - // Fourth pass
|
| - return 1 + 2 * (encodedRow - ceil_div(height, 2));
|
| -}
|
| -
|
| /*
|
| * This function cleans up the gif object after the decode completes
|
| * It is used in a SkAutoTCallIProc template
|
| @@ -492,11 +467,8 @@ SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo,
|
| return kUnimplemented;
|
| }
|
|
|
| -SkCodec::Result SkGifCodec::readRow() {
|
| - if (GIF_ERROR == DGifGetLine(fGif, fSrcBuffer.get(), fFrameDims.width())) {
|
| - return kIncompleteInput;
|
| - }
|
| - return kSuccess;
|
| +bool SkGifCodec::readRow() {
|
| + return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameDims.width());
|
| }
|
|
|
| /*
|
| @@ -506,7 +478,8 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| void* dst, size_t dstRowBytes,
|
| const Options& opts,
|
| SkPMColor* inputColorPtr,
|
| - int* inputColorCount) {
|
| + int* inputColorCount,
|
| + int* rowsDecoded) {
|
| Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, opts);
|
| if (kSuccess != result) {
|
| return result;
|
| @@ -525,8 +498,8 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
|
|
|
| // Fill the background
|
| const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| - SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getInfo().height(),
|
| - fFillIndex, colorPtr, opts.fZeroInitialized);
|
| + SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getFillValue(dstInfo.colorType(),
|
| + dstInfo.alphaType()), opts.fZeroInitialized);
|
|
|
| // Modify the dst pointer
|
| const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorType());
|
| @@ -538,49 +511,29 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
|
| }
|
| }
|
|
|
| - // Check the interlace flag and iterate over rows of the input
|
| + // Iterate over rows of the input
|
| uint32_t width = fFrameDims.width();
|
| uint32_t height = fFrameDims.height();
|
| - if (fGif->Image.Interlace) {
|
| - // In interlace mode, the rows of input are rearranged in
|
| - // the output image. We a helper function to help us
|
| - // rearrange the decoded rows.
|
| - for (uint32_t y = 0; y < height; y++) {
|
| - if (kSuccess != this->readRow()) {
|
| - // Recover from error by filling remainder of image
|
| - memset(fSrcBuffer.get(), fFillIndex, width);
|
| - for (; y < height; y++) {
|
| - void* dstRow = SkTAddOffset<void>(dst,
|
| - dstRowBytes * get_output_row_interlaced(y, height));
|
| - fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| - }
|
| - return gif_error("Could not decode line.\n", kIncompleteInput);
|
| - }
|
| - void* dstRow = SkTAddOffset<void>(dst,
|
| - dstRowBytes * get_output_row_interlaced(y, height));
|
| - fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| - }
|
| - } else {
|
| - // Standard mode
|
| - void* dstRow = dst;
|
| - for (uint32_t y = 0; y < height; y++) {
|
| - if (kSuccess != this->readRow()) {
|
| - const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| - SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes,
|
| - height - y, fFillIndex, colorPtr, opts.fZeroInitialized);
|
| - return gif_error("Could not decode line\n", kIncompleteInput);
|
| - }
|
| - fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| - dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
|
| + for (uint32_t y = 0; y < height; y++) {
|
| + if (!this->readRow()) {
|
| + *rowsDecoded = y;
|
| + return gif_error("Could not decode line.\n", kIncompleteInput);
|
| }
|
| + void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->nextScanline(y));
|
| + fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| }
|
| return kSuccess;
|
| }
|
|
|
| +uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
|
| + const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| + return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
|
| +}
|
| +
|
| SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
|
| const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColorCount) {
|
| - Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount,
|
| - this->options());
|
| +
|
| + Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->options());
|
| if (kSuccess != result) {
|
| return result;
|
| }
|
| @@ -611,60 +564,43 @@ SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
|
| return kSuccess;
|
| }
|
|
|
| -SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
|
| +uint32_t SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
|
| + int rowsBeforeFrame = 0;
|
| + int rowsAfterFrame = 0;
|
| if (fFrameIsSubset) {
|
| // Fill the requested rows
|
| - const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| - SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fFillIndex,
|
| - colorPtr, this->options().fZeroInitialized);
|
| + SkSwizzler::Fill(dst, this->dstInfo().makeWH(this->dstInfo().width(), count), rowBytes,
|
| + this->onGetFillValue(this->dstInfo().colorType(), this->dstInfo().alphaType()),
|
| + this->options().fZeroInitialized);
|
|
|
| // Do nothing for rows before the image frame
|
| - // FIXME: nextScanline is not virtual, so using "INHERITED" does not change
|
| - // behavior. Was the intent to call this->INHERITED::onNextScanline()? Same
|
| - // for the next call down below.
|
| - int rowsBeforeFrame = fFrameDims.top() - this->INHERITED::nextScanline();
|
| - if (rowsBeforeFrame > 0) {
|
| - count = SkTMin(0, count - rowsBeforeFrame);
|
| - dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
|
| - }
|
| + // FIXME: Do we handle fFrameIsSubset properly for interlaced images?
|
| + rowsBeforeFrame = SkTMax(0, fFrameDims.top() - this->nextScanline());
|
| + count = SkTMax(0, count - rowsBeforeFrame);
|
| + dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
|
|
|
| // Do nothing for rows after the image frame
|
| - int rowsAfterFrame = this->INHERITED::nextScanline() + count - fFrameDims.bottom();
|
| - if (rowsAfterFrame > 0) {
|
| - count = SkTMin(0, count - rowsAfterFrame);
|
| - }
|
| + rowsAfterFrame = SkTMax(0, this->nextScanline() + count - fFrameDims.bottom());
|
| + count = SkTMax(0, count - rowsAfterFrame);
|
|
|
| - // Adjust dst pointer for left offset
|
| + // Adjust dst pointer for left offset
|
| int bpp = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrameDims.left();
|
| dst = SkTAddOffset<void>(dst, bpp);
|
| }
|
|
|
| for (int i = 0; i < count; i++) {
|
| - if (kSuccess != this->readRow()) {
|
| - const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
|
| - SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count - i, fFillIndex, colorPtr,
|
| - this->options().fZeroInitialized);
|
| - return gif_error("Could not decode line\n", SkCodec::kIncompleteInput);
|
| + if (!this->readRow()) {
|
| + return i + rowsBeforeFrame;
|
| }
|
| fSwizzler->swizzle(dst, fSrcBuffer.get());
|
| dst = SkTAddOffset<void>(dst, rowBytes);
|
| }
|
| - return SkCodec::kSuccess;
|
| + return count + rowsBeforeFrame + rowsAfterFrame;
|
| }
|
|
|
| SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const {
|
| if (fGif->Image.Interlace) {
|
| return kOutOfOrder_SkScanlineOrder;
|
| - } else {
|
| - return kTopDown_SkScanlineOrder;
|
| }
|
| + return kTopDown_SkScanlineOrder;
|
| }
|
| -
|
| -int SkGifCodec::onNextScanline() const {
|
| - if (fGif->Image.Interlace) {
|
| - return get_output_row_interlaced(this->INHERITED::onNextScanline(), this->dstInfo().height());
|
| - } else {
|
| - return this->INHERITED::onNextScanline();
|
| - }
|
| -}
|
| -
|
|
|