| 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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 height - y, fFillIndex, colorPtr, opts.fZeroInitialized)
; | 575 height - y, fFillIndex, colorPtr, opts.fZeroInitialized)
; |
| 576 return gif_error("Could not decode line\n", kIncompleteInput); | 576 return gif_error("Could not decode line\n", kIncompleteInput); |
| 577 } | 577 } |
| 578 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); | 578 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); |
| 579 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 579 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 580 } | 580 } |
| 581 } | 581 } |
| 582 return kSuccess; | 582 return kSuccess; |
| 583 } | 583 } |
| 584 | 584 |
| 585 // TODO (msarett): skbug.com/3582 | 585 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, |
| 586 // Should we implement reallyHasAlpha? Or should we read extens
ion blocks in the | 586 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor
Count) { |
| 587 // header? Or should we do both? | 587 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun
t, |
| 588 | 588 this->options()); |
| 589 class SkGifScanlineDecoder : public SkScanlineDecoder { | 589 if (kSuccess != result) { |
| 590 public: | 590 return result; |
| 591 SkGifScanlineDecoder(const SkImageInfo& srcInfo, SkGifCodec* codec) | |
| 592 : INHERITED(srcInfo) | |
| 593 , fCodec(codec) | |
| 594 {} | |
| 595 | |
| 596 SkEncodedFormat onGetEncodedFormat() const override { | |
| 597 return kGIF_SkEncodedFormat; | |
| 598 } | 591 } |
| 599 | 592 |
| 600 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options&
opts, | 593 // Check to see if scaling was requested. |
| 601 SkPMColor inputColorPtr[], int* inputColorCount) ove
rride { | 594 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 602 SkCodec::Result result = fCodec->prepareToDecode(dstInfo, inputColorPtr,
inputColorCount, | 595 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI
nfo)) { |
| 603 this->options()); | 596 return gif_error("Scaling not supported.\n", SkCodec::kInvalidScale)
; |
| 604 if (SkCodec::kSuccess != result) { | |
| 605 return result; | |
| 606 } | |
| 607 | |
| 608 // Check to see if scaling was requested. | |
| 609 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | |
| 610 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(),
dstInfo)) { | |
| 611 return gif_error("Scaling not supported.\n", SkCodec::kInvalidSc
ale); | |
| 612 } | |
| 613 } | |
| 614 | |
| 615 // Initialize the swizzler | |
| 616 if (fCodec->fFrameIsSubset) { | |
| 617 int sampleX; | |
| 618 SkScaledCodec::ComputeSampleSize(dstInfo, fCodec->getInfo(), &sample
X, NULL); | |
| 619 const SkImageInfo subsetDstInfo = dstInfo.makeWH( | |
| 620 get_scaled_dimension(fCodec->fFrameDims.width(), sampleX), | |
| 621 fCodec->fFrameDims.height()); | |
| 622 if (SkCodec::kSuccess != fCodec->initializeSwizzler(subsetDstInfo, | |
| 623 opts.fZeroInitialized)) { | |
| 624 return gif_error("Could not initialize swizzler.\n", SkCodec::kU
nimplemented); | |
| 625 } | |
| 626 } else { | |
| 627 if (SkCodec::kSuccess != fCodec->initializeSwizzler(dstInfo, opts.fZ
eroInitialized)) { | |
| 628 return gif_error("Could not initialize swizzler.\n", SkCodec::kU
nimplemented); | |
| 629 } | |
| 630 } | |
| 631 | |
| 632 return SkCodec::kSuccess; | |
| 633 } | |
| 634 | |
| 635 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { | |
| 636 if (fCodec->fFrameIsSubset) { | |
| 637 // Fill the requested rows | |
| 638 const SkPMColor* colorPtr = get_color_ptr(fCodec->fColorTable.get())
; | |
| 639 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fCodec->fFil
lIndex, | |
| 640 colorPtr, this->options().fZeroInitialized); | |
| 641 | |
| 642 // Do nothing for rows before the image frame | |
| 643 int rowsBeforeFrame = fCodec->fFrameDims.top() - INHERITED::getY(); | |
| 644 if (rowsBeforeFrame > 0) { | |
| 645 count = SkTMin(0, count - rowsBeforeFrame); | |
| 646 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); | |
| 647 } | |
| 648 | |
| 649 // Do nothing for rows after the image frame | |
| 650 int rowsAfterFrame = INHERITED::getY() + count - fCodec->fFrameDims.
bottom(); | |
| 651 if (rowsAfterFrame > 0) { | |
| 652 count = SkTMin(0, count - rowsAfterFrame); | |
| 653 } | |
| 654 | |
| 655 // Adjust dst pointer for left offset | |
| 656 dst = SkTAddOffset<void>(dst, SkColorTypeBytesPerPixel( | |
| 657 this->dstInfo().colorType()) * fCodec->fFrameDims.left()); | |
| 658 } | |
| 659 | |
| 660 for (int i = 0; i < count; i++) { | |
| 661 if (SkCodec::kSuccess != fCodec->readRow()) { | |
| 662 const SkPMColor* colorPtr = get_color_ptr(fCodec->fColorTable.ge
t()); | |
| 663 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, | |
| 664 count - i, fCodec->fFillIndex, colorPtr, | |
| 665 this->options().fZeroInitialized); | |
| 666 return gif_error("Could not decode line\n", SkCodec::kIncomplete
Input); | |
| 667 } | |
| 668 fCodec->fSwizzler->swizzle(dst, fCodec->fSrcBuffer.get()); | |
| 669 dst = SkTAddOffset<void>(dst, rowBytes); | |
| 670 } | |
| 671 return SkCodec::kSuccess; | |
| 672 } | |
| 673 | |
| 674 SkScanlineOrder onGetScanlineOrder() const override { | |
| 675 if (fCodec->fGif->Image.Interlace) { | |
| 676 return kOutOfOrder_SkScanlineOrder; | |
| 677 } else { | |
| 678 return kTopDown_SkScanlineOrder; | |
| 679 } | 597 } |
| 680 } | 598 } |
| 681 | 599 |
| 682 int onGetY() const override { | 600 // Initialize the swizzler |
| 683 if (fCodec->fGif->Image.Interlace) { | 601 if (fFrameIsSubset) { |
| 684 return get_output_row_interlaced(INHERITED::onGetY(), this->dstInfo(
).height()); | 602 int sampleX; |
| 685 } else { | 603 SkScaledCodec::ComputeSampleSize(dstInfo, this->getInfo(), &sampleX, NUL
L); |
| 686 return INHERITED::onGetY(); | 604 const SkImageInfo subsetDstInfo = dstInfo.makeWH( |
| 605 get_scaled_dimension(fFrameDims.width(), sampleX), |
| 606 fFrameDims.height()); |
| 607 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia
lized)) { |
| 608 return gif_error("Could not initialize swizzler.\n", kUnimplemented)
; |
| 609 } |
| 610 } else { |
| 611 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized)
) { |
| 612 return gif_error("Could not initialize swizzler.\n", kUnimplemented)
; |
| 687 } | 613 } |
| 688 } | 614 } |
| 689 | 615 |
| 690 private: | 616 return kSuccess; |
| 691 SkAutoTDelete<SkGifCodec> fCodec; | 617 } |
| 692 | 618 |
| 693 typedef SkScanlineDecoder INHERITED; | 619 SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes
) { |
| 694 }; | 620 if (fFrameIsSubset) { |
| 621 // Fill the requested rows |
| 622 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
| 623 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fFillIndex, |
| 624 colorPtr, this->options().fZeroInitialized); |
| 695 | 625 |
| 696 SkScanlineDecoder* SkGifCodec::NewSDFromStream(SkStream* stream) { | 626 // Do nothing for rows before the image frame |
| 697 SkAutoTDelete<SkGifCodec> codec (static_cast<SkGifCodec*>(SkGifCodec::NewFro
mStream(stream))); | 627 // FIXME: nextScanline is not virtual, so using "INHERITED" does not cha
nge |
| 698 if (!codec) { | 628 // behavior. Was the intent to call this->INHERITED::onNextScanline()? S
ame |
| 699 return NULL; | 629 // for the next call down below. |
| 630 int rowsBeforeFrame = fFrameDims.top() - this->INHERITED::nextScanline()
; |
| 631 if (rowsBeforeFrame > 0) { |
| 632 count = SkTMin(0, count - rowsBeforeFrame); |
| 633 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); |
| 634 } |
| 635 |
| 636 // Do nothing for rows after the image frame |
| 637 int rowsAfterFrame = this->INHERITED::nextScanline() + count - fFrameDim
s.bottom(); |
| 638 if (rowsAfterFrame > 0) { |
| 639 count = SkTMin(0, count - rowsAfterFrame); |
| 640 } |
| 641 |
| 642 // Adjust dst pointer for left offset |
| 643 int bpp = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrame
Dims.left(); |
| 644 dst = SkTAddOffset<void>(dst, bpp); |
| 700 } | 645 } |
| 701 | 646 |
| 702 const SkImageInfo& srcInfo = codec->getInfo(); | 647 for (int i = 0; i < count; i++) { |
| 648 if (kSuccess != this->readRow()) { |
| 649 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
| 650 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count - i, fFillInd
ex, colorPtr, |
| 651 this->options().fZeroInitialized); |
| 652 return gif_error("Could not decode line\n", SkCodec::kIncompleteInpu
t); |
| 653 } |
| 654 fSwizzler->swizzle(dst, fSrcBuffer.get()); |
| 655 dst = SkTAddOffset<void>(dst, rowBytes); |
| 656 } |
| 657 return SkCodec::kSuccess; |
| 658 } |
| 703 | 659 |
| 704 return new SkGifScanlineDecoder(srcInfo, codec.detach()); | 660 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { |
| 661 if (fGif->Image.Interlace) { |
| 662 return kOutOfOrder_SkScanlineOrder; |
| 663 } else { |
| 664 return kTopDown_SkScanlineOrder; |
| 665 } |
| 705 } | 666 } |
| 667 |
| 668 int SkGifCodec::onNextScanline() const { |
| 669 if (fGif->Image.Interlace) { |
| 670 return get_output_row_interlaced(this->INHERITED::onNextScanline(), this
->dstInfo().height()); |
| 671 } else { |
| 672 return this->INHERITED::onNextScanline(); |
| 673 } |
| 674 } |
| 675 |
| OLD | NEW |