| 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 418 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  429 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo
     r* inputColorPtr, |  429 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo
     r* inputColorPtr, | 
|  430         int* inputColorCount, const Options& opts) { |  430         int* inputColorCount, const Options& opts) { | 
|  431     // Check for valid input parameters |  431     // Check for valid input parameters | 
|  432     if (!conversion_possible(dstInfo, this->getInfo())) { |  432     if (!conversion_possible(dstInfo, this->getInfo())) { | 
|  433         return gif_error("Cannot convert input type to output type.\n", |  433         return gif_error("Cannot convert input type to output type.\n", | 
|  434                 kInvalidConversion); |  434                 kInvalidConversion); | 
|  435     } |  435     } | 
|  436  |  436  | 
|  437     // Initialize color table and copy to the client if necessary |  437     // Initialize color table and copy to the client if necessary | 
|  438     this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); |  438     this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); | 
|  439     return kSuccess; |  439  | 
 |  440     return this->initializeSwizzler(dstInfo, opts); | 
|  440 } |  441 } | 
|  441  |  442  | 
|  442 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const
      Options& opts) { |  443 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const
      Options& opts) { | 
|  443     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |  444     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 
|  444     fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dst
     Info, opts)); |  445     const SkIRect* frameRect = fFrameIsSubset ? &fFrameRect : nullptr; | 
 |  446     fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dst
     Info, opts, | 
 |  447             frameRect)); | 
 |  448  | 
|  445     if (nullptr != fSwizzler.get()) { |  449     if (nullptr != fSwizzler.get()) { | 
|  446         return kSuccess; |  450         return kSuccess; | 
|  447     } |  451     } | 
|  448     return kUnimplemented; |  452     return kUnimplemented; | 
|  449 } |  453 } | 
|  450  |  454  | 
|  451 bool SkGifCodec::readRow() { |  455 bool SkGifCodec::readRow() { | 
|  452     return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); |  456     return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); | 
|  453 } |  457 } | 
|  454  |  458  | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  465     if (kSuccess != result) { |  469     if (kSuccess != result) { | 
|  466         return result; |  470         return result; | 
|  467     } |  471     } | 
|  468  |  472  | 
|  469     if (dstInfo.dimensions() != this->getInfo().dimensions()) { |  473     if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 
|  470         return gif_error("Scaling not supported.\n", kInvalidScale); |  474         return gif_error("Scaling not supported.\n", kInvalidScale); | 
|  471     } |  475     } | 
|  472  |  476  | 
|  473     // Initialize the swizzler |  477     // Initialize the swizzler | 
|  474     if (fFrameIsSubset) { |  478     if (fFrameIsSubset) { | 
|  475         const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr
     ameRect.height()); |  | 
|  476         if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) { |  | 
|  477             return gif_error("Could not initialize swizzler.\n", kUnimplemented)
     ; |  | 
|  478         } |  | 
|  479  |  | 
|  480         // Fill the background |  479         // Fill the background | 
|  481         SkSampler::Fill(dstInfo, dst, dstRowBytes, |  480         SkSampler::Fill(dstInfo, dst, dstRowBytes, | 
|  482                 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), |  481                 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), | 
|  483                 opts.fZeroInitialized); |  482                 opts.fZeroInitialized); | 
|  484  |  | 
|  485         // Modify the dst pointer |  | 
|  486         const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT
     ype()); |  | 
|  487         dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + |  | 
|  488                 dstBytesPerPixel * fFrameRect.left()); |  | 
|  489     } else { |  | 
|  490         if (kSuccess != this->initializeSwizzler(dstInfo, opts)) { |  | 
|  491             return gif_error("Could not initialize swizzler.\n", kUnimplemented)
     ; |  | 
|  492         } |  | 
|  493     } |  483     } | 
|  494  |  484  | 
|  495     // Iterate over rows of the input |  485     // Iterate over rows of the input | 
|  496     uint32_t height = fFrameRect.height(); |  486     for (int y = fFrameRect.top(); y < fFrameRect.bottom(); y++) { | 
|  497     for (uint32_t y = 0; y < height; y++) { |  | 
|  498         if (!this->readRow()) { |  487         if (!this->readRow()) { | 
|  499             *rowsDecoded = y; |  488             *rowsDecoded = y; | 
|  500             return gif_error("Could not decode line.\n", kIncompleteInput); |  489             return gif_error("Could not decode line.\n", kIncompleteInput); | 
|  501         } |  490         } | 
|  502         void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin
     e(y)); |  491         void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin
     e(y)); | 
|  503         fSwizzler->swizzle(dstRow, fSrcBuffer.get()); |  492         fSwizzler->swizzle(dstRow, fSrcBuffer.get()); | 
|  504     } |  493     } | 
|  505     return kSuccess; |  494     return kSuccess; | 
|  506 } |  495 } | 
|  507  |  496  | 
|  508 // FIXME: This is similar to the implementation for bmp and png.  Can we share m
     ore code or |  497 // FIXME: This is similar to the implementation for bmp and png.  Can we share m
     ore code or | 
|  509 //        possibly make this non-virtual? |  498 //        possibly make this non-virtual? | 
|  510 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType
     ) const { |  499 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType
     ) const { | 
|  511     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |  500     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 
|  512     return get_color_table_fill_value(colorType, colorPtr, fFillIndex); |  501     return get_color_table_fill_value(colorType, colorPtr, fFillIndex); | 
|  513 } |  502 } | 
|  514  |  503  | 
|  515 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, |  504 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, | 
|  516         const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor
     Count) { |  505         const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor
     Count) { | 
|  517  |  506     return this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->
     options()); | 
|  518     Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun
     t, this->options()); |  | 
|  519     if (kSuccess != result) { |  | 
|  520         return result; |  | 
|  521     } |  | 
|  522  |  | 
|  523     // Initialize the swizzler |  | 
|  524     if (fFrameIsSubset) { |  | 
|  525         const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr
     ameRect.height()); |  | 
|  526         if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) { |  | 
|  527             return gif_error("Could not initialize swizzler.\n", kUnimplemented)
     ; |  | 
|  528         } |  | 
|  529     } else { |  | 
|  530         if (kSuccess != this->initializeSwizzler(dstInfo, opts)) { |  | 
|  531             return gif_error("Could not initialize swizzler.\n", kUnimplemented)
     ; |  | 
|  532         } |  | 
|  533     } |  | 
|  534  |  | 
|  535     return kSuccess; |  | 
|  536 } |  507 } | 
|  537  |  508  | 
|  538 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |  509 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { | 
|  539     int rowsBeforeFrame = 0; |  510     int rowsBeforeFrame = 0; | 
|  540     int rowsAfterFrame = 0; |  511     int rowsAfterFrame = 0; | 
|  541     int rowsInFrame = count; |  512     int rowsInFrame = count; | 
|  542     if (fFrameIsSubset) { |  513     if (fFrameIsSubset) { | 
|  543         // Fill the requested rows |  514         // Fill the requested rows | 
|  544         SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), c
     ount); |  515         SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), c
     ount); | 
|  545         uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType(), |  516         uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType(), | 
|  546                 this->dstInfo().alphaType()); |  517                 this->dstInfo().alphaType()); | 
|  547         SkSampler::Fill(fillInfo, dst, rowBytes, fillValue, this->options().fZer
     oInitialized); |  518         fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZer
     oInitialized); | 
|  548  |  519  | 
|  549         // Do nothing for rows before the image frame |  520         // Do nothing for rows before the image frame | 
|  550         rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScan
     line()); |  521         rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScan
     line()); | 
|  551         rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame); |  522         rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame); | 
|  552         dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); |  523         dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); | 
|  553  |  524  | 
|  554         // Do nothing for rows after the image frame |  525         // Do nothing for rows after the image frame | 
|  555         rowsAfterFrame = SkTMax(0, |  526         rowsAfterFrame = SkTMax(0, | 
|  556                 this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.botto
     m()); |  527                 this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.botto
     m()); | 
|  557         rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame); |  528         rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame); | 
|  558  |  | 
|  559         // Adjust dst pointer for left offset |  | 
|  560         int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFr
     ameRect.left(); |  | 
|  561         dst = SkTAddOffset<void>(dst, offset); |  | 
|  562     } |  529     } | 
|  563  |  530  | 
|  564     for (int i = 0; i < rowsInFrame; i++) { |  531     for (int i = 0; i < rowsInFrame; i++) { | 
|  565         if (!this->readRow()) { |  532         if (!this->readRow()) { | 
|  566             return i + rowsBeforeFrame; |  533             return i + rowsBeforeFrame; | 
|  567         } |  534         } | 
|  568         fSwizzler->swizzle(dst, fSrcBuffer.get()); |  535         fSwizzler->swizzle(dst, fSrcBuffer.get()); | 
|  569         dst = SkTAddOffset<void>(dst, rowBytes); |  536         dst = SkTAddOffset<void>(dst, rowBytes); | 
|  570     } |  537     } | 
|  571  |  538  | 
|  572     return count; |  539     return count; | 
|  573 } |  540 } | 
|  574  |  541  | 
|  575 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { |  542 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { | 
|  576     if (fGif->Image.Interlace) { |  543     if (fGif->Image.Interlace) { | 
|  577         return kOutOfOrder_SkScanlineOrder; |  544         return kOutOfOrder_SkScanlineOrder; | 
|  578     } |  545     } | 
|  579     return kTopDown_SkScanlineOrder; |  546     return kTopDown_SkScanlineOrder; | 
|  580 } |  547 } | 
|  581  |  548  | 
|  582 int SkGifCodec::onOutputScanline(int inputScanline) const { |  549 int SkGifCodec::onOutputScanline(int inputScanline) const { | 
|  583     if (fGif->Image.Interlace) { |  550     if (fGif->Image.Interlace) { | 
|  584         if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott
     om()) { |  551         if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott
     om()) { | 
|  585             return inputScanline; |  552             return inputScanline; | 
|  586         } |  553         } | 
|  587         return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram
     eRect.height()); |  554         return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram
     eRect.height()) + | 
 |  555                 fFrameRect.top(); | 
|  588     } |  556     } | 
|  589     return inputScanline; |  557     return inputScanline; | 
|  590 } |  558 } | 
| OLD | NEW |