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::onStart(const SkImageInfo& dstInfo, const SkCodec::O
ptions& opts, |
586 // Should we implement reallyHasAlpha? Or should we read extens
ion blocks in the | 586 SkPMColor inputColorPtr[], int* inputColorCount) { |
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 int rowsBeforeFrame = fFrameDims.top() - this->INHERITED::getY(); |
698 if (!codec) { | 628 if (rowsBeforeFrame > 0) { |
699 return NULL; | 629 count = SkTMin(0, count - rowsBeforeFrame); |
| 630 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); |
| 631 } |
| 632 |
| 633 // Do nothing for rows after the image frame |
| 634 int rowsAfterFrame = this->INHERITED::getY() + count - fFrameDims.bottom
(); |
| 635 if (rowsAfterFrame > 0) { |
| 636 count = SkTMin(0, count - rowsAfterFrame); |
| 637 } |
| 638 |
| 639 // Adjust dst pointer for left offset |
| 640 int bpp = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrame
Dims.left(); |
| 641 dst = SkTAddOffset<void>(dst, bpp); |
700 } | 642 } |
701 | 643 |
702 const SkImageInfo& srcInfo = codec->getInfo(); | 644 for (int i = 0; i < count; i++) { |
| 645 if (kSuccess != this->readRow()) { |
| 646 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
| 647 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count - i, fFillInd
ex, colorPtr, |
| 648 this->options().fZeroInitialized); |
| 649 return gif_error("Could not decode line\n", SkCodec::kIncompleteInpu
t); |
| 650 } |
| 651 fSwizzler->swizzle(dst, fSrcBuffer.get()); |
| 652 dst = SkTAddOffset<void>(dst, rowBytes); |
| 653 } |
| 654 return SkCodec::kSuccess; |
| 655 } |
703 | 656 |
704 return new SkGifScanlineDecoder(srcInfo, codec.detach()); | 657 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { |
| 658 if (fGif->Image.Interlace) { |
| 659 return kOutOfOrder_SkScanlineOrder; |
| 660 } else { |
| 661 return kTopDown_SkScanlineOrder; |
| 662 } |
705 } | 663 } |
| 664 |
| 665 int SkGifCodec::onGetY() const { |
| 666 if (fGif->Image.Interlace) { |
| 667 return get_output_row_interlaced(this->INHERITED::onGetY(), this->dstInf
o().height()); |
| 668 } else { |
| 669 return this->INHERITED::onGetY(); |
| 670 } |
| 671 } |
| 672 |
OLD | NEW |