OLD | NEW |
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* ***** BEGIN LICENSE BLOCK ***** | 2 /* ***** BEGIN LICENSE BLOCK ***** |
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 * | 4 * |
5 * The contents of this file are subject to the Mozilla Public License Version | 5 * The contents of this file are subject to the Mozilla Public License Version |
6 * 1.1 (the "License"); you may not use this file except in compliance with | 6 * 1.1 (the "License"); you may not use this file except in compliance with |
7 * the License. You may obtain a copy of the License at | 7 * the License. You may obtain a copy of the License at |
8 * http://www.mozilla.org/MPL/ | 8 * http://www.mozilla.org/MPL/ |
9 * | 9 * |
10 * Software distributed under the License is distributed on an "AS IS" basis, | 10 * Software distributed under the License is distributed on an "AS IS" basis, |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 , m_screenWidth(0) | 291 , m_screenWidth(0) |
292 , m_screenHeight(0) | 292 , m_screenHeight(0) |
293 , m_loopCount(cLoopCountNotSeen) | 293 , m_loopCount(cLoopCountNotSeen) |
294 , m_streamBuffer(stream) | 294 , m_streamBuffer(stream) |
295 , m_parseCompleted(false) | 295 , m_parseCompleted(false) |
296 , m_firstFrameHasAlpha(false) | 296 , m_firstFrameHasAlpha(false) |
297 , m_firstFrameSupportsIndex8(false) | 297 , m_firstFrameSupportsIndex8(false) |
298 { | 298 { |
299 } | 299 } |
300 | 300 |
301 static constexpr int cLoopCountNotSeen = -2; | |
302 | |
303 ~SkGifImageReader() | 301 ~SkGifImageReader() |
304 { | 302 { |
305 } | 303 } |
306 | 304 |
307 void setClient(SkGifCodec* client) { m_client = client; } | 305 void setClient(SkGifCodec* client) { m_client = client; } |
308 | 306 |
309 unsigned screenWidth() const { return m_screenWidth; } | 307 unsigned screenWidth() const { return m_screenWidth; } |
310 unsigned screenHeight() const { return m_screenHeight; } | 308 unsigned screenHeight() const { return m_screenHeight; } |
311 | 309 |
312 // Option to pass to parse(). All enums are negative, because a non-negative
value is used to | 310 // Option to pass to parse(). All enums are negative, because a non-negative
value is used to |
313 // indicate that the Reader should parse up to and including the frame indic
ated. | 311 // indicate that the Reader should parse up to and including the frame indic
ated. |
314 enum SkGIFParseQuery { | 312 enum SkGIFParseQuery { |
315 // Parse enough to determine the size. Note that this parses the first f
rame's header, | 313 // Parse enough to determine the size. Note that this parses the first f
rame's header, |
316 // since we may decide to expand based on the frame's dimensions. | 314 // since we may decide to expand based on the frame's dimensions. |
317 SkGIFSizeQuery = -1, | 315 SkGIFSizeQuery = -1, |
318 // Parse to the end, so we know about all frames. | 316 // Parse to the end, so we know about all frames. |
319 SkGIFFrameCountQuery = -2, | 317 SkGIFFrameCountQuery = -2, |
| 318 // Parse until we see the loop count. |
| 319 SkGIFLoopCountQuery = -3, |
320 }; | 320 }; |
321 | 321 |
322 // Parse incoming GIF data stream into internal data structures. | 322 // Parse incoming GIF data stream into internal data structures. |
323 // Non-negative values are used to indicate to parse through that frame. | 323 // Non-negative values are used to indicate to parse through that frame. |
324 // Return true if parsing has progressed or there is not enough data. | 324 // Return true if parsing has progressed or there is not enough data. |
325 // Return false if a fatal error is encountered. | 325 // Return false if a fatal error is encountered. |
326 bool parse(SkGIFParseQuery); | 326 bool parse(SkGIFParseQuery); |
327 | 327 |
328 // Decode the frame indicated by frameIndex. | 328 // Decode the frame indicated by frameIndex. |
329 // frameComplete will be set to true if the frame is completely decoded. | 329 // frameComplete will be set to true if the frame is completely decoded. |
330 // The method returns false if there is an error. | 330 // The method returns false if there is an error. |
331 bool decode(size_t frameIndex, bool* frameComplete); | 331 bool decode(size_t frameIndex, bool* frameComplete); |
332 | 332 |
333 size_t imagesCount() const | 333 size_t imagesCount() const |
334 { | 334 { |
335 if (m_frames.empty()) | 335 if (m_frames.empty()) |
336 return 0; | 336 return 0; |
337 | 337 |
338 // This avoids counting an empty frame when the file is truncated right
after | 338 // This avoids counting an empty frame when the file is truncated right
after |
339 // SkGIFControlExtension but before SkGIFImageHeader. | 339 // SkGIFControlExtension but before SkGIFImageHeader. |
340 // FIXME: This extra complexity is not necessary and we should just repo
rt m_frames.size(). | 340 // FIXME: This extra complexity is not necessary and we should just repo
rt m_frames.size(). |
341 return m_frames.back()->isHeaderDefined() ? m_frames.size() : m_frames.s
ize() - 1; | 341 return m_frames.back()->isHeaderDefined() ? m_frames.size() : m_frames.s
ize() - 1; |
342 } | 342 } |
343 int loopCount() const { return m_loopCount; } | 343 int loopCount() const { |
| 344 if (cLoopCountNotSeen == m_loopCount) { |
| 345 return 0; |
| 346 } |
| 347 return m_loopCount; |
| 348 } |
344 | 349 |
345 const SkGIFColorMap& globalColorMap() const | 350 const SkGIFColorMap& globalColorMap() const |
346 { | 351 { |
347 return m_globalColorMap; | 352 return m_globalColorMap; |
348 } | 353 } |
349 | 354 |
350 const SkGIFFrameContext* frameContext(size_t index) const | 355 const SkGIFFrameContext* frameContext(size_t index) const |
351 { | 356 { |
352 return index < m_frames.size() ? m_frames[index].get() : 0; | 357 return index < m_frames.size() ? m_frames[index].get() : 0; |
353 } | 358 } |
(...skipping 28 matching lines...) Expand all Loading... |
382 | 387 |
383 // Parsing state machine. | 388 // Parsing state machine. |
384 SkGIFState m_state; // Current decoder master state. | 389 SkGIFState m_state; // Current decoder master state. |
385 size_t m_bytesToConsume; // Number of bytes to consume for next stage of par
sing. | 390 size_t m_bytesToConsume; // Number of bytes to consume for next stage of par
sing. |
386 | 391 |
387 // Global (multi-image) state. | 392 // Global (multi-image) state. |
388 int m_version; // Either 89 for GIF89 or 87 for GIF87. | 393 int m_version; // Either 89 for GIF89 or 87 for GIF87. |
389 unsigned m_screenWidth; // Logical screen width & height. | 394 unsigned m_screenWidth; // Logical screen width & height. |
390 unsigned m_screenHeight; | 395 unsigned m_screenHeight; |
391 SkGIFColorMap m_globalColorMap; | 396 SkGIFColorMap m_globalColorMap; |
| 397 |
| 398 static constexpr int cLoopCountNotSeen = -2; |
392 int m_loopCount; // Netscape specific extension block to control the number
of animation loops a GIF renders. | 399 int m_loopCount; // Netscape specific extension block to control the number
of animation loops a GIF renders. |
393 | 400 |
394 std::vector<std::unique_ptr<SkGIFFrameContext>> m_frames; | 401 std::vector<std::unique_ptr<SkGIFFrameContext>> m_frames; |
395 | 402 |
396 SkStreamBuffer m_streamBuffer; | 403 SkStreamBuffer m_streamBuffer; |
397 bool m_parseCompleted; | 404 bool m_parseCompleted; |
398 | 405 |
399 // These values can be computed before we create a SkGIFFrameContext, so we | 406 // These values can be computed before we create a SkGIFFrameContext, so we |
400 // store them here instead of on m_frames[0]. | 407 // store them here instead of on m_frames[0]. |
401 bool m_firstFrameHasAlpha; | 408 bool m_firstFrameHasAlpha; |
402 bool m_firstFrameSupportsIndex8; | 409 bool m_firstFrameSupportsIndex8; |
403 }; | 410 }; |
404 | 411 |
405 #endif | 412 #endif |
OLD | NEW |