Switch SkCodec to int for counts and indices
authorLeon Scroggins III <scroggo@google.com>
Mon, 17 Apr 2017 16:46:33 +0000 (12:46 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Mon, 17 Apr 2017 17:38:35 +0000 (17:38 +0000)
This matches other Skia APIs. size_t was adopted from blink/
GIFImageReader.

Change-Id: Ic83e59f0942f597c4fb834e623acd9886ad483fe
Reviewed-on: https://skia-review.googlesource.com/13274
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
Reviewed-by: Chris Blume <cblume@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>

dm/DMSrcSink.cpp
gm/animatedGif.cpp
include/codec/SkCodec.h
src/codec/SkCodec.cpp
src/codec/SkGifCodec.cpp
src/codec/SkGifCodec.h
tests/CodecAnimTest.cpp
tests/CodecTest.cpp
third_party/gif/SkGifImageReader.cpp
third_party/gif/SkGifImageReader.h

index b223c97..ebcda38 100644 (file)
@@ -465,11 +465,11 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
 
             // Used to cache a frame that future frames will depend on.
             SkAutoMalloc priorFramePixels;
-            size_t cachedFrame = SkCodec::kNone;
-            for (size_t i = 0; i < frameInfos.size(); i++) {
+            int cachedFrame = SkCodec::kNone;
+            for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) {
                 options.fFrameIndex = i;
                 // Check for a prior frame
-                const size_t reqFrame = frameInfos[i].fRequiredFrame;
+                const int reqFrame = frameInfos[i].fRequiredFrame;
                 if (reqFrame != SkCodec::kNone && reqFrame == cachedFrame
                         && priorFramePixels.get()) {
                     // Copy into pixels
@@ -514,7 +514,8 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
 
                 // If a future frame depends on this one, store it in priorFrame.
                 // (Note that if i+1 does *not* depend on i, then no future frame can.)
-                if (i+1 < frameInfos.size() && frameInfos[i+1].fRequiredFrame == i) {
+                if (static_cast<size_t>(i+1) < frameInfos.size()
+                        && frameInfos[i+1].fRequiredFrame == i) {
                     memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize);
                     cachedFrame = i;
                 }
index 03bf66c..c7871e0 100644 (file)
@@ -34,9 +34,9 @@ namespace {
 class AnimatedGifGM : public skiagm::GM {
 private:
     std::unique_ptr<SkCodec>        fCodec;
-    size_t                          fFrame;
+    int                             fFrame;
     double                          fNextUpdate;
-    size_t                          fTotalFrames;
+    int                             fTotalFrames;
     std::vector<SkCodec::FrameInfo> fFrameInfos;
     std::vector<SkBitmap>           fFrames;
 
@@ -53,9 +53,10 @@ private:
             SkCodec::Options opts;
             opts.fFrameIndex = frameIndex;
             opts.fHasPriorFrame = false;
-            const size_t requiredFrame = fFrameInfos[frameIndex].fRequiredFrame;
+            const int requiredFrame = fFrameInfos[frameIndex].fRequiredFrame;
             if (requiredFrame != SkCodec::kNone) {
-                SkASSERT(requiredFrame < fFrames.size());
+                SkASSERT(requiredFrame >= 0
+                         && static_cast<size_t>(requiredFrame) < fFrames.size());
                 SkBitmap& requiredBitmap = fFrames[requiredFrame];
                 // For simplicity, do not try to cache old frames
                 if (requiredBitmap.getPixels() && requiredBitmap.copyTo(&bm)) {
@@ -101,7 +102,7 @@ private:
         canvas->clear(SK_ColorWHITE);
         if (this->initCodec()) {
             SkAutoCanvasRestore acr(canvas, true);
-            for (size_t frameIndex = 0; frameIndex < fTotalFrames; frameIndex++) {
+            for (int frameIndex = 0; frameIndex < fTotalFrames; frameIndex++) {
                 this->drawFrame(canvas, frameIndex);
                 canvas->translate(SkIntToScalar(fCodec->getInfo().width()), 0);
             }
index aadcb05..7f88fc6 100644 (file)
@@ -277,7 +277,7 @@ public:
          *
          *  Only meaningful for multi-frame images.
          */
-        size_t                     fFrameIndex;
+        int                        fFrameIndex;
 
         /**
          *  If true, the dst already contains the prior frame.
@@ -598,13 +598,13 @@ public:
      *
      *  May require reading through the stream.
      */
-    size_t getFrameCount() {
+    int getFrameCount() {
         return this->onGetFrameCount();
     }
 
     // The required frame for an independent frame is marked as
     // kNone.
-    static constexpr size_t kNone = static_cast<size_t>(-1);
+    static constexpr int kNone = -1;
 
     /**
      *  Information about individual frames in a multi-framed image.
@@ -614,12 +614,12 @@ public:
          *  The frame that this frame needs to be blended with, or
          *  kNone.
          */
-        size_t fRequiredFrame;
+        int fRequiredFrame;
 
         /**
          *  Number of milliseconds to show this frame.
          */
-        size_t fDuration;
+        int fDuration;
 
         /**
          *  Whether the end marker for this frame is contained in the stream.
@@ -643,7 +643,7 @@ public:
      *  so it should be called after getFrameCount() to parse any frames that
      *  have not already been parsed.
      */
-    bool getFrameInfo(size_t index, FrameInfo* info) const {
+    bool getFrameInfo(int index, FrameInfo* info) const {
         return this->onGetFrameInfo(index, info);
     }
 
@@ -818,11 +818,11 @@ protected:
                               SkTransferFunctionBehavior premulBehavior);
     SkColorSpaceXform* colorXform() const { return fColorXform.get(); }
 
-    virtual size_t onGetFrameCount() {
+    virtual int onGetFrameCount() {
         return 1;
     }
 
-    virtual bool onGetFrameInfo(size_t, FrameInfo*) const {
+    virtual bool onGetFrameInfo(int, FrameInfo*) const {
         return false;
     }
 
index 6a6fdc7..9e693b1 100644 (file)
@@ -491,22 +491,20 @@ bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo,
 }
 
 std::vector<SkCodec::FrameInfo> SkCodec::getFrameInfo() {
-    const size_t frameCount = this->getFrameCount();
-    switch (frameCount) {
-        case 0:
-            return std::vector<FrameInfo>{};
-        case 1:
-            if (!this->onGetFrameInfo(0, nullptr)) {
-                // Not animated.
-                return std::vector<FrameInfo>{};
-            }
-            // fall through
-        default: {
-            std::vector<FrameInfo> result(frameCount);
-            for (size_t i = 0; i < frameCount; ++i) {
-                SkAssertResult(this->onGetFrameInfo(i, &result[i]));
-            }
-            return result;
-        }
+    const int frameCount = this->getFrameCount();
+    SkASSERT(frameCount >= 0);
+    if (frameCount <= 0) {
+        return std::vector<FrameInfo>{};
     }
+
+    if (frameCount == 1 && !this->onGetFrameInfo(0, nullptr)) {
+        // Not animated.
+        return std::vector<FrameInfo>{};
+    }
+
+    std::vector<FrameInfo> result(frameCount);
+    for (int i = 0; i < frameCount; ++i) {
+        SkAssertResult(this->onGetFrameInfo(i, &result[i]));
+    }
+    return result;
 }
index 2e0ec30..2584ee5 100644 (file)
@@ -132,12 +132,12 @@ SkGifCodec::SkGifCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imag
     reader->setClient(this);
 }
 
-size_t SkGifCodec::onGetFrameCount() {
+int SkGifCodec::onGetFrameCount() {
     fReader->parse(SkGifImageReader::SkGIFFrameCountQuery);
     return fReader->imagesCount();
 }
 
-bool SkGifCodec::onGetFrameInfo(size_t i, SkCodec::FrameInfo* frameInfo) const {
+bool SkGifCodec::onGetFrameInfo(int i, SkCodec::FrameInfo* frameInfo) const {
     if (i >= fReader->imagesCount()) {
         return false;
     }
@@ -164,7 +164,7 @@ int SkGifCodec::onGetRepetitionCount() {
 
 static const SkColorType kXformSrcColorType = kRGBA_8888_SkColorType;
 
-void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex) {
+void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, int frameIndex) {
     SkColorType colorTableColorType = dstInfo.colorType();
     if (this->colorXform()) {
         colorTableColorType = kXformSrcColorType;
@@ -215,7 +215,7 @@ SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo
         return gif_error("Subsets not supported.\n", kUnimplemented);
     }
 
-    const size_t frameIndex = opts.fFrameIndex;
+    const int frameIndex = opts.fFrameIndex;
     if (frameIndex > 0) {
         switch (dstInfo.colorType()) {
             case kIndex_8_SkColorType:
@@ -276,7 +276,7 @@ SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo
     return kSuccess;
 }
 
-void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, size_t frameIndex) {
+void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex) {
     const SkGIFFrameContext* frame = fReader->frameContext(frameIndex);
     // This is only called by prepareToDecode, which ensures frameIndex is in range.
     SkASSERT(frame);
@@ -365,7 +365,7 @@ SkCodec::Result SkGifCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo,
 SkCodec::Result SkGifCodec::onIncrementalDecode(int* rowsDecoded) {
     // It is possible the client has appended more data. Parse, if needed.
     const auto& options = this->options();
-    const size_t frameIndex = options.fFrameIndex;
+    const int frameIndex = options.fFrameIndex;
     fReader->parse((SkGifImageReader::SkGIFParseQuery) frameIndex);
 
     const bool firstCallToIncrementalDecode = fFirstCallToIncrementalDecode;
@@ -375,7 +375,7 @@ SkCodec::Result SkGifCodec::onIncrementalDecode(int* rowsDecoded) {
 
 SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded) {
     const SkImageInfo& dstInfo = this->dstInfo();
-    const size_t frameIndex = opts.fFrameIndex;
+    const int frameIndex = opts.fFrameIndex;
     SkASSERT(frameIndex < fReader->imagesCount());
     const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
     if (firstAttempt) {
@@ -500,8 +500,8 @@ uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
         // compatibity on Android, so we are using the color table for the first frame.
         SkASSERT(this->options().fFrameIndex == 0);
         // Use the transparent index for the first frame.
-        const size_t transPixel = fReader->frameContext(0)->transparentPixel();
-        if (transPixel < (size_t) fCurrColorTable->count()) {
+        const int transPixel = fReader->frameContext(0)->transparentPixel();
+        if (transPixel >= 0 && transPixel < fCurrColorTable->count()) {
             return transPixel;
         }
         // Fall through to return SK_ColorTRANSPARENT (i.e. 0). This choice is arbitrary,
@@ -532,8 +532,8 @@ void SkGifCodec::applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint
     }
 }
 
-bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin,
-                                size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels)
+bool SkGifCodec::haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
+                                int rowNumber, int repeatCount, bool writeTransparentPixels)
 {
     const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
     // The pixel data and coordinates supplied to us are relative to the frame's
@@ -542,13 +542,11 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin
     // that width == (size().width() - frameContext->xOffset), so
     // we must ensure we don't run off the end of either the source data or the
     // row's X-coordinates.
-    const size_t width = frameContext->width();
+    const int width = frameContext->width();
     const int xBegin = frameContext->xOffset();
     const int yBegin = frameContext->yOffset() + rowNumber;
-    const int xEnd = std::min(static_cast<int>(frameContext->xOffset() + width),
-                              this->getInfo().width());
-    const int yEnd = std::min(static_cast<int>(frameContext->yOffset() + rowNumber + repeatCount),
-                              this->getInfo().height());
+    const int xEnd = std::min(xBegin + width, this->getInfo().width());
+    const int yEnd = std::min(yBegin + rowNumber + repeatCount, this->getInfo().height());
     // FIXME: No need to make the checks on width/xBegin/xEnd for every row. We could instead do
     // this once in prepareToDecode.
     if (!width || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
@@ -563,7 +561,7 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin
         // Check to see whether this row or one that falls in the repeatCount is needed in the
         // output.
         bool foundNecessaryRow = false;
-        for (unsigned i = 0; i < repeatCount; i++) {
+        for (int i = 0; i < repeatCount; i++) {
             const int potentialRow = yBegin + i;
             if (fSwizzler->rowNeeded(potentialRow)) {
                 dstRow = potentialRow / sampleY;
@@ -578,7 +576,7 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin
                 repeatCount = (repeatCount - 1) / sampleY + 1;
 
                 // Make sure the repeatCount does not take us beyond the end of the dst
-                if (dstRow + (int) repeatCount > scaledHeight) {
+                if (dstRow + repeatCount > scaledHeight) {
                     repeatCount = scaledHeight - dstRow;
                     SkASSERT(repeatCount >= 1);
                 }
@@ -592,7 +590,7 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin
     } else {
         // Make sure the repeatCount does not take us beyond the end of the dst
         SkASSERT(this->dstInfo().height() >= yBegin);
-        repeatCount = SkTMin(repeatCount, (unsigned) (this->dstInfo().height() - yBegin));
+        repeatCount = SkTMin(repeatCount, this->dstInfo().height() - yBegin);
     }
 
     if (!fFilledBackground) {
@@ -665,7 +663,7 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin
         const size_t bytesToCopy = fSwizzler->swizzleWidth() * bytesPerPixel;
         void* copiedLine = SkTAddOffset<void>(dstLine, fSwizzler->swizzleOffsetBytes());
         void* dst = copiedLine;
-        for (unsigned i = 1; i < repeatCount; i++) {
+        for (int i = 1; i < repeatCount; i++) {
             dst = SkTAddOffset<void>(dst, fDstRowBytes);
             memcpy(dst, copiedLine, bytesToCopy);
         }
index 11714eb..9cb6632 100644 (file)
@@ -33,8 +33,8 @@ public:
     static SkCodec* NewFromStream(SkStream*);
 
     // Callback for SkGifImageReader when a row is available.
-    bool haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin,
-                        size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels);
+    bool haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
+                        int rowNumber, int repeatCount, bool writeTransparentPixels);
 protected:
     /*
      * Performs the full gif decode
@@ -50,8 +50,8 @@ protected:
 
     uint64_t onGetFillValue(const SkImageInfo&) const override;
 
-    size_t onGetFrameCount() override;
-    bool onGetFrameInfo(size_t, FrameInfo*) const override;
+    int onGetFrameCount() override;
+    bool onGetFrameInfo(int, FrameInfo*) const override;
     int onGetRepetitionCount() override;
 
     Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
@@ -67,7 +67,7 @@ private:
      * @param dstInfo         Contains the requested dst color type.
      * @param frameIndex      Frame whose color table to use.
      */
-    void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex);
+    void initializeColorTable(const SkImageInfo& dstInfo, int frameIndex);
 
    /*
     * Does necessary setup, including setting up the color table and swizzler,
@@ -85,7 +85,7 @@ private:
      * @param frameIndex Which frame we are decoding. This determines the frameRect
      *                   to use.
      */
-    void initializeSwizzler(const SkImageInfo& dstInfo, size_t frameIndex);
+    void initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex);
 
     SkSampler* getSampler(bool createIfNecessary) override {
         SkASSERT(fSwizzler);
index 3d7080e..79e03bd 100644 (file)
@@ -43,15 +43,15 @@ DEF_TEST(Codec_frames, r) {
     #define kUnpremul   kUnpremul_SkAlphaType
     static const struct {
         const char*              fName;
-        size_t                   fFrameCount;
+        int                      fFrameCount;
         // One less than fFramecount, since the first frame is always
         // independent.
-        std::vector<size_t>      fRequiredFrames;
+        std::vector<int>         fRequiredFrames;
         // Same, since the first frame should match getInfo.
         std::vector<SkAlphaType> fAlphaTypes;
         // The size of this one should match fFrameCount for animated, empty
         // otherwise.
-        std::vector<size_t>      fDurations;
+        std::vector<int>         fDurations;
         int                      fRepetitionCount;
     } gRecs[] = {
         { "alphabetAnim.gif", 13,
@@ -126,14 +126,14 @@ DEF_TEST(Codec_frames, r) {
                       rec.fName, rec.fRepetitionCount, repetitionCount);
         }
 
-        const size_t expected = rec.fFrameCount;
-        if (rec.fRequiredFrames.size() + 1 != expected) {
+        const int expected = rec.fFrameCount;
+        if (rec.fRequiredFrames.size() + 1 != static_cast<size_t>(expected)) {
             ERRORF(r, "'%s' has wrong number entries in fRequiredFrames; expected: %i\tactual: %i",
                    rec.fName, expected, rec.fRequiredFrames.size() + 1);
             continue;
         }
 
-        if (rec.fDurations.size() != expected) {
+        if (rec.fDurations.size() != static_cast<size_t>(expected)) {
             ERRORF(r, "'%s' has wrong number entries in fDurations; expected: %i\tactual: %i",
                    rec.fName, expected, rec.fDurations.size());
             continue;
@@ -148,7 +148,7 @@ DEF_TEST(Codec_frames, r) {
             // Re-create the codec to reset state and test parsing.
             codec.reset(SkCodec::NewFromData(data));
 
-            size_t frameCount;
+            int frameCount;
             std::vector<SkCodec::FrameInfo> frameInfos;
             switch (mode) {
                 case TestMode::kVector:
@@ -172,7 +172,7 @@ DEF_TEST(Codec_frames, r) {
                 continue;
             }
 
-            for (size_t i = 0; i < frameCount; i++) {
+            for (int i = 0; i < frameCount; i++) {
                 SkCodec::FrameInfo frameInfo;
                 switch (mode) {
                     case TestMode::kVector:
@@ -233,11 +233,11 @@ DEF_TEST(Codec_frames, r) {
             std::vector<SkBitmap> cachedFrames(frameCount);
             const auto& info = codec->getInfo().makeColorType(kN32_SkColorType);
 
-            auto decode = [&](SkBitmap* bm, bool cached, size_t index) {
+            auto decode = [&](SkBitmap* bm, bool cached, int index) {
                 bm->allocPixels(info);
                 if (cached) {
                     // First copy the pixels from the cached frame
-                    const size_t requiredFrame = frameInfos[index].fRequiredFrame;
+                    const int requiredFrame = frameInfos[index].fRequiredFrame;
                     if (requiredFrame != SkCodec::kNone) {
                         const bool success = cachedFrames[requiredFrame].copyTo(bm);
                         REPORTER_ASSERT(r, success);
@@ -251,7 +251,7 @@ DEF_TEST(Codec_frames, r) {
                 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
             };
 
-            for (size_t i = 0; i < frameCount; i++) {
+            for (int i = 0; i < frameCount; i++) {
                 SkBitmap& cachedFrame = cachedFrames[i];
                 decode(&cachedFrame, true, i);
                 SkBitmap uncachedFrame;
index ceafa15..5224054 100644 (file)
@@ -1508,7 +1508,7 @@ DEF_TEST(Codec_InvalidAnimated, r) {
 
     auto frameInfos = codec->getFrameInfo();
     SkCodec::Options opts;
-    for (size_t i = 0; i < frameInfos.size(); i++) {
+    for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) {
         opts.fFrameIndex = i;
         opts.fHasPriorFrame = frameInfos[i].fRequiredFrame == i - 1;
         auto result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes(), &opts);
index 86768e3..8c5cfa1 100644 (file)
@@ -202,7 +202,7 @@ bool SkGIFLZWContext::outputRow(const unsigned char* rowBegin)
 // Otherwise, decoding failed; returns false in this case, which will always cause the SkGifImageReader to set the "decode failed" flag.
 bool SkGIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
 {
-    const size_t width = m_frameContext->width();
+    const int width = m_frameContext->width();
 
     if (rowIter == rowBuffer.end())
         return true;
@@ -306,14 +306,14 @@ bool SkGIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
 }
 
 sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkColorType colorType,
-                                              size_t transparentPixel) const
+                                              int transparentPixel) const
 {
     if (!m_isDefined)
         return nullptr;
 
     const PackColorProc proc = choose_pack_color_proc(false, colorType);
     if (m_table && proc == m_packColorProc && m_transPixel == transparentPixel) {
-        SkASSERT(transparentPixel > (unsigned) m_table->count()
+        SkASSERT(transparentPixel == kNotFound || transparentPixel > m_table->count()
                 || m_table->operator[](transparentPixel) == SK_ColorTRANSPARENT);
         // This SkColorTable has already been built with the same transparent color and
         // packing proc. Reuse it.
@@ -331,7 +331,7 @@ sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkCo
     SkASSERT(m_colors <= SK_MAX_COLORS);
     const uint8_t* srcColormap = rawData->bytes();
     SkPMColor colorStorage[SK_MAX_COLORS];
-    for (size_t i = 0; i < m_colors; i++) {
+    for (int i = 0; i < m_colors; i++) {
         if (i == transparentPixel) {
             colorStorage[i] = SK_ColorTRANSPARENT;
         } else {
@@ -339,21 +339,21 @@ sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkCo
         }
         srcColormap += SK_BYTES_PER_COLORMAP_ENTRY;
     }
-    for (size_t i = m_colors; i < SK_MAX_COLORS; i++) {
+    for (int i = m_colors; i < SK_MAX_COLORS; i++) {
         colorStorage[i] = SK_ColorTRANSPARENT;
     }
     m_table = sk_sp<SkColorTable>(new SkColorTable(colorStorage, SK_MAX_COLORS));
     return m_table;
 }
 
-sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, size_t index) {
-    if (index >= m_frames.size()) {
+sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, int index) {
+    if (index < 0 || static_cast<size_t>(index) >= m_frames.size()) {
         return nullptr;
     }
 
     const SkGIFFrameContext* frameContext = m_frames[index].get();
     const SkGIFColorMap& localColorMap = frameContext->localColorMap();
-    const size_t transPix = frameContext->transparentPixel();
+    const int transPix = frameContext->transparentPixel();
     if (localColorMap.isDefined()) {
         return localColorMap.buildTable(&m_streamBuffer, colorType, transPix);
     }
@@ -385,7 +385,8 @@ bool SkGIFFrameContext::decode(SkStreamBuffer* streamBuffer, SkGifCodec* client,
     }
 
     // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode.
-    while (m_currentLzwBlock < m_lzwBlocks.size() && m_lzwContext->hasRemainingRows()) {
+    while (static_cast<size_t>(m_currentLzwBlock) < m_lzwBlocks.size()
+           && m_lzwContext->hasRemainingRows()) {
         const auto& block = m_lzwBlocks[m_currentLzwBlock];
         const size_t len = block.blockSize;
 
@@ -411,7 +412,7 @@ bool SkGIFFrameContext::decode(SkStreamBuffer* streamBuffer, SkGifCodec* client,
 // Decode a frame.
 // This method uses SkGIFFrameContext:decode() to decode the frame; decoding error is reported to client as a critical failure.
 // Return true if decoding has progressed. Return false if an error has occurred.
-bool SkGifImageReader::decode(size_t frameIndex, bool* frameComplete)
+bool SkGifImageReader::decode(int frameIndex, bool* frameComplete)
 {
     SkGIFFrameContext* currentFrame = m_frames[frameIndex].get();
 
@@ -493,7 +494,7 @@ bool SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
             m_screenWidth = GETINT16(currentComponent);
             m_screenHeight = GETINT16(currentComponent + 2);
 
-            const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07);
+            const int globalColorMapColors = 2 << (currentComponent[4] & 0x07);
 
             if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* global map */
                 m_globalColorMap.setNumColors(globalColorMapColors);
@@ -753,7 +754,7 @@ bool SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
 
             const bool isLocalColormapDefined = SkToBool(currentComponent[8] & 0x80);
             // The three low-order bits of currentComponent[8] specify the bits per pixel.
-            const size_t numColors = 2 << (currentComponent[8] & 0x7);
+            const int numColors = 2 << (currentComponent[8] & 0x7);
             if (currentFrameIsFirstFrame()) {
                 if (hasTransparentPixel(0, isLocalColormapDefined, numColors)) {
                     m_firstFrameHasAlpha = true;
@@ -851,9 +852,10 @@ bool SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
     return true;
 }
 
-bool SkGifImageReader::hasTransparentPixel(size_t i, bool isLocalColormapDefined,
-                                           size_t localColors) {
-    if (m_frames.size() <= i) {
+bool SkGifImageReader::hasTransparentPixel(int i, bool isLocalColormapDefined,
+                                           int localColors) {
+    SkASSERT(i >= 0);
+    if (m_frames.size() <= static_cast<size_t>(i)) {
         // This should only happen when parsing the first frame.
         SkASSERT(0 == i);
 
@@ -863,12 +865,17 @@ bool SkGifImageReader::hasTransparentPixel(size_t i, bool isLocalColormapDefined
         return !isLocalColormapDefined && m_globalColorMap.numColors() == 0;
     }
 
-    const size_t transparentPixel = m_frames[i]->transparentPixel();
+    const int transparentPixel = m_frames[i]->transparentPixel();
+    if (transparentPixel < 0) {
+        SkASSERT(SkGIFColorMap::kNotFound == transparentPixel);
+        return false;
+    }
+
     if (isLocalColormapDefined) {
         return transparentPixel < localColors;
     }
 
-    const size_t globalColors = m_globalColorMap.numColors();
+    const int globalColors = m_globalColorMap.numColors();
     if (!globalColors) {
         // No color table for this frame, so the frame is empty.
         // This is technically different from having a transparent
@@ -886,7 +893,7 @@ void SkGifImageReader::addFrameIfNecessary()
 {
     if (m_frames.empty() || m_frames.back()->isComplete()) {
         const size_t i = m_frames.size();
-        std::unique_ptr<SkGIFFrameContext> frame(new SkGIFFrameContext(i));
+        std::unique_ptr<SkGIFFrameContext> frame(new SkGIFFrameContext(static_cast<int>(i)));
         m_frames.push_back(std::move(frame));
     }
 }
@@ -909,7 +916,7 @@ static bool restore_bg(const SkGIFFrameContext& frame) {
 }
 
 void SkGifImageReader::setAlphaAndRequiredFrame(SkGIFFrameContext* frame) {
-    const size_t i = frame->frameId();
+    const int i = frame->frameId();
     if (0 == i) {
         frame->setHasAlpha(m_firstFrameHasAlpha);
         frame->setRequiredFrame(SkCodec::kNone);
@@ -933,7 +940,7 @@ void SkGifImageReader::setAlphaAndRequiredFrame(SkGIFFrameContext* frame) {
 
     const SkGIFFrameContext* prevFrame = m_frames[i - 1].get();
     while (prevFrame->getDisposalMethod() == SkCodecAnimation::RestorePrevious_DisposalMethod) {
-        const size_t prevId = prevFrame->frameId();
+        const int prevId = prevFrame->frameId();
         if (0 == prevId) {
             frame->setHasAlpha(true);
             frame->setRequiredFrame(SkCodec::kNone);
@@ -965,7 +972,7 @@ void SkGifImageReader::setAlphaAndRequiredFrame(SkGIFFrameContext* frame) {
     }
 
     while (frameRect.contains(prevFrameRect)) {
-        const size_t prevRequiredFrame = prevFrame->getRequiredFrame();
+        const int prevRequiredFrame = prevFrame->getRequiredFrame();
         if (prevRequiredFrame == SkCodec::kNone) {
             frame->setRequiredFrame(SkCodec::kNone);
             frame->setHasAlpha(true);
index 9d69e48..4667f79 100644 (file)
@@ -148,7 +148,7 @@ struct SkGIFLZWBlock {
 
 class SkGIFColorMap final {
 public:
-    static constexpr size_t kNotFound = static_cast<size_t>(-1);
+    static constexpr int kNotFound = -1;
 
     SkGIFColorMap()
         : m_isDefined(false)
@@ -159,7 +159,7 @@ public:
     {
     }
 
-    void setNumColors(size_t colors) {
+    void setNumColors(int colors) {
         SkASSERT(!m_colors);
         SkASSERT(!m_position);
 
@@ -173,20 +173,20 @@ public:
         m_isDefined = true;
     }
 
-    size_t numColors() const { return m_colors; }
+    int numColors() const { return m_colors; }
 
     bool isDefined() const { return m_isDefined; }
 
     // Build RGBA table using the data stream.
     sk_sp<SkColorTable> buildTable(SkStreamBuffer*, SkColorType dstColorType,
-                                   size_t transparentPixel) const;
+                                   int transparentPixel) const;
 
 private:
     bool m_isDefined;
     size_t m_position;
-    size_t m_colors;
+    int m_colors;
     // Cached values. If these match on a new request, we can reuse m_table.
-    mutable size_t m_transPixel;
+    mutable int m_transPixel;
     mutable PackColorProc m_packColorProc;
     mutable sk_sp<SkColorTable> m_table;
 };
@@ -239,18 +239,18 @@ public:
     unsigned yOffset() const { return m_yOffset; }
     unsigned width() const { return m_width; }
     unsigned height() const { return m_height; }
-    size_t transparentPixel() const { return m_transparentPixel; }
-    void setTransparentPixel(size_t pixel) { m_transparentPixel = pixel; }
+    int transparentPixel() const { return m_transparentPixel; }
+    void setTransparentPixel(int pixel) { m_transparentPixel = pixel; }
     bool hasAlpha() const { return m_hasAlpha; }
     void setHasAlpha(bool alpha) { m_hasAlpha = alpha; }
     SkCodecAnimation::DisposalMethod getDisposalMethod() const { return m_disposalMethod; }
     void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; }
 
-    size_t getRequiredFrame() const {
+    int getRequiredFrame() const {
         SkASSERT(this->reachedStartOfData());
         return m_requiredFrame;
     }
-    void setRequiredFrame(size_t req) { m_requiredFrame = req; }
+    void setRequiredFrame(int req) { m_requiredFrame = req; }
 
     unsigned delayTime() const { return m_delayTime; }
     void setDelayTime(unsigned delay) { m_delayTime = delay; }
@@ -277,21 +277,21 @@ public:
     bool reachedStartOfData() const { return m_requiredFrame != kUninitialized; }
 
 private:
-    static constexpr size_t kUninitialized = static_cast<size_t>(-2);
+    static constexpr int kUninitialized = -2;
 
     int m_frameId;
     unsigned m_xOffset;
     unsigned m_yOffset; // With respect to "screen" origin.
     unsigned m_width;
     unsigned m_height;
-    size_t m_transparentPixel; // Index of transparent pixel. Value is kNotFound if there is no transparent pixel.
+    int m_transparentPixel; // Index of transparent pixel. Value is kNotFound if there is no transparent pixel.
     // Cached value, taking into account:
     // - m_transparentPixel
     // - frameRect
     // - previous required frame
     bool m_hasAlpha;
     SkCodecAnimation::DisposalMethod m_disposalMethod; // Restore to background, leave in place, etc.
-    size_t m_requiredFrame;
+    int m_requiredFrame;
     int m_dataSize;
 
     bool m_progressiveDisplay; // If true, do Haeberli interlace hack.
@@ -305,7 +305,7 @@ private:
 
     SkGIFColorMap m_localColorMap;
 
-    size_t m_currentLzwBlock;
+    int m_currentLzwBlock;
     bool m_isComplete;
     bool m_isHeaderDefined;
     bool m_isDataSizeDefined;
@@ -359,15 +359,15 @@ public:
     // Decode the frame indicated by frameIndex.
     // frameComplete will be set to true if the frame is completely decoded.
     // The method returns false if there is an error.
-    bool decode(size_t frameIndex, bool* frameComplete);
+    bool decode(int frameIndex, bool* frameComplete);
 
-    size_t imagesCount() const
+    int imagesCount() const
     {
         // Report the first frame immediately, so the parser can stop when it
         // sees the size on a SizeQuery.
         const size_t frames = m_frames.size();
         if (frames <= 1) {
-            return frames;
+            return static_cast<int>(frames);
         }
 
         // This avoids counting an empty frame when the file is truncated (or
@@ -375,7 +375,7 @@ public:
         // possibly SkGIFImageHeader) but before reading the color table. This
         // ensures that we do not count a frame before we know its required
         // frame.
-        return m_frames.back()->reachedStartOfData() ? frames : frames - 1;
+        return static_cast<int>(m_frames.back()->reachedStartOfData() ? frames : frames - 1);
     }
     int loopCount() const {
         if (cLoopCountNotSeen == m_loopCount) {
@@ -389,9 +389,10 @@ public:
         return m_globalColorMap;
     }
 
-    const SkGIFFrameContext* frameContext(size_t index) const
+    const SkGIFFrameContext* frameContext(int index) const
     {
-        return index < m_frames.size() ? m_frames[index].get() : 0;
+        return index >= 0 && index < static_cast<int>(m_frames.size())
+                ? m_frames[index].get() : 0;
     }
 
     void clearDecodeState() {
@@ -401,7 +402,7 @@ public:
     }
 
     // Return the color table for frame index (which may be the global color table).
-    sk_sp<SkColorTable> getColorTable(SkColorType dstColorType, size_t index);
+    sk_sp<SkColorTable> getColorTable(SkColorType dstColorType, int index);
 
     bool firstFrameHasAlpha() const { return m_firstFrameHasAlpha; }
 
@@ -418,7 +419,7 @@ private:
     void setAlphaAndRequiredFrame(SkGIFFrameContext*);
     // This method is sometimes called before creating a SkGIFFrameContext, so it cannot rely
     // on SkGIFFrameContext::localColorMap().
-    bool hasTransparentPixel(size_t frameIndex, bool hasLocalColorMap, size_t localMapColors);
+    bool hasTransparentPixel(int frameIndex, bool hasLocalColorMap, int localMapColors);
     bool currentFrameIsFirstFrame() const
     {
         return m_frames.empty() || (m_frames.size() == 1u && !m_frames[0]->isComplete());