Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkWuffsCodec.h"
      9 
     10 #include "../private/SkMalloc.h"
     11 #include "SkFrameHolder.h"
     12 #include "SkSampler.h"
     13 #include "SkSwizzler.h"
     14 #include "SkUtils.h"
     15 
     16 // Wuffs ships as a "single file C library" or "header file library" as per
     17 // https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
     18 //
     19 // As we have not #define'd WUFFS_IMPLEMENTATION, the #include here is
     20 // including a header file, even though that file name ends in ".c".
     21 #if defined(WUFFS_IMPLEMENTATION)
     22 #error "SkWuffsCodec should not #define WUFFS_IMPLEMENTATION"
     23 #endif
     24 #include "wuffs-v0.2.c"
     25 #if WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT < 1655
     26 #error "Wuffs version is too old. Upgrade to the latest version."
     27 #endif
     28 
     29 #define SK_WUFFS_CODEC_BUFFER_SIZE 4096
     30 
     31 static bool fill_buffer(wuffs_base__io_buffer* b, SkStream* s) {
     32     b->compact();
     33     size_t num_read = s->read(b->data.ptr + b->meta.wi, b->data.len - b->meta.wi);
     34     b->meta.wi += num_read;
     35     b->meta.closed = s->isAtEnd();
     36     return num_read > 0;
     37 }
     38 
     39 static bool seek_buffer(wuffs_base__io_buffer* b, SkStream* s, uint64_t pos) {
     40     // Try to re-position the io_buffer's meta.ri read-index first, which is
     41     // cheaper than seeking in the backing SkStream.
     42     if ((pos >= b->meta.pos) && (pos - b->meta.pos <= b->meta.wi)) {
     43         b->meta.ri = pos - b->meta.pos;
     44         return true;
     45     }
     46     // Seek in the backing SkStream.
     47     if ((pos > SIZE_MAX) || (!s->seek(pos))) {
     48         return false;
     49     }
     50     b->meta.wi = 0;
     51     b->meta.ri = 0;
     52     b->meta.pos = pos;
     53     b->meta.closed = false;
     54     return true;
     55 }
     56 
     57 static SkEncodedInfo::Alpha wuffs_blend_to_skia_alpha(wuffs_base__animation_blend w) {
     58     return (w == WUFFS_BASE__ANIMATION_BLEND__OPAQUE) ? SkEncodedInfo::kOpaque_Alpha
     59                                                       : SkEncodedInfo::kUnpremul_Alpha;
     60 }
     61 
     62 static SkCodecAnimation::Blend wuffs_blend_to_skia_blend(wuffs_base__animation_blend w) {
     63     return (w == WUFFS_BASE__ANIMATION_BLEND__SRC) ? SkCodecAnimation::Blend::kBG
     64                                                    : SkCodecAnimation::Blend::kPriorFrame;
     65 }
     66 
     67 static SkCodecAnimation::DisposalMethod wuffs_disposal_to_skia_disposal(
     68     wuffs_base__animation_disposal w) {
     69     switch (w) {
     70         case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND:
     71             return SkCodecAnimation::DisposalMethod::kRestoreBGColor;
     72         case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS:
     73             return SkCodecAnimation::DisposalMethod::kRestorePrevious;
     74         default:
     75             return SkCodecAnimation::DisposalMethod::kKeep;
     76     }
     77 }
     78 
     79 // -------------------------------- Class definitions
     80 
     81 class SkWuffsCodec;
     82 
     83 class SkWuffsFrame final : public SkFrame {
     84 public:
     85     SkWuffsFrame(wuffs_base__frame_config* fc);
     86 
     87     SkCodec::FrameInfo frameInfo(bool fullyReceived) const;
     88     uint64_t           ioPosition() const;
     89 
     90     // SkFrame overrides.
     91     SkEncodedInfo::Alpha onReportedAlpha() const override;
     92 
     93 private:
     94     uint64_t             fIOPosition;
     95     SkEncodedInfo::Alpha fReportedAlpha;
     96 
     97     typedef SkFrame INHERITED;
     98 };
     99 
    100 // SkWuffsFrameHolder is a trivial indirector that forwards its calls onto a
    101 // SkWuffsCodec. It is a separate class as SkWuffsCodec would otherwise
    102 // inherit from both SkCodec and SkFrameHolder, and Skia style discourages
    103 // multiple inheritance (e.g. with its "typedef Foo INHERITED" convention).
    104 class SkWuffsFrameHolder final : public SkFrameHolder {
    105 public:
    106     SkWuffsFrameHolder() : INHERITED() {}
    107 
    108     void init(SkWuffsCodec* codec, int width, int height);
    109 
    110     // SkFrameHolder overrides.
    111     const SkFrame* onGetFrame(int i) const override;
    112 
    113 private:
    114     const SkWuffsCodec* fCodec;
    115 
    116     typedef SkFrameHolder INHERITED;
    117 };
    118 
    119 // SkWuffsSpySampler is a placeholder SkSampler implementation. The Skia API
    120 // expects to manipulate the codec's sampler (i.e. call setSampleX and
    121 // setSampleY) in between the startIncrementalDecode (SID) and
    122 // incrementalDecode (ID) calls. But creating the SkSwizzler (the real sampler)
    123 // requires knowing the destination buffer's dimensions, i.e. the animation
    124 // frame's width and height. That width and height are decoded in ID, not SID.
    125 //
    126 // To break that circle, the SkWuffsSpySampler always exists, so its methods
    127 // can be called between SID and ID. It doesn't actually do any sampling, it
    128 // merely records the arguments given to setSampleX (explicitly) and setSampleY
    129 // (implicitly, via the superclass' implementation). Inside ID, those recorded
    130 // arguments are forwarded on to the SkSwizzler (the real sampler) when that
    131 // SkSwizzler is created, after the frame width and height are known.
    132 //
    133 // Roughly speaking, the SkWuffsSpySampler is an eager proxy for the lazily
    134 // constructed real sampler. But that laziness is out of necessity.
    135 //
    136 // The "Spy" name is because it records its arguments. See
    137 // https://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
    138 class SkWuffsSpySampler final : public SkSampler {
    139 public:
    140     SkWuffsSpySampler(int imageWidth)
    141         : INHERITED(), fFillWidth(0), fImageWidth(imageWidth), fSampleX(1) {}
    142 
    143     void reset();
    144     int  sampleX() const;
    145 
    146     int fFillWidth;
    147 
    148 private:
    149     // SkSampler overrides.
    150     int fillWidth() const override;
    151     int onSetSampleX(int sampleX) override;
    152 
    153     const int fImageWidth;
    154 
    155     int fSampleX;
    156 
    157     typedef SkSampler INHERITED;
    158 };
    159 
    160 class SkWuffsCodec final : public SkCodec {
    161 public:
    162     SkWuffsCodec(SkEncodedInfo&&                                         encodedInfo,
    163                  std::unique_ptr<SkStream>                               stream,
    164                  std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> dec,
    165                  std::unique_ptr<uint8_t, decltype(&sk_free)>            pixbuf_ptr,
    166                  std::unique_ptr<uint8_t, decltype(&sk_free)>            workbuf_ptr,
    167                  size_t                                                  workbuf_len,
    168                  wuffs_base__image_config                                imgcfg,
    169                  wuffs_base__pixel_buffer                                pixbuf,
    170                  wuffs_base__io_buffer                                   iobuf);
    171 
    172     const SkWuffsFrame* frame(int i) const;
    173 
    174 private:
    175     // SkCodec overrides.
    176     SkEncodedImageFormat onGetEncodedFormat() const override;
    177     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, int*) override;
    178     const SkFrameHolder* getFrameHolder() const override;
    179     Result               onStartIncrementalDecode(const SkImageInfo&      dstInfo,
    180                                                   void*                   dst,
    181                                                   size_t                  rowBytes,
    182                                                   const SkCodec::Options& options) override;
    183     Result               onIncrementalDecode(int* rowsDecoded) override;
    184     int                  onGetFrameCount() override;
    185     bool                 onGetFrameInfo(int, FrameInfo*) const override;
    186     int                  onGetRepetitionCount() override;
    187     SkSampler*           getSampler(bool createIfNecessary) override;
    188     bool                 conversionSupported(const SkImageInfo& dst, bool, bool) override;
    189 
    190     void   readFrames();
    191     Result seekFrame(int frameIndex);
    192 
    193     Result      resetDecoder();
    194     const char* decodeFrameConfig();
    195     const char* decodeFrame();
    196     void        updateNumFullyReceivedFrames();
    197 
    198     SkWuffsSpySampler                                       fSpySampler;
    199     SkWuffsFrameHolder                                      fFrameHolder;
    200     std::unique_ptr<SkStream>                               fStream;
    201     std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> fDecoder;
    202     std::unique_ptr<uint8_t, decltype(&sk_free)>            fPixbufPtr;
    203     std::unique_ptr<uint8_t, decltype(&sk_free)>            fWorkbufPtr;
    204     size_t                                                  fWorkbufLen;
    205 
    206     const uint64_t           fFirstFrameIOPosition;
    207     wuffs_base__frame_config fFrameConfig;
    208     wuffs_base__pixel_buffer fPixelBuffer;
    209     wuffs_base__io_buffer    fIOBuffer;
    210 
    211     // Incremental decoding state.
    212     uint8_t* fIncrDecDst;
    213     size_t   fIncrDecRowBytes;
    214 
    215     std::unique_ptr<SkSwizzler> fSwizzler;
    216     int                         fScaledHeight;
    217 
    218     uint64_t                  fNumFullyReceivedFrames;
    219     std::vector<SkWuffsFrame> fFrames;
    220     bool                      fFramesComplete;
    221 
    222     // If calling an fDecoder method returns an incomplete status, then
    223     // fDecoder is suspended in a coroutine (i.e. waiting on I/O or halted on a
    224     // non-recoverable error). To keep its internal proof-of-safety invariants
    225     // consistent, there's only two things you can safely do with a suspended
    226     // Wuffs object: resume the coroutine, or reset all state (memset to zero
    227     // and start again).
    228     //
    229     // If fDecoderIsSuspended, and we aren't sure that we're going to resume
    230     // the coroutine, then we will need to call this->resetDecoder before
    231     // calling other fDecoder methods.
    232     bool fDecoderIsSuspended;
    233 
    234     uint8_t fBuffer[SK_WUFFS_CODEC_BUFFER_SIZE];
    235 
    236     typedef SkCodec INHERITED;
    237 };
    238 
    239 // -------------------------------- SkWuffsFrame implementation
    240 
    241 SkWuffsFrame::SkWuffsFrame(wuffs_base__frame_config* fc)
    242     : INHERITED(fc->index()),
    243       fIOPosition(fc->io_position()),
    244       fReportedAlpha(wuffs_blend_to_skia_alpha(fc->blend())) {
    245     wuffs_base__rect_ie_u32 r = fc->bounds();
    246     this->setXYWH(r.min_incl_x, r.min_incl_y, r.width(), r.height());
    247     this->setDisposalMethod(wuffs_disposal_to_skia_disposal(fc->disposal()));
    248     this->setDuration(fc->duration() / WUFFS_BASE__FLICKS_PER_MILLISECOND);
    249     this->setBlend(wuffs_blend_to_skia_blend(fc->blend()));
    250 }
    251 
    252 SkCodec::FrameInfo SkWuffsFrame::frameInfo(bool fullyReceived) const {
    253     return ((SkCodec::FrameInfo){
    254         .fRequiredFrame = getRequiredFrame(),
    255         .fDuration = getDuration(),
    256         .fFullyReceived = fullyReceived,
    257         .fAlphaType = hasAlpha() ? kUnpremul_SkAlphaType : kOpaque_SkAlphaType,
    258         .fDisposalMethod = getDisposalMethod(),
    259     });
    260 }
    261 
    262 uint64_t SkWuffsFrame::ioPosition() const {
    263     return fIOPosition;
    264 }
    265 
    266 SkEncodedInfo::Alpha SkWuffsFrame::onReportedAlpha() const {
    267     return fReportedAlpha;
    268 }
    269 
    270 // -------------------------------- SkWuffsFrameHolder implementation
    271 
    272 void SkWuffsFrameHolder::init(SkWuffsCodec* codec, int width, int height) {
    273     fCodec = codec;
    274     // Initialize SkFrameHolder's (the superclass) fields.
    275     fScreenWidth = width;
    276     fScreenHeight = height;
    277 }
    278 
    279 const SkFrame* SkWuffsFrameHolder::onGetFrame(int i) const {
    280     return fCodec->frame(i);
    281 };
    282 
    283 // -------------------------------- SkWuffsSpySampler implementation
    284 
    285 void SkWuffsSpySampler::reset() {
    286     fFillWidth = 0;
    287     fSampleX = 1;
    288     this->setSampleY(1);
    289 }
    290 
    291 int SkWuffsSpySampler::sampleX() const {
    292     return fSampleX;
    293 }
    294 
    295 int SkWuffsSpySampler::fillWidth() const {
    296     return fFillWidth;
    297 }
    298 
    299 int SkWuffsSpySampler::onSetSampleX(int sampleX) {
    300     fSampleX = sampleX;
    301     return get_scaled_dimension(fImageWidth, sampleX);
    302 }
    303 
    304 // -------------------------------- SkWuffsCodec implementation
    305 
    306 SkWuffsCodec::SkWuffsCodec(SkEncodedInfo&&                                         encodedInfo,
    307                            std::unique_ptr<SkStream>                               stream,
    308                            std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> dec,
    309                            std::unique_ptr<uint8_t, decltype(&sk_free)>            pixbuf_ptr,
    310                            std::unique_ptr<uint8_t, decltype(&sk_free)>            workbuf_ptr,
    311                            size_t                                                  workbuf_len,
    312                            wuffs_base__image_config                                imgcfg,
    313                            wuffs_base__pixel_buffer                                pixbuf,
    314                            wuffs_base__io_buffer                                   iobuf)
    315     : INHERITED(std::move(encodedInfo),
    316                 skcms_PixelFormat_RGBA_8888,
    317                 // Pass a nullptr SkStream to the SkCodec constructor. We
    318                 // manage the stream ourselves, as the default SkCodec behavior
    319                 // is too trigger-happy on rewinding the stream.
    320                 nullptr),
    321       fSpySampler(imgcfg.pixcfg.width()),
    322       fFrameHolder(),
    323       fStream(std::move(stream)),
    324       fDecoder(std::move(dec)),
    325       fPixbufPtr(std::move(pixbuf_ptr)),
    326       fWorkbufPtr(std::move(workbuf_ptr)),
    327       fWorkbufLen(workbuf_len),
    328       fFirstFrameIOPosition(imgcfg.first_frame_io_position()),
    329       fFrameConfig(wuffs_base__null_frame_config()),
    330       fPixelBuffer(pixbuf),
    331       fIOBuffer(wuffs_base__null_io_buffer()),
    332       fIncrDecDst(nullptr),
    333       fIncrDecRowBytes(0),
    334       fSwizzler(nullptr),
    335       fScaledHeight(0),
    336       fNumFullyReceivedFrames(0),
    337       fFramesComplete(false),
    338       fDecoderIsSuspended(false) {
    339     fFrameHolder.init(this, imgcfg.pixcfg.width(), imgcfg.pixcfg.height());
    340 
    341     // Initialize fIOBuffer's fields, copying any outstanding data from iobuf to
    342     // fIOBuffer, as iobuf's backing array may not be valid for the lifetime of
    343     // this SkWuffsCodec object, but fIOBuffer's backing array (fBuffer) is.
    344     SkASSERT(iobuf.data.len == SK_WUFFS_CODEC_BUFFER_SIZE);
    345     memmove(fBuffer, iobuf.data.ptr, iobuf.meta.wi);
    346     fIOBuffer.data = wuffs_base__make_slice_u8(fBuffer, SK_WUFFS_CODEC_BUFFER_SIZE);
    347     fIOBuffer.meta = iobuf.meta;
    348 }
    349 
    350 const SkWuffsFrame* SkWuffsCodec::frame(int i) const {
    351     if ((0 <= i) && (static_cast<size_t>(i) < fFrames.size())) {
    352         return &fFrames[i];
    353     }
    354     return nullptr;
    355 }
    356 
    357 SkEncodedImageFormat SkWuffsCodec::onGetEncodedFormat() const {
    358     return SkEncodedImageFormat::kGIF;
    359 }
    360 
    361 SkCodec::Result SkWuffsCodec::onGetPixels(const SkImageInfo& dstInfo,
    362                                           void*              dst,
    363                                           size_t             rowBytes,
    364                                           const Options&     options,
    365                                           int*               rowsDecoded) {
    366     SkCodec::Result result = this->onStartIncrementalDecode(dstInfo, dst, rowBytes, options);
    367     if (result != kSuccess) {
    368         return result;
    369     }
    370     return this->onIncrementalDecode(rowsDecoded);
    371 }
    372 
    373 const SkFrameHolder* SkWuffsCodec::getFrameHolder() const {
    374     return &fFrameHolder;
    375 }
    376 
    377 SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo&      dstInfo,
    378                                                        void*                   dst,
    379                                                        size_t                  rowBytes,
    380                                                        const SkCodec::Options& options) {
    381     if (options.fSubset) {
    382         return SkCodec::kUnimplemented;
    383     }
    384     SkCodec::Result result = this->seekFrame(options.fFrameIndex);
    385     if (result != SkCodec::kSuccess) {
    386         return result;
    387     }
    388 
    389     fSpySampler.reset();
    390     fSwizzler = nullptr;
    391     fScaledHeight = 0;
    392 
    393     const char* status = this->decodeFrameConfig();
    394     if (status == wuffs_base__suspension__short_read) {
    395         return SkCodec::kIncompleteInput;
    396     } else if (status != nullptr) {
    397         SkCodecPrintf("decodeFrameConfig: %s", status);
    398         return SkCodec::kErrorInInput;
    399     }
    400 
    401     uint32_t src_bits_per_pixel =
    402         wuffs_base__pixel_format__bits_per_pixel(fPixelBuffer.pixcfg.pixel_format());
    403     if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
    404         return SkCodec::kInternalError;
    405     }
    406     size_t src_bytes_per_pixel = src_bits_per_pixel / 8;
    407 
    408     // Zero-initialize Wuffs' buffer covering the frame rect.
    409     wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
    410     wuffs_base__table_u8    pixels = fPixelBuffer.plane(0);
    411     for (uint32_t y = frame_rect.min_incl_y; y < frame_rect.max_excl_y; y++) {
    412         sk_bzero(pixels.ptr + (y * pixels.stride) + (frame_rect.min_incl_x * src_bytes_per_pixel),
    413                  frame_rect.width() * src_bytes_per_pixel);
    414     }
    415 
    416     fIncrDecDst = static_cast<uint8_t*>(dst);
    417     fIncrDecRowBytes = rowBytes;
    418     return SkCodec::kSuccess;
    419 }
    420 
    421 static bool independent_frame(SkCodec* codec, int frameIndex) {
    422     if (frameIndex == 0) {
    423         return true;
    424     }
    425 
    426     SkCodec::FrameInfo frameInfo;
    427     SkAssertResult(codec->getFrameInfo(frameIndex, &frameInfo));
    428     return frameInfo.fRequiredFrame == SkCodec::kNoFrame;
    429 }
    430 
    431 static void blend(uint32_t* dst, const uint32_t* src, int width) {
    432     while (width --> 0) {
    433         if (*src != 0) {
    434             *dst = *src;
    435         }
    436         src++;
    437         dst++;
    438     }
    439 }
    440 
    441 SkCodec::Result SkWuffsCodec::onIncrementalDecode(int* rowsDecoded) {
    442     if (!fIncrDecDst) {
    443         return SkCodec::kInternalError;
    444     }
    445 
    446     SkCodec::Result result = SkCodec::kSuccess;
    447     const char*     status = this->decodeFrame();
    448     const bool      independent = independent_frame(this, options().fFrameIndex);
    449     if (status != nullptr) {
    450         if (status == wuffs_base__suspension__short_read) {
    451             result = SkCodec::kIncompleteInput;
    452         } else {
    453             SkCodecPrintf("decodeFrame: %s", status);
    454             result = SkCodec::kErrorInInput;
    455         }
    456 
    457         if (!independent) {
    458             // For a dependent frame, we cannot blend the partial result, since
    459             // that will overwrite the contribution from prior frames.
    460             return result;
    461         }
    462     }
    463 
    464     uint32_t src_bits_per_pixel =
    465         wuffs_base__pixel_format__bits_per_pixel(fPixelBuffer.pixcfg.pixel_format());
    466     if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
    467         return SkCodec::kInternalError;
    468     }
    469     size_t src_bytes_per_pixel = src_bits_per_pixel / 8;
    470 
    471     wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
    472     if (!fSwizzler) {
    473         auto bounds = SkIRect::MakeLTRB(frame_rect.min_incl_x, frame_rect.min_incl_y,
    474                                         frame_rect.max_excl_x, frame_rect.max_excl_y);
    475         fSwizzler =
    476             SkSwizzler::Make(this->getEncodedInfo(), nullptr, dstInfo(), this->options(), &bounds);
    477         fSwizzler->setSampleX(fSpySampler.sampleX());
    478         fSwizzler->setSampleY(fSpySampler.sampleY());
    479         fScaledHeight = get_scaled_dimension(dstInfo().height(), fSpySampler.sampleY());
    480 
    481         if (frame_rect.width() > (SIZE_MAX / src_bytes_per_pixel)) {
    482             return SkCodec::kInternalError;
    483         }
    484 
    485         // If the frame rect does not fill the output, ensure that those pixels are not
    486         // left uninitialized.
    487         if (independent && (bounds != this->bounds() || result != kSuccess)) {
    488             auto fillInfo = dstInfo().makeWH(fSwizzler->fillWidth(), fScaledHeight);
    489             SkSampler::Fill(fillInfo, fIncrDecDst, fIncrDecRowBytes, options().fZeroInitialized);
    490         }
    491     }
    492     if (fScaledHeight == 0) {
    493         return SkCodec::kInternalError;
    494     }
    495 
    496     // The semantics of *rowsDecoded is: say you have a 10 pixel high image
    497     // (both the frame and the image). If you only decoded the first 3 rows,
    498     // set this to 3, and then SkCodec (or the caller of incrementalDecode)
    499     // would zero-initialize the remaining 7 (unless the memory was already
    500     // zero-initialized).
    501     //
    502     // Now let's say that the image is still 10 pixels high, but the frame is
    503     // from row 5 to 9. If you only decoded 3 rows, but you initialized the
    504     // first 5, you could return 8, and the caller would zero-initialize the
    505     // final 2. For GIF (where a frame can be smaller than the image and can be
    506     // interlaced), we just zero-initialize all 10 rows ahead of time and
    507     // return the height of the image, so the caller knows it doesn't need to
    508     // do anything.
    509     //
    510     // Similarly, if the output is scaled, we zero-initialized all
    511     // |fScaledHeight| rows (the scaled image height), so we inform the caller
    512     // that it doesn't need to do anything.
    513     if (rowsDecoded) {
    514         *rowsDecoded = fScaledHeight;
    515     }
    516 
    517     // If the frame's dirty rect is empty, no need to swizzle.
    518     wuffs_base__rect_ie_u32 dirty_rect = fDecoder->frame_dirty_rect();
    519     if (!dirty_rect.is_empty()) {
    520         std::unique_ptr<uint8_t[]> tmpBuffer;
    521         if (!independent) {
    522             tmpBuffer.reset(new uint8_t[dstInfo().minRowBytes()]);
    523         }
    524         wuffs_base__table_u8 pixels = fPixelBuffer.plane(0);
    525         const int            sampleY = fSwizzler->sampleY();
    526         for (uint32_t y = dirty_rect.min_incl_y; y < dirty_rect.max_excl_y; y++) {
    527             int dstY = y;
    528             if (sampleY != 1) {
    529                 if (!fSwizzler->rowNeeded(y)) {
    530                     continue;
    531                 }
    532                 dstY /= sampleY;
    533                 if (dstY >= fScaledHeight) {
    534                     break;
    535                 }
    536             }
    537 
    538             // We don't adjust d by (frame_rect.min_incl_x * dst_bpp) as we
    539             // have already accounted for that in swizzleRect, above.
    540             uint8_t* d = fIncrDecDst + (dstY * fIncrDecRowBytes);
    541 
    542             // The Wuffs model is that the dst buffer is the image, not the frame.
    543             // The expectation is that you allocate the buffer once, but re-use it
    544             // for the N frames, regardless of each frame's top-left co-ordinate.
    545             //
    546             // To get from the start (in the X-direction) of the image to the start
    547             // of the frame, we adjust s by (frame_rect.min_incl_x *
    548             // src_bytes_per_pixel).
    549             //
    550             // We adjust (in the X-direction) by the frame rect, not the dirty
    551             // rect, because the swizzler (which operates on rows) was
    552             // configured with the frame rect's X range.
    553             uint8_t* s =
    554                 pixels.ptr + (y * pixels.stride) + (frame_rect.min_incl_x * src_bytes_per_pixel);
    555             if (independent) {
    556                 fSwizzler->swizzle(d, s);
    557             } else {
    558                 SkASSERT(tmpBuffer.get());
    559                 fSwizzler->swizzle(tmpBuffer.get(), s);
    560                 d = SkTAddOffset<uint8_t>(d, fSwizzler->swizzleOffsetBytes());
    561                 const auto* swizzled = SkTAddOffset<uint32_t>(tmpBuffer.get(),
    562                                                               fSwizzler->swizzleOffsetBytes());
    563                 blend(reinterpret_cast<uint32_t*>(d), swizzled, fSwizzler->swizzleWidth());
    564             }
    565         }
    566     }
    567 
    568     if (result == SkCodec::kSuccess) {
    569         fSpySampler.reset();
    570         fIncrDecDst = nullptr;
    571         fIncrDecRowBytes = 0;
    572         fSwizzler = nullptr;
    573     } else {
    574         // Make fSpySampler return whatever fSwizzler would have for fillWidth.
    575         fSpySampler.fFillWidth = fSwizzler->fillWidth();
    576     }
    577     return result;
    578 }
    579 
    580 int SkWuffsCodec::onGetFrameCount() {
    581     if (!fFramesComplete) {
    582         this->readFrames();
    583         this->updateNumFullyReceivedFrames();
    584     }
    585     return fFrames.size();
    586 }
    587 
    588 bool SkWuffsCodec::onGetFrameInfo(int i, SkCodec::FrameInfo* frameInfo) const {
    589     const SkWuffsFrame* f = this->frame(i);
    590     if (!f) {
    591         return false;
    592     }
    593     if (frameInfo) {
    594         *frameInfo = f->frameInfo(static_cast<uint64_t>(i) < this->fNumFullyReceivedFrames);
    595     }
    596     return true;
    597 }
    598 
    599 int SkWuffsCodec::onGetRepetitionCount() {
    600     // Convert from Wuffs's loop count to Skia's repeat count. Wuffs' uint32_t
    601     // number is how many times to play the loop. Skia's int number is how many
    602     // times to play the loop *after the first play*. Wuffs and Skia use 0 and
    603     // kRepetitionCountInfinite respectively to mean loop forever.
    604     uint32_t n = fDecoder->num_animation_loops();
    605     if (n == 0) {
    606         return SkCodec::kRepetitionCountInfinite;
    607     }
    608     n--;
    609     return n < INT_MAX ? n : INT_MAX;
    610 }
    611 
    612 SkSampler* SkWuffsCodec::getSampler(bool createIfNecessary) {
    613     // fIncrDst being non-nullptr means that we are between an
    614     // onStartIncrementalDecode call and the matching final (successful)
    615     // onIncrementalDecode call.
    616     if (createIfNecessary || fIncrDecDst) {
    617         return &fSpySampler;
    618     }
    619     return nullptr;
    620 }
    621 
    622 bool SkWuffsCodec::conversionSupported(const SkImageInfo& dst, bool srcIsOpaque, bool needsColorXform) {
    623     if (!this->INHERITED::conversionSupported(dst, srcIsOpaque, needsColorXform)) {
    624         return false;
    625     }
    626 
    627     switch (dst.colorType()) {
    628         case kRGBA_8888_SkColorType:
    629         case kBGRA_8888_SkColorType:
    630             return true;
    631         default:
    632             // FIXME: Add skcms to support F16
    633             // FIXME: Add support for 565 on the first frame
    634             return false;
    635     }
    636 }
    637 
    638 void SkWuffsCodec::readFrames() {
    639     size_t n = fFrames.size();
    640     int    i = n ? n - 1 : 0;
    641     if (this->seekFrame(i) != SkCodec::kSuccess) {
    642         return;
    643     }
    644 
    645     // Iterate through the frames, converting from Wuffs'
    646     // wuffs_base__frame_config type to Skia's SkWuffsFrame type.
    647     for (; i < INT_MAX; i++) {
    648         const char* status = this->decodeFrameConfig();
    649         if (status == nullptr) {
    650             // No-op.
    651         } else if (status == wuffs_base__warning__end_of_data) {
    652             break;
    653         } else {
    654             return;
    655         }
    656 
    657         if (static_cast<size_t>(i) < fFrames.size()) {
    658             continue;
    659         }
    660         fFrames.emplace_back(&fFrameConfig);
    661         SkWuffsFrame* f = &fFrames[fFrames.size() - 1];
    662         fFrameHolder.setAlphaAndRequiredFrame(f);
    663     }
    664 
    665     fFramesComplete = true;
    666 }
    667 
    668 SkCodec::Result SkWuffsCodec::seekFrame(int frameIndex) {
    669     if (fDecoderIsSuspended) {
    670         SkCodec::Result res = this->resetDecoder();
    671         if (res != SkCodec::kSuccess) {
    672             return res;
    673         }
    674     }
    675 
    676     uint64_t pos = 0;
    677     if (frameIndex < 0) {
    678         return SkCodec::kInternalError;
    679     } else if (frameIndex == 0) {
    680         pos = fFirstFrameIOPosition;
    681     } else if (static_cast<size_t>(frameIndex) < fFrames.size()) {
    682         pos = fFrames[frameIndex].ioPosition();
    683     } else {
    684         return SkCodec::kInternalError;
    685     }
    686 
    687     if (!seek_buffer(&fIOBuffer, fStream.get(), pos)) {
    688         return SkCodec::kInternalError;
    689     }
    690     const char* status = fDecoder->restart_frame(frameIndex, fIOBuffer.reader_io_position());
    691     if (status != nullptr) {
    692         return SkCodec::kInternalError;
    693     }
    694     return SkCodec::kSuccess;
    695 }
    696 
    697 // An overview of the Wuffs decoding API:
    698 //
    699 // An animated image (such as GIF) has an image header and then N frames. The
    700 // image header gives e.g. the overall image's width and height. Each frame
    701 // consists of a frame header (e.g. frame rectangle bounds, display duration)
    702 // and a payload (the pixels).
    703 //
    704 // In Wuffs terminology, there is one image config and then N pairs of
    705 // (frame_config, frame). To decode everything (without knowing N in advance)
    706 // sequentially:
    707 //  - call wuffs_gif__decoder::decode_image_config
    708 //  - while (true) {
    709 //  -   call wuffs_gif__decoder::decode_frame_config
    710 //  -   if that returned wuffs_base__warning__end_of_data, break
    711 //  -   call wuffs_gif__decoder::decode_frame
    712 //  - }
    713 //
    714 // The first argument to each decode_foo method is the destination struct to
    715 // store the decoded information.
    716 //
    717 // For random (instead of sequential) access to an image's frames, call
    718 // wuffs_gif__decoder::restart_frame to prepare to decode the i'th frame.
    719 // Essentially, it restores the state to be at the top of the while loop above.
    720 // The wuffs_base__io_buffer's reader position will also need to be set at the
    721 // right point in the source data stream. The position for the i'th frame is
    722 // calculated by the i'th decode_frame_config call. You can only call
    723 // restart_frame after decode_image_config is called, explicitly or implicitly
    724 // (see below), as decoding a single frame might require for-all-frames
    725 // information like the overall image dimensions and the global palette.
    726 //
    727 // All of those decode_xxx calls are optional. For example, if
    728 // decode_image_config is not called, then the first decode_frame_config call
    729 // will implicitly parse and verify the image header, before parsing the first
    730 // frame's header. Similarly, you can call only decode_frame N times, without
    731 // calling decode_image_config or decode_frame_config, if you already know
    732 // metadata like N and each frame's rectangle bounds by some other means (e.g.
    733 // this is a first party, statically known image).
    734 //
    735 // Specifically, starting with an unknown (but re-windable) GIF image, if you
    736 // want to just find N (i.e. count the number of frames), you can loop calling
    737 // only the decode_frame_config method and avoid calling the more expensive
    738 // decode_frame method. In terms of the underlying GIF image format, this will
    739 // skip over the LZW-encoded pixel data, avoiding the costly LZW decompression.
    740 //
    741 // Those decode_xxx methods are also suspendible. They will return early (with
    742 // a status code that is_suspendible and therefore isn't is_complete) if there
    743 // isn't enough source data to complete the operation: an incremental decode.
    744 // Calling decode_xxx again with additional source data will resume the
    745 // previous operation, instead of starting a new operation. Calling decode_yyy
    746 // whilst decode_xxx is suspended will result in an error.
    747 //
    748 // Once an error is encountered, whether from invalid source data or from a
    749 // programming error such as calling decode_yyy while suspended in decode_xxx,
    750 // all subsequent calls will be no-ops that return an error. To reset the
    751 // decoder into something that does productive work, memset the entire struct
    752 // to zero, check the Wuffs version and then, in order to be able to call
    753 // restart_frame, call decode_image_config. The io_buffer and its associated
    754 // stream will also need to be rewound.
    755 
    756 static SkCodec::Result reset_and_decode_image_config(wuffs_gif__decoder*       decoder,
    757                                                      wuffs_base__image_config* imgcfg,
    758                                                      wuffs_base__io_buffer*    b,
    759                                                      SkStream*                 s) {
    760     // Calling decoder->initialize will memset it to zero.
    761     const char* status = decoder->initialize(sizeof__wuffs_gif__decoder(), WUFFS_VERSION, 0);
    762     if (status != nullptr) {
    763         SkCodecPrintf("initialize: %s", status);
    764         return SkCodec::kInternalError;
    765     }
    766     while (true) {
    767         status = decoder->decode_image_config(imgcfg, b->reader());
    768         if (status == nullptr) {
    769             break;
    770         } else if (status != wuffs_base__suspension__short_read) {
    771             SkCodecPrintf("decode_image_config: %s", status);
    772             return SkCodec::kErrorInInput;
    773         } else if (!fill_buffer(b, s)) {
    774             return SkCodec::kIncompleteInput;
    775         }
    776     }
    777 
    778     // A GIF image's natural color model is indexed color: 1 byte per pixel,
    779     // indexing a 256-element palette.
    780     //
    781     // For Skia, we override that to decode to 4 bytes per pixel, BGRA or RGBA.
    782     wuffs_base__pixel_format pixfmt = 0;
    783     switch (kN32_SkColorType) {
    784         case kBGRA_8888_SkColorType:
    785             pixfmt = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
    786             break;
    787         case kRGBA_8888_SkColorType:
    788             pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
    789             break;
    790         default:
    791             return SkCodec::kInternalError;
    792     }
    793     imgcfg->pixcfg.set(pixfmt, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, imgcfg->pixcfg.width(),
    794                        imgcfg->pixcfg.height());
    795 
    796     return SkCodec::kSuccess;
    797 }
    798 
    799 SkCodec::Result SkWuffsCodec::resetDecoder() {
    800     if (!fStream->rewind()) {
    801         return SkCodec::kInternalError;
    802     }
    803     fIOBuffer.meta = wuffs_base__null_io_buffer_meta();
    804 
    805     SkCodec::Result result =
    806         reset_and_decode_image_config(fDecoder.get(), nullptr, &fIOBuffer, fStream.get());
    807     if (result == SkCodec::kIncompleteInput) {
    808         return SkCodec::kInternalError;
    809     } else if (result != SkCodec::kSuccess) {
    810         return result;
    811     }
    812 
    813     fDecoderIsSuspended = false;
    814     return SkCodec::kSuccess;
    815 }
    816 
    817 const char* SkWuffsCodec::decodeFrameConfig() {
    818     while (true) {
    819         const char* status = fDecoder->decode_frame_config(&fFrameConfig, fIOBuffer.reader());
    820         if ((status == wuffs_base__suspension__short_read) &&
    821             fill_buffer(&fIOBuffer, fStream.get())) {
    822             continue;
    823         }
    824         fDecoderIsSuspended = !wuffs_base__status__is_complete(status);
    825         this->updateNumFullyReceivedFrames();
    826         return status;
    827     }
    828 }
    829 
    830 const char* SkWuffsCodec::decodeFrame() {
    831     while (true) {
    832         const char* status =
    833             fDecoder->decode_frame(&fPixelBuffer, fIOBuffer.reader(),
    834                                    wuffs_base__make_slice_u8(fWorkbufPtr.get(), fWorkbufLen), NULL);
    835         if ((status == wuffs_base__suspension__short_read) &&
    836             fill_buffer(&fIOBuffer, fStream.get())) {
    837             continue;
    838         }
    839         fDecoderIsSuspended = !wuffs_base__status__is_complete(status);
    840         this->updateNumFullyReceivedFrames();
    841         return status;
    842     }
    843 }
    844 
    845 void SkWuffsCodec::updateNumFullyReceivedFrames() {
    846     // num_decoded_frames's return value, n, can change over time, both up and
    847     // down, as we seek back and forth in the underlying stream.
    848     // fNumFullyReceivedFrames is the highest n we've seen.
    849     uint64_t n = fDecoder->num_decoded_frames();
    850     if (fNumFullyReceivedFrames < n) {
    851         fNumFullyReceivedFrames = n;
    852     }
    853 }
    854 
    855 // -------------------------------- SkWuffsCodec.h functions
    856 
    857 bool SkWuffsCodec_IsFormat(const void* buf, size_t bytesRead) {
    858     constexpr const char* gif_ptr = "GIF8";
    859     constexpr size_t      gif_len = 4;
    860     return (bytesRead >= gif_len) && (memcmp(buf, gif_ptr, gif_len) == 0);
    861 }
    862 
    863 std::unique_ptr<SkCodec> SkWuffsCodec_MakeFromStream(std::unique_ptr<SkStream> stream,
    864                                                      SkCodec::Result*          result) {
    865     uint8_t               buffer[SK_WUFFS_CODEC_BUFFER_SIZE];
    866     wuffs_base__io_buffer iobuf =
    867         wuffs_base__make_io_buffer(wuffs_base__make_slice_u8(buffer, SK_WUFFS_CODEC_BUFFER_SIZE),
    868                                    wuffs_base__null_io_buffer_meta());
    869     wuffs_base__image_config imgcfg = wuffs_base__null_image_config();
    870 
    871     // Wuffs is primarily a C library, not a C++ one. Furthermore, outside of
    872     // the wuffs_base__etc types, the sizeof a file format specific type like
    873     // GIF's wuffs_gif__decoder can vary between Wuffs versions. If p is of
    874     // type wuffs_gif__decoder*, then the supported API treats p as a pointer
    875     // to an opaque type: a private implementation detail. The API is always
    876     // "set_foo(p, etc)" and not "p->foo = etc".
    877     //
    878     // See https://en.wikipedia.org/wiki/Opaque_pointer#C
    879     //
    880     // Thus, we don't use C++'s new operator (which requires knowing the sizeof
    881     // the struct at compile time). Instead, we use sk_malloc_canfail, with
    882     // sizeof__wuffs_gif__decoder returning the appropriate value for the
    883     // (statically or dynamically) linked version of the Wuffs library.
    884     //
    885     // As a C (not C++) library, none of the Wuffs types have constructors or
    886     // destructors.
    887     //
    888     // In RAII style, we can still use std::unique_ptr with these pointers, but
    889     // we pair the pointer with sk_free instead of C++'s delete.
    890     void* decoder_raw = sk_malloc_canfail(sizeof__wuffs_gif__decoder());
    891     if (!decoder_raw) {
    892         *result = SkCodec::kInternalError;
    893         return nullptr;
    894     }
    895     std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> decoder(
    896         reinterpret_cast<wuffs_gif__decoder*>(decoder_raw), &sk_free);
    897 
    898     SkCodec::Result reset_result =
    899         reset_and_decode_image_config(decoder.get(), &imgcfg, &iobuf, stream.get());
    900     if (reset_result != SkCodec::kSuccess) {
    901         *result = reset_result;
    902         return nullptr;
    903     }
    904 
    905     uint32_t width = imgcfg.pixcfg.width();
    906     uint32_t height = imgcfg.pixcfg.height();
    907     if ((width == 0) || (width > INT_MAX) || (height == 0) || (height > INT_MAX)) {
    908         *result = SkCodec::kInvalidInput;
    909         return nullptr;
    910     }
    911 
    912     uint64_t workbuf_len = decoder->workbuf_len().max_incl;
    913     void*    workbuf_ptr_raw = nullptr;
    914     if (workbuf_len) {
    915         workbuf_ptr_raw = workbuf_len <= SIZE_MAX ? sk_malloc_canfail(workbuf_len) : nullptr;
    916         if (!workbuf_ptr_raw) {
    917             *result = SkCodec::kInternalError;
    918             return nullptr;
    919         }
    920     }
    921     std::unique_ptr<uint8_t, decltype(&sk_free)> workbuf_ptr(
    922         reinterpret_cast<uint8_t*>(workbuf_ptr_raw), &sk_free);
    923 
    924     uint64_t pixbuf_len = imgcfg.pixcfg.pixbuf_len();
    925     void*    pixbuf_ptr_raw = pixbuf_len <= SIZE_MAX ? sk_malloc_canfail(pixbuf_len) : nullptr;
    926     if (!pixbuf_ptr_raw) {
    927         *result = SkCodec::kInternalError;
    928         return nullptr;
    929     }
    930     std::unique_ptr<uint8_t, decltype(&sk_free)> pixbuf_ptr(
    931         reinterpret_cast<uint8_t*>(pixbuf_ptr_raw), &sk_free);
    932     wuffs_base__pixel_buffer pixbuf = wuffs_base__null_pixel_buffer();
    933 
    934     const char* status = pixbuf.set_from_slice(
    935         &imgcfg.pixcfg, wuffs_base__make_slice_u8(pixbuf_ptr.get(), SkToSizeT(pixbuf_len)));
    936     if (status != nullptr) {
    937         SkCodecPrintf("set_from_slice: %s", status);
    938         *result = SkCodec::kInternalError;
    939         return nullptr;
    940     }
    941 
    942     SkEncodedInfo::Color color =
    943         (imgcfg.pixcfg.pixel_format() == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL)
    944             ? SkEncodedInfo::kBGRA_Color
    945             : SkEncodedInfo::kRGBA_Color;
    946 
    947     // In Skia's API, the alpha we calculate here and return is only for the
    948     // first frame.
    949     SkEncodedInfo::Alpha alpha = imgcfg.first_frame_is_opaque() ? SkEncodedInfo::kOpaque_Alpha
    950                                                                 : SkEncodedInfo::kBinary_Alpha;
    951 
    952     SkEncodedInfo encodedInfo = SkEncodedInfo::Make(width, height, color, alpha, 8);
    953 
    954     *result = SkCodec::kSuccess;
    955     return std::unique_ptr<SkCodec>(new SkWuffsCodec(
    956         std::move(encodedInfo), std::move(stream), std::move(decoder), std::move(pixbuf_ptr),
    957         std::move(workbuf_ptr), workbuf_len, imgcfg, pixbuf, iobuf));
    958 }
    959