aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/gif/SkGifImageReader.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/gif/SkGifImageReader.h')
-rw-r--r--third_party/gif/SkGifImageReader.h31
1 files changed, 23 insertions, 8 deletions
diff --git a/third_party/gif/SkGifImageReader.h b/third_party/gif/SkGifImageReader.h
index c51f4a8983..24c917af2a 100644
--- a/third_party/gif/SkGifImageReader.h
+++ b/third_party/gif/SkGifImageReader.h
@@ -202,7 +202,7 @@ public:
, m_height(0)
, m_transparentPixel(SkGIFColorMap::kNotFound)
, m_disposalMethod(SkCodecAnimation::Keep_DisposalMethod)
- , m_requiredFrame(SkCodec::kNone)
+ , m_requiredFrame(kUninitialized)
, m_dataSize(0)
, m_progressiveDisplay(false)
, m_interlaced(false)
@@ -242,8 +242,13 @@ public:
void setTransparentPixel(size_t pixel) { m_transparentPixel = pixel; }
SkCodecAnimation::DisposalMethod getDisposalMethod() const { return m_disposalMethod; }
void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; }
- size_t getRequiredFrame() const { return m_requiredFrame; }
+
+ size_t getRequiredFrame() const {
+ SkASSERT(this->reachedStartOfData());
+ return m_requiredFrame;
+ }
void setRequiredFrame(size_t req) { m_requiredFrame = req; }
+
unsigned delayTime() const { return m_delayTime; }
void setDelayTime(unsigned delay) { m_delayTime = delay; }
bool isComplete() const { return m_isComplete; }
@@ -266,7 +271,11 @@ public:
const SkGIFColorMap& localColorMap() const { return m_localColorMap; }
SkGIFColorMap& localColorMap() { return m_localColorMap; }
+ bool reachedStartOfData() const { return m_requiredFrame != kUninitialized; }
+
private:
+ static constexpr size_t kUninitialized = static_cast<size_t>(-2);
+
int m_frameId;
unsigned m_xOffset;
unsigned m_yOffset; // With respect to "screen" origin.
@@ -346,13 +355,19 @@ public:
size_t imagesCount() const
{
- if (m_frames.empty())
- return 0;
+ // 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;
+ }
- // This avoids counting an empty frame when the file is truncated right after
- // SkGIFControlExtension but before SkGIFImageHeader.
- // FIXME: This extra complexity is not necessary and we should just report m_frames.size().
- return m_frames.back()->isHeaderDefined() ? m_frames.size() : m_frames.size() - 1;
+ // This avoids counting an empty frame when the file is truncated (or
+ // simply not yet complete) after receiving SkGIFControlExtension (and
+ // 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;
}
int loopCount() const {
if (cLoopCountNotSeen == m_loopCount) {