57#if defined(WUFFS_IMPLEMENTATION)
58#error "SkWuffsCodec should not #define WUFFS_IMPLEMENTATION"
60#include "wuffs-v0.3.c"
62#if WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT < 2514
63#error "Wuffs version is too old. Upgrade to the latest version."
66#define SK_WUFFS_CODEC_BUFFER_SIZE 4096
78#if defined(SK_WUFFS_FAVORS_PERFORMANCE_OVER_ADDITIONAL_MEMORY_SAFETY)
79#define SK_WUFFS_INITIALIZE_FLAGS WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
81#define SK_WUFFS_INITIALIZE_FLAGS WUFFS_INITIALIZE__DEFAULT_OPTIONS
86 size_t num_read =
s->read(
b->data.ptr +
b->meta.wi,
b->data.len -
b->meta.wi);
87 b->meta.wi += num_read;
109 b->meta.closed =
false;
116 if ((
pos >=
b->meta.pos) && (
pos -
b->meta.pos <=
b->meta.wi)) {
117 b->meta.ri =
pos -
b->meta.pos;
121 if ((
pos > SIZE_MAX) || (!
s->seek(
pos))) {
127 b->meta.closed =
false;
132 wuffs_base__animation_disposal
w) {
134 case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND:
136 case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS:
148 wuffs_base__image_config* imgcfg,
149 wuffs_base__io_buffer*
b,
153 wuffs_base__status status =
155 if (status.repr !=
nullptr) {
161 decoder->set_quirk_enabled(WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA,
true);
164 status = decoder->decode_image_config(imgcfg,
b);
165 if (status.repr ==
nullptr) {
167 }
else if (status.repr != wuffs_base__suspension__short_read) {
179 uint32_t pixfmt = WUFFS_BASE__PIXEL_FORMAT__INVALID;
180 switch (kN32_SkColorType) {
182 pixfmt = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
185 pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
191 imgcfg->pixcfg.set(pixfmt, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, imgcfg->pixcfg.width(),
192 imgcfg->pixcfg.height());
212 uint64_t fIOPosition;
240 std::unique_ptr<SkStream>
stream,
242 std::unique_ptr<wuffs_gif__decoder,
decltype(&
sk_free)> dec,
243 std::unique_ptr<uint8_t,
decltype(&
sk_free)> workbuf_ptr,
245 wuffs_base__image_config imgcfg,
246 wuffs_base__io_buffer iobuf);
282 uint32_t pixelFormat,
283 size_t bytesPerPixel);
284 Result onStartIncrementalDecodeTwoPass();
285 Result onIncrementalDecodeOnePass();
286 Result onIncrementalDecodeTwoPass();
288 void onGetFrameCountInternal();
289 Result seekFrame(
int frameIndex);
291 const char* decodeFrameConfig();
292 const char* decodeFrame();
293 void updateNumFullyReceivedFrames();
296 std::unique_ptr<SkStream> fPrivStream;
297 std::unique_ptr<uint8_t,
decltype(&
sk_free)> fWorkbufPtr;
300 std::unique_ptr<wuffs_gif__decoder,
decltype(&
sk_free)> fDecoder;
302 const uint64_t fFirstFrameIOPosition;
303 wuffs_base__frame_config fFrameConfig;
304 wuffs_base__pixel_config fPixelConfig;
305 wuffs_base__pixel_buffer fPixelBuffer;
306 wuffs_base__io_buffer fIOBuffer;
309 uint8_t* fIncrDecDst;
310 size_t fIncrDecRowBytes;
311 wuffs_base__pixel_blend fIncrDecPixelBlend;
312 bool fIncrDecOnePass;
313 bool fFirstCallToIncrementalDecode;
316 std::unique_ptr<uint8_t,
decltype(&
sk_free)> fTwoPassPixbufPtr;
317 size_t fTwoPassPixbufLen;
319 uint64_t fNumFullyReceivedFrames;
320 std::vector<SkWuffsFrame> fFrames;
321 bool fFramesComplete;
333 bool fDecoderIsSuspended;
346 fIOPosition(fc->io_position()),
347 fReportedAlpha(fc->opaque_within_bounds() ?
SkEncodedInfo::kOpaque_Alpha
349 wuffs_base__rect_ie_u32 r = fc->bounds();
350 this->
setXYWH(r.min_incl_x, r.min_incl_y, r.width(), r.height());
352 this->
setDuration(fc->duration() / WUFFS_BASE__FLICKS_PER_MILLISECOND);
362 return fReportedAlpha;
375 return fCodec->
frame(i);
381 std::unique_ptr<SkStream> stream,
383 std::unique_ptr<wuffs_gif__decoder,
decltype(&
sk_free)> dec,
384 std::unique_ptr<uint8_t,
decltype(&
sk_free)> workbuf_ptr,
386 wuffs_base__image_config imgcfg,
387 wuffs_base__io_buffer iobuf)
395 fPrivStream(
std::move(stream)),
396 fWorkbufPtr(
std::move(workbuf_ptr)),
397 fWorkbufLen(workbuf_len),
398 fDecoder(
std::move(dec)),
399 fFirstFrameIOPosition(imgcfg.first_frame_io_position()),
400 fFrameConfig(wuffs_base__null_frame_config()),
401 fPixelConfig(imgcfg.pixcfg),
402 fPixelBuffer(wuffs_base__null_pixel_buffer()),
403 fIOBuffer(wuffs_base__empty_io_buffer()),
404 fIncrDecDst(nullptr),
406 fIncrDecPixelBlend(WUFFS_BASE__PIXEL_BLEND__SRC),
407 fIncrDecOnePass(false),
408 fFirstCallToIncrementalDecode(false),
409 fTwoPassPixbufPtr(nullptr, &
sk_free),
410 fTwoPassPixbufLen(0),
411 fNumFullyReceivedFrames(0),
412 fFramesComplete(false),
413 fDecoderIsSuspended(false),
415 fFrameHolder.
init(
this, imgcfg.pixcfg.width(), imgcfg.pixcfg.height());
421 memmove(fBuffer, iobuf.data.ptr, iobuf.meta.wi);
423 fIOBuffer.meta = iobuf.meta;
427 if ((0 <= i) && (
static_cast<size_t>(i) < fFrames.size())) {
450 return &fFrameHolder;
468 const char* status = this->decodeFrameConfig();
469 if (status == wuffs_base__suspension__short_read) {
471 }
else if (status !=
nullptr) {
476 uint32_t pixelFormat = WUFFS_BASE__PIXEL_FORMAT__INVALID;
477 size_t bytesPerPixel = 0;
481 pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGR_565;
485 pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
489 pixelFormat = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
498 fIncrDecOnePass = (pixelFormat != WUFFS_BASE__PIXEL_FORMAT__INVALID) &&
505 result = fIncrDecOnePass ? this->onStartIncrementalDecodeOnePass(
507 pixelFormat, bytesPerPixel)
508 : this->onStartIncrementalDecodeTwoPass();
513 fIncrDecDst =
static_cast<uint8_t*
>(dst);
514 fIncrDecRowBytes = rowBytes;
515 fFirstCallToIncrementalDecode =
true;
523 uint32_t pixelFormat,
524 size_t bytesPerPixel) {
525 wuffs_base__pixel_config pixelConfig;
526 pixelConfig.set(pixelFormat, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
dstInfo.
width(),
529 wuffs_base__table_u8
table;
533 table.stride = rowBytes;
535 wuffs_base__status status = fPixelBuffer.set_from_table(&pixelConfig,
table);
536 if (status.repr !=
nullptr) {
546 fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC_OVER;
549 fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
558 bool already_zeroed =
false;
560 if (!fTwoPassPixbufPtr) {
561 uint64_t pixbuf_len = fPixelConfig.pixbuf_len();
562 void* pixbuf_ptr_raw = (pixbuf_len <= SIZE_MAX)
565 if (!pixbuf_ptr_raw) {
568 fTwoPassPixbufPtr.reset(
reinterpret_cast<uint8_t*
>(pixbuf_ptr_raw));
569 fTwoPassPixbufLen =
SkToSizeT(pixbuf_len);
570 already_zeroed =
true;
573 wuffs_base__status status = fPixelBuffer.set_from_slice(
574 &fPixelConfig, wuffs_base__make_slice_u8(fTwoPassPixbufPtr.get(), fTwoPassPixbufLen));
575 if (status.repr !=
nullptr) {
580 if (!already_zeroed) {
581 uint32_t src_bits_per_pixel = fPixelConfig.pixel_format().bits_per_pixel();
582 if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
585 size_t src_bytes_per_pixel = src_bits_per_pixel / 8;
587 wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
588 wuffs_base__table_u8 pixels = fPixelBuffer.plane(0);
590 uint8_t* ptr = pixels.ptr + (frame_rect.min_incl_y * pixels.stride) +
591 (frame_rect.min_incl_x * src_bytes_per_pixel);
592 size_t len = frame_rect.width() * src_bytes_per_pixel;
596 if ((len == pixels.stride) && (frame_rect.min_incl_y < frame_rect.max_excl_y)) {
597 sk_bzero(ptr, len * (frame_rect.max_excl_y - frame_rect.min_incl_y));
599 for (uint32_t
y = frame_rect.min_incl_y;
y < frame_rect.max_excl_y;
y++) {
601 ptr += pixels.stride;
606 fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
620 fIncrDecOnePass ? this->onIncrementalDecodeOnePass() : this->onIncrementalDecodeTwoPass();
622 fIncrDecDst =
nullptr;
623 fIncrDecRowBytes = 0;
624 fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
625 fIncrDecOnePass =
false;
631 const char* status = this->decodeFrame();
632 if (status !=
nullptr) {
633 if (status == wuffs_base__suspension__short_read) {
645 const char* status = this->decodeFrame();
657 if (status !=
nullptr) {
658 if (status == wuffs_base__suspension__short_read) {
672 uint32_t src_bits_per_pixel = fPixelBuffer.pixcfg.pixel_format().bits_per_pixel();
673 if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
676 size_t src_bytes_per_pixel = src_bits_per_pixel / 8;
678 wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
679 if (fFirstCallToIncrementalDecode) {
680 if (frame_rect.width() > (SIZE_MAX / src_bytes_per_pixel)) {
685 frame_rect.max_excl_x, frame_rect.max_excl_y);
692 fFirstCallToIncrementalDecode =
false;
706 wuffs_base__rect_ie_u32 dirty_rect = fDecoder->frame_dirty_rect();
707 if (!dirty_rect.is_empty()) {
708 wuffs_base__table_u8 pixels = fPixelBuffer.plane(0);
716 uint8_t*
s = pixels.ptr + (dirty_rect.min_incl_y * pixels.stride) +
717 (dirty_rect.min_incl_x * src_bytes_per_pixel);
727 src.installPixels(srcInfo,
s, pixels.stride);
771 if (fFramesComplete && (
static_cast<size_t>(
options().fFrameIndex) == fFrames.size() - 1)) {
772 fTwoPassPixbufPtr.reset(
nullptr);
773 fTwoPassPixbufLen = 0;
813 bool incrementalDecodeIsInProgress = fIncrDecDst !=
nullptr;
815 if (!fFramesComplete && !incrementalDecodeIsInProgress) {
816 this->onGetFrameCountInternal();
817 this->updateNumFullyReceivedFrames();
819 return fFrames.size();
822void SkWuffsCodec::onGetFrameCountInternal() {
823 size_t n = fFrames.size();
824 int i = n ? n - 1 : 0;
831 for (; i < INT_MAX; i++) {
832 const char* status = this->decodeFrameConfig();
833 if (status ==
nullptr) {
835 }
else if (status == wuffs_base__note__end_of_data) {
841 if (
static_cast<size_t>(i) < fFrames.size()) {
844 fFrames.emplace_back(&fFrameConfig);
849 fFramesComplete =
true;
863 f->fillIn(frameInfo,
static_cast<uint64_t
>(i) < this->fNumFullyReceivedFrames);
873 uint32_t n = fDecoder->num_animation_loops();
878 return n < INT_MAX ? n : INT_MAX;
882 if (fDecoderIsSuspended) {
890 if (frameIndex < 0) {
892 }
else if (frameIndex == 0) {
893 pos = fFirstFrameIOPosition;
894 }
else if (
static_cast<size_t>(frameIndex) < fFrames.size()) {
895 pos = fFrames[frameIndex].ioPosition();
903 wuffs_base__status status =
904 fDecoder->restart_frame(frameIndex, fIOBuffer.reader_io_position());
905 if (status.repr !=
nullptr) {
912 if (!fPrivStream->rewind()) {
915 fIOBuffer.meta = wuffs_base__empty_io_buffer_meta();
925 fDecoderIsSuspended =
false;
929const char* SkWuffsCodec::decodeFrameConfig() {
931 wuffs_base__status status =
932 fDecoder->decode_frame_config(&fFrameConfig, &fIOBuffer);
933 if ((status.repr == wuffs_base__suspension__short_read) &&
937 fDecoderIsSuspended = !status.is_complete();
938 this->updateNumFullyReceivedFrames();
943const char* SkWuffsCodec::decodeFrame() {
945 wuffs_base__status status = fDecoder->decode_frame(
946 &fPixelBuffer, &fIOBuffer, fIncrDecPixelBlend,
947 wuffs_base__make_slice_u8(fWorkbufPtr.get(), fWorkbufLen),
nullptr);
948 if ((status.repr == wuffs_base__suspension__short_read) &&
952 fDecoderIsSuspended = !status.is_complete();
953 this->updateNumFullyReceivedFrames();
958void SkWuffsCodec::updateNumFullyReceivedFrames() {
962 uint64_t n = fDecoder->num_decoded_frames();
963 if (fNumFullyReceivedFrames < n) {
964 fNumFullyReceivedFrames = n;
972 return fPrivStream->duplicate();
977bool IsGif(
const void* buf,
size_t bytesRead) {
978 constexpr const char* gif_ptr =
"GIF8";
979 constexpr size_t gif_len = 4;
980 return (bytesRead >= gif_len) && (memcmp(buf, gif_ptr, gif_len) == 0);
983std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream> stream,
992 bool canSeek =
stream->hasPosition() &&
stream->hasLength();
999 stream = std::make_unique<SkMemoryStream>(std::move(data));
1005 wuffs_base__io_buffer iobuf =
1007 wuffs_base__empty_io_buffer_meta());
1008 wuffs_base__image_config imgcfg = wuffs_base__null_image_config();
1034 std::unique_ptr<wuffs_gif__decoder,
decltype(&
sk_free)> decoder(
1035 reinterpret_cast<wuffs_gif__decoder*
>(decoder_raw), &
sk_free);
1044 uint32_t
width = imgcfg.pixcfg.width();
1045 uint32_t
height = imgcfg.pixcfg.height();
1051 uint64_t workbuf_len = decoder->workbuf_len().max_incl;
1052 void* workbuf_ptr_raw =
nullptr;
1054 workbuf_ptr_raw = workbuf_len <= SIZE_MAX ?
sk_malloc_canfail(workbuf_len) : nullptr;
1055 if (!workbuf_ptr_raw) {
1060 std::unique_ptr<uint8_t,
decltype(&
sk_free)> workbuf_ptr(
1061 reinterpret_cast<uint8_t*
>(workbuf_ptr_raw), &
sk_free);
1064 (imgcfg.pixcfg.pixel_format().repr == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL)
1076 return std::unique_ptr<SkCodec>(
new SkWuffsCodec(std::move(encodedInfo), std::move(stream),
1078 std::move(decoder), std::move(workbuf_ptr),
1079 workbuf_len, imgcfg, iobuf));
1082std::unique_ptr<SkCodec>
Decode(std::unique_ptr<SkStream> stream,
1084 SkCodecs::DecodeContext ctx) {
1087 outResult = &resultStorage;
1093 return MakeFromStream(std::move(stream), policy, outResult);
1098 SkCodecs::DecodeContext ctx) {
@ kOpaque_SkAlphaType
pixel is opaque
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkCodecPrintf(...)
static bool independent(const SkFrame &frame)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
SK_API void * sk_malloc_flags(size_t size, unsigned flags)
static void sk_bzero(void *buffer, size_t size)
SK_API void sk_free(void *)
static void * sk_malloc_canfail(size_t size)
@ SK_MALLOC_ZERO_INITIALIZE
sk_sp< SkData > SkCopyStreamToData(SkStream *stream)
constexpr size_t SkToSizeT(S x)
static SkCodecAnimation::DisposalMethod wuffs_disposal_to_skia_disposal(wuffs_base__animation_disposal w)
static SkCodec::Result reset_and_decode_image_config(wuffs_gif__decoder *decoder, wuffs_base__image_config *imgcfg, wuffs_base__io_buffer *b, SkStream *s)
static SkAlphaType to_alpha_type(bool opaque)
static bool seek_buffer(wuffs_base__io_buffer *b, SkStream *s, uint64_t pos)
#define SK_WUFFS_CODEC_BUFFER_SIZE
#define SK_WUFFS_INITIALIZE_FLAGS
static bool fill_buffer(wuffs_base__io_buffer *b, SkStream *s)
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
SkISize dimensions() const
const SkImageInfo & dstInfo() const
const SkEncodedInfo & getEncodedInfo() const
static constexpr int kRepetitionCountInfinite
static constexpr int kNoFrame
SkImageInfo getInfo() const
const Options & options() const
void setAlphaAndRequiredFrame(SkFrame *)
void setBlend(SkCodecAnimation::Blend blend)
void setDuration(int duration)
void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod)
void setXYWH(int x, int y, int width, int height)
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
static void Fill(const SkImageInfo &info, void *dst, size_t rowBytes, SkCodec::ZeroInitialized zeroInit)
const SkWuffsFrame * frame(int i) const
int onGetFrameCount() override
Result onIncrementalDecode(int *rowsDecoded) override
bool onGetFrameInfo(int, FrameInfo *) const override
Result onStartIncrementalDecode(const SkImageInfo &dstInfo, void *dst, size_t rowBytes, const SkCodec::Options &options) override
int onGetRepetitionCount() override
Result onGetPixels(const SkImageInfo &, void *, size_t, const Options &, int *) override
SkEncodedImageFormat onGetEncodedFormat() const override
SkWuffsCodec(SkEncodedInfo &&encodedInfo, std::unique_ptr< SkStream > stream, bool canSeek, std::unique_ptr< wuffs_gif__decoder, decltype(&sk_free)> dec, std::unique_ptr< uint8_t, decltype(&sk_free)> workbuf_ptr, size_t workbuf_len, wuffs_base__image_config imgcfg, wuffs_base__io_buffer iobuf)
std::unique_ptr< SkStream > getEncodedData() const override
const SkFrameHolder * getFrameHolder() const override
const SkFrame * onGetFrame(int i) const override
void init(SkWuffsCodec *codec, int width, int height)
SkWuffsFrame(wuffs_base__frame_config *fc)
SkEncodedInfo::Alpha onReportedAlpha() const override
uint64_t ioPosition() const
static const uint8_t buffer[]
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsGif(const void *, size_t)
unsigned useCenter Optional< SkMatrix > matrix
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
@ skcms_PixelFormat_RGBA_8888
ZeroInitialized fZeroInitialized
const skcms_ICCProfile * profile() const
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
static constexpr SkIRect MakeSize(const SkISize &size)
SkImageInfo makeWH(int newWidth, int newHeight) const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
SkISize dimensions() const
SkColorType colorType() const
static SkRect Make(const SkISize &size)