Chromium Code Reviews| Index: src/codec/SkCodec_libgif.cpp |
| diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp |
| index 7b380473fc667a6f5ccf544a143dc047da4cf69b..036285360b47040f49b04db4a8db8e3bceb746fc 100644 |
| --- a/src/codec/SkCodec_libgif.cpp |
| +++ b/src/codec/SkCodec_libgif.cpp |
| @@ -95,31 +95,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 |
| @@ -460,11 +435,8 @@ SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, |
| return kUnimplemented; |
| } |
| -SkCodec::Result SkGifCodec::readRow() { |
| - if (GIF_ERROR == DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width())) { |
| - return kIncompleteInput; |
| - } |
| - return kSuccess; |
| +bool SkGifCodec::readRow() { |
| + return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); |
| } |
| /* |
| @@ -474,7 +446,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; |
| @@ -492,9 +465,9 @@ 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); |
| + fSwizzler->fill(dst, dstInfo.colorType(), dstInfo.height(), dstRowBytes, |
|
scroggo
2015/10/07 16:04:24
I don't think this does what you want. The swizzle
msarett
2015/10/07 17:40:41
You're correct, fixing.
|
| + this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), |
| + opts.fZeroInitialized); |
| // Modify the dst pointer |
| const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorType()); |
| @@ -506,49 +479,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 = fFrameRect.width(); |
| uint32_t height = fFrameRect.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->outputScanline(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; |
| } |
| @@ -568,58 +521,55 @@ SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, |
| return kSuccess; |
| } |
| -SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
| +int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
| + int rowsBeforeFrame = 0; |
| + int rowsAfterFrame = 0; |
| + int rowsInFrame = count; |
| 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); |
| + fSwizzler->fill(dst, this->dstInfo().colorType(), count, rowBytes, |
| + this->onGetFillValue(this->dstInfo().colorType(), this->dstInfo().alphaType()), |
| + this->options().fZeroInitialized); |
| // Do nothing for rows before the image frame |
| - int rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::onNextScanline()); |
| - count = SkTMax(0, count - rowsBeforeFrame); |
| + rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScanline()); |
| + rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame); |
| dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); |
| // Do nothing for rows after the image frame |
| - int rowsAfterFrame = SkTMax(0, |
| - this->INHERITED::onNextScanline() + count - fFrameRect.bottom()); |
| - count = SkTMax(0, count - rowsAfterFrame); |
| + rowsAfterFrame = SkTMax(0, |
| + this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.bottom()); |
| + rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame); |
| // Adjust dst pointer for left offset |
| int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrameRect.left(); |
| dst = SkTAddOffset<void>(dst, offset); |
| } |
| - for (int i = 0; i < count; i++) { |
| - if (kSuccess != this->readRow()) { |
| - const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
| - SkSwizzler::Fill(dst, this->dstInfo().makeWH(fFrameRect.width(), |
| - this->dstInfo().height()), rowBytes, count - i, fFillIndex, colorPtr, |
| - this->options().fZeroInitialized); |
| - return kIncompleteInput; |
| + for (int i = 0; i < rowsInFrame; i++) { |
| + if (!this->readRow()) { |
| + return i + rowsBeforeFrame; |
| } |
| fSwizzler->swizzle(dst, fSrcBuffer.get()); |
| dst = SkTAddOffset<void>(dst, rowBytes); |
| } |
| - return kSuccess; |
| + |
| + return count; |
| } |
| SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { |
| if (fGif->Image.Interlace) { |
| return kOutOfOrder_SkScanlineOrder; |
| - } else { |
| - return kTopDown_SkScanlineOrder; |
| } |
| + return kTopDown_SkScanlineOrder; |
| } |
| -int SkGifCodec::onNextScanline() const { |
| - int nextScanline = this->INHERITED::onNextScanline(); |
| +int SkGifCodec::onOutputScanline(int inputScanline) const { |
| if (fGif->Image.Interlace) { |
| - if (nextScanline < fFrameRect.top() || nextScanline >= fFrameRect.bottom()) { |
| - return nextScanline; |
| + if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bottom()) { |
| + return inputScanline; |
| } |
| - return get_output_row_interlaced(nextScanline - fFrameRect.top(), fFrameRect.height()); |
| + return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFrameRect.height()); |
| } |
| - return nextScanline; |
| + return inputScanline; |
| } |
| - |