Add SkCodec::FrameInfo::fFullyReceived

This indicates whether the frame has been fully received, i.e. the
stream contains enough data to decode to the end of the frame.

A client may want to use this to know whether they should attempt to
decode this frame, if they do not want to decode partial frames.

Change-Id: I336c7031b0c0b8c1401ce040f5372aedc87fdc14
Reviewed-on: https://skia-review.googlesource.com/5703
Reviewed-by: Chris Blume <cblume@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index 314bec4..89fc57e 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -602,6 +602,14 @@
          *  Number of milliseconds to show this frame.
          */
         size_t fDuration;
+
+        /**
+         *  Whether the end marker for this frame is contained in the stream.
+         *
+         *  Note: this does not guarantee that an attempt to decode will be complete.
+         *  There could be an error in the stream.
+         */
+        bool fFullyReceived;
     };
 
     /**
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp
index 7b07f2a..9c7746d 100644
--- a/src/codec/SkGifCodec.cpp
+++ b/src/codec/SkGifCodec.cpp
@@ -140,6 +140,7 @@
         const SkGIFFrameContext* frameContext = fReader->frameContext(i);
         result[i].fDuration = frameContext->delayTime();
         result[i].fRequiredFrame = frameContext->getRequiredFrame();
+        result[i].fFullyReceived = frameContext->isComplete();
     }
     return result;
 }
diff --git a/tests/CodecPartialTest.cpp b/tests/CodecPartialTest.cpp
index e29037d..93e5d63 100644
--- a/tests/CodecPartialTest.cpp
+++ b/tests/CodecPartialTest.cpp
@@ -247,6 +247,9 @@
         const size_t secondHalf = fullFrameBytes - firstHalf;
 
         haltingStream->addNewData(firstHalf);
+        auto frameInfo = partialCodec->getFrameInfo();
+        REPORTER_ASSERT(r, frameInfo.size() == i + 1);
+        REPORTER_ASSERT(r, !frameInfo[i].fFullyReceived);
 
         SkBitmap frame;
         frame.allocPixels(info);
@@ -268,6 +271,10 @@
         result = partialCodec->incrementalDecode();
         REPORTER_ASSERT(r, SkCodec::kSuccess == result);
 
+        frameInfo = partialCodec->getFrameInfo();
+        REPORTER_ASSERT(r, frameInfo.size() == i + 1);
+        REPORTER_ASSERT(r, frameInfo[i].fFullyReceived);
+
         // allocPixels locked the pixels for frame, but frames[i] was copied
         // from another bitmap, and did not retain the locked status.
         SkAutoLockPixels alp(frames[i]);