Add base.image_decoder
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index ccad8ca..3fbcb14 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -346,11 +346,13 @@
var Interfaces = []string{
"hasher_u32",
+ "image_decoder",
"io_transformer",
}
var InterfacesMap = map[string]bool{
"hasher_u32": true,
+ "image_decoder": true,
"io_transformer": true,
}
@@ -359,6 +361,24 @@
"hasher_u32.update_u32!(x: slice u8) u32",
+ // ---- image_decoder
+
+ "image_decoder.ack_metadata_chunk?(src: io_reader)",
+ "image_decoder.decode_frame?(" +
+ "dst: ptr pixel_buffer, src: io_reader, workbuf: slice u8," +
+ "opts: nptr decode_frame_options)",
+ "image_decoder.decode_frame_config?(dst: nptr frame_config, src: io_reader)",
+ "image_decoder.decode_image_config?(dst: nptr image_config, src: io_reader)",
+ "image_decoder.frame_dirty_rect() rect_ie_u32",
+ "image_decoder.metadata_chunk_length() u64",
+ "image_decoder.metadata_fourcc() u32",
+ "image_decoder.num_animation_loops() u32",
+ "image_decoder.num_decoded_frame_configs() u64",
+ "image_decoder.num_decoded_frames() u64",
+ "image_decoder.restart_frame!(index: u64, io_position: u64) status",
+ "image_decoder.set_report_metadata!(fourcc: u32, report: bool)",
+ "image_decoder.workbuf_len() range_ii_u64",
+
// ---- io_transformer
"io_transformer.transform_io?(dst: io_writer, src: io_reader, workbuf: slice u8)",
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index ed4c560..ead174b 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -2604,6 +2604,190 @@
// --------
+extern const char* wuffs_base__image_decoder__vtable_name;
+
+typedef struct {
+ wuffs_base__status (*ack_metadata_chunk)(void* self,
+ wuffs_base__io_buffer* a_src);
+ wuffs_base__status (*decode_frame)(void* self,
+ wuffs_base__pixel_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf,
+ wuffs_base__decode_frame_options* a_opts);
+ wuffs_base__status (*decode_frame_config)(void* self,
+ wuffs_base__frame_config* a_dst,
+ wuffs_base__io_buffer* a_src);
+ wuffs_base__status (*decode_image_config)(void* self,
+ wuffs_base__image_config* a_dst,
+ wuffs_base__io_buffer* a_src);
+ wuffs_base__rect_ie_u32 (*frame_dirty_rect)(const void* self);
+ uint64_t (*metadata_chunk_length)(const void* self);
+ uint32_t (*metadata_fourcc)(const void* self);
+ uint32_t (*num_animation_loops)(const void* self);
+ uint64_t (*num_decoded_frame_configs)(const void* self);
+ uint64_t (*num_decoded_frames)(const void* self);
+ wuffs_base__status (*restart_frame)(void* self,
+ uint64_t a_index,
+ uint64_t a_io_position);
+ wuffs_base__empty_struct (*set_report_metadata)(void* self,
+ uint32_t a_fourcc,
+ bool a_report);
+ wuffs_base__range_ii_u64 (*workbuf_len)(const void* self);
+} wuffs_base__image_decoder__func_ptrs;
+
+typedef struct wuffs_base__image_decoder__struct wuffs_base__image_decoder;
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__ack_metadata_chunk(wuffs_base__image_decoder* self,
+ wuffs_base__io_buffer* a_src);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_frame(
+ wuffs_base__image_decoder* self,
+ wuffs_base__pixel_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf,
+ wuffs_base__decode_frame_options* a_opts);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_frame_config(wuffs_base__image_decoder* self,
+ wuffs_base__frame_config* a_dst,
+ wuffs_base__io_buffer* a_src);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_image_config(wuffs_base__image_decoder* self,
+ wuffs_base__image_config* a_dst,
+ wuffs_base__io_buffer* a_src);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 //
+wuffs_base__image_decoder__frame_dirty_rect(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__metadata_chunk_length(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_base__image_decoder__metadata_fourcc(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_base__image_decoder__num_animation_loops(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__num_decoded_frame_configs(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__num_decoded_frames(
+ const wuffs_base__image_decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__restart_frame(wuffs_base__image_decoder* self,
+ uint64_t a_index,
+ uint64_t a_io_position);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_base__image_decoder__set_report_metadata(wuffs_base__image_decoder* self,
+ uint32_t a_fourcc,
+ bool a_report);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 //
+wuffs_base__image_decoder__workbuf_len(const wuffs_base__image_decoder* self);
+
+#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
+struct wuffs_base__image_decoder__struct {
+ struct {
+ uint32_t magic;
+ uint32_t active_coroutine;
+ wuffs_base__vtable first_vtable;
+ } private_impl;
+
+#ifdef __cplusplus
+
+ inline wuffs_base__status //
+ ack_metadata_chunk(wuffs_base__io_buffer* a_src) {
+ return wuffs_base__image_decoder__ack_metadata_chunk(this, a_src);
+ }
+
+ inline wuffs_base__status //
+ decode_frame(wuffs_base__pixel_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf,
+ wuffs_base__decode_frame_options* a_opts) {
+ return wuffs_base__image_decoder__decode_frame(this, a_dst, a_src,
+ a_workbuf, a_opts);
+ }
+
+ inline wuffs_base__status //
+ decode_frame_config(wuffs_base__frame_config* a_dst,
+ wuffs_base__io_buffer* a_src) {
+ return wuffs_base__image_decoder__decode_frame_config(this, a_dst, a_src);
+ }
+
+ inline wuffs_base__status //
+ decode_image_config(wuffs_base__image_config* a_dst,
+ wuffs_base__io_buffer* a_src) {
+ return wuffs_base__image_decoder__decode_image_config(this, a_dst, a_src);
+ }
+
+ inline wuffs_base__rect_ie_u32 //
+ frame_dirty_rect() const {
+ return wuffs_base__image_decoder__frame_dirty_rect(this);
+ }
+
+ inline uint64_t //
+ metadata_chunk_length() const {
+ return wuffs_base__image_decoder__metadata_chunk_length(this);
+ }
+
+ inline uint32_t //
+ metadata_fourcc() const {
+ return wuffs_base__image_decoder__metadata_fourcc(this);
+ }
+
+ inline uint32_t //
+ num_animation_loops() const {
+ return wuffs_base__image_decoder__num_animation_loops(this);
+ }
+
+ inline uint64_t //
+ num_decoded_frame_configs() const {
+ return wuffs_base__image_decoder__num_decoded_frame_configs(this);
+ }
+
+ inline uint64_t //
+ num_decoded_frames() const {
+ return wuffs_base__image_decoder__num_decoded_frames(this);
+ }
+
+ inline wuffs_base__status //
+ restart_frame(uint64_t a_index, uint64_t a_io_position) {
+ return wuffs_base__image_decoder__restart_frame(this, a_index,
+ a_io_position);
+ }
+
+ inline wuffs_base__empty_struct //
+ set_report_metadata(uint32_t a_fourcc, bool a_report) {
+ return wuffs_base__image_decoder__set_report_metadata(this, a_fourcc,
+ a_report);
+ }
+
+ inline wuffs_base__range_ii_u64 //
+ workbuf_len() const {
+ return wuffs_base__image_decoder__workbuf_len(this);
+ }
+
+#endif // __cplusplus
+
+}; // struct wuffs_base__image_decoder__struct
+
+#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
+// --------
+
extern const char* wuffs_base__io_transformer__vtable_name;
typedef struct {
@@ -3372,6 +3556,12 @@
// ---------------- Upcasts
+static inline wuffs_base__image_decoder* //
+wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(
+ wuffs_gif__decoder* p) {
+ return (wuffs_base__image_decoder*)p;
+}
+
// ---------------- Public Function Prototypes
WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
@@ -3451,6 +3641,7 @@
struct {
uint32_t magic;
uint32_t active_coroutine;
+ wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
wuffs_base__vtable null_vtable;
uint32_t f_width;
@@ -3606,6 +3797,11 @@
initialize_flags);
}
+ inline wuffs_base__image_decoder* //
+ upcast_as__wuffs_base__image_decoder() {
+ return (wuffs_base__image_decoder*)this;
+ }
+
inline wuffs_base__empty_struct //
set_quirk_enabled(uint32_t a_quirk, bool a_enabled) {
return wuffs_gif__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
@@ -4841,6 +5037,378 @@
// --------
+const char* wuffs_base__image_decoder__vtable_name =
+ "{vtable}wuffs_base__image_decoder";
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__ack_metadata_chunk(wuffs_base__image_decoder* self,
+ wuffs_base__io_buffer* a_src) {
+ if (!self) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_status(
+ (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->ack_metadata_chunk)(self, a_src);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_status(wuffs_base__error__bad_vtable);
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_frame(
+ wuffs_base__image_decoder* self,
+ wuffs_base__pixel_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
+ wuffs_base__slice_u8 a_workbuf,
+ wuffs_base__decode_frame_options* a_opts) {
+ if (!self) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_status(
+ (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->decode_frame)(self, a_dst, a_src, a_workbuf, a_opts);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_status(wuffs_base__error__bad_vtable);
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_frame_config(wuffs_base__image_decoder* self,
+ wuffs_base__frame_config* a_dst,
+ wuffs_base__io_buffer* a_src) {
+ if (!self) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_status(
+ (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->decode_frame_config)(self, a_dst, a_src);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_status(wuffs_base__error__bad_vtable);
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__decode_image_config(wuffs_base__image_decoder* self,
+ wuffs_base__image_config* a_dst,
+ wuffs_base__io_buffer* a_src) {
+ if (!self) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_status(
+ (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->decode_image_config)(self, a_dst, a_src);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_status(wuffs_base__error__bad_vtable);
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32 //
+wuffs_base__image_decoder__frame_dirty_rect(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return wuffs_base__utility__make_rect_ie_u32(0, 0, 0, 0);
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return wuffs_base__utility__make_rect_ie_u32(0, 0, 0, 0);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->frame_dirty_rect)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__utility__make_rect_ie_u32(0, 0, 0, 0);
+}
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__metadata_chunk_length(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->metadata_chunk_length)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_base__image_decoder__metadata_fourcc(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->metadata_fourcc)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_base__image_decoder__num_animation_loops(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->num_animation_loops)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__num_decoded_frame_configs(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->num_decoded_frame_configs)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_base__image_decoder__num_decoded_frames(
+ const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->num_decoded_frames)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__image_decoder__restart_frame(wuffs_base__image_decoder* self,
+ uint64_t a_index,
+ uint64_t a_io_position) {
+ if (!self) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_status(
+ (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->restart_frame)(self, a_index, a_io_position);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_status(wuffs_base__error__bad_vtable);
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_base__image_decoder__set_report_metadata(wuffs_base__image_decoder* self,
+ uint32_t a_fourcc,
+ bool a_report) {
+ if (!self) {
+ return wuffs_base__make_empty_struct();
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_empty_struct();
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->set_report_metadata)(self, a_fourcc, a_report);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__make_empty_struct();
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64 //
+wuffs_base__image_decoder__workbuf_len(const wuffs_base__image_decoder* self) {
+ if (!self) {
+ return wuffs_base__utility__make_range_ii_u64(0, 0);
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return wuffs_base__utility__make_range_ii_u64(0, 0);
+ }
+
+ const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+ int i;
+ for (i = 0; i < 63; i++) {
+ if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
+ const wuffs_base__image_decoder__func_ptrs* func_ptrs =
+ (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
+ return (*func_ptrs->workbuf_len)(self);
+ } else if (v->vtable_name == NULL) {
+ break;
+ }
+ v++;
+ }
+
+ return wuffs_base__utility__make_range_ii_u64(0, 0);
+}
+
+// --------
+
const char* wuffs_base__io_transformer__vtable_name =
"{vtable}wuffs_base__io_transformer";
@@ -8926,6 +9494,40 @@
// ---------------- VTables
+const wuffs_base__image_decoder__func_ptrs
+ wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder = {
+ (wuffs_base__status(*)(void*, wuffs_base__io_buffer*))(
+ &wuffs_gif__decoder__ack_metadata_chunk),
+ (wuffs_base__status(*)(void*,
+ wuffs_base__pixel_buffer*,
+ wuffs_base__io_buffer*,
+ wuffs_base__slice_u8,
+ wuffs_base__decode_frame_options*))(
+ &wuffs_gif__decoder__decode_frame),
+ (wuffs_base__status(*)(void*,
+ wuffs_base__frame_config*,
+ wuffs_base__io_buffer*))(
+ &wuffs_gif__decoder__decode_frame_config),
+ (wuffs_base__status(*)(void*,
+ wuffs_base__image_config*,
+ wuffs_base__io_buffer*))(
+ &wuffs_gif__decoder__decode_image_config),
+ (wuffs_base__rect_ie_u32(*)(const void*))(
+ &wuffs_gif__decoder__frame_dirty_rect),
+ (uint64_t(*)(const void*))(&wuffs_gif__decoder__metadata_chunk_length),
+ (uint32_t(*)(const void*))(&wuffs_gif__decoder__metadata_fourcc),
+ (uint32_t(*)(const void*))(&wuffs_gif__decoder__num_animation_loops),
+ (uint64_t(*)(const void*))(
+ &wuffs_gif__decoder__num_decoded_frame_configs),
+ (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frames),
+ (wuffs_base__status(*)(void*, uint64_t, uint64_t))(
+ &wuffs_gif__decoder__restart_frame),
+ (wuffs_base__empty_struct(*)(void*, uint32_t, bool))(
+ &wuffs_gif__decoder__set_report_metadata),
+ (wuffs_base__range_ii_u64(*)(const void*))(
+ &wuffs_gif__decoder__workbuf_len),
+};
+
// ---------------- Initializer Implementations
wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT //
@@ -8977,6 +9579,10 @@
}
}
self->private_impl.magic = WUFFS_BASE__MAGIC;
+ self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
+ wuffs_base__image_decoder__vtable_name;
+ self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
+ (const void*)(&wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder);
return wuffs_base__make_status(NULL);
}
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 2019331..e4606a1 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -46,7 +46,7 @@
pri const interlace_delta array[5] base.u8 = [1, 2, 4, 8, 8]
pri const interlace_count array[5] base.u8 = [0, 1, 2, 4, 8]
-pub struct decoder?(
+pub struct decoder? implements base.image_decoder(
width : base.u32,
height : base.u32,
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 4fdd5ce..a3fa11f 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -195,6 +195,18 @@
// ---------------- GIF Tests
+const char* test_wuffs_gif_decode_interface() {
+ CHECK_FOCUS(__func__);
+ wuffs_gif__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_gif__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+ return do_test__wuffs_base__image_decoder(
+ wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(&dec),
+ "test/data/bricks-nodither.gif", 0, SIZE_MAX, 160, 120, 0xFF012463);
+}
+
const char* wuffs_gif_decode(wuffs_base__io_buffer* dst,
uint32_t wuffs_initialize_flags,
wuffs_base__pixel_format pixfmt,
@@ -2267,6 +2279,7 @@
test_wuffs_gif_decode_input_is_a_gif_many_medium_reads, //
test_wuffs_gif_decode_input_is_a_gif_many_small_reads, //
test_wuffs_gif_decode_input_is_a_png, //
+ test_wuffs_gif_decode_interface, //
test_wuffs_gif_decode_interlaced_truncated, //
test_wuffs_gif_decode_metadata_empty, //
test_wuffs_gif_decode_metadata_full, //
diff --git a/test/c/testlib/testlib.c b/test/c/testlib/testlib.c
index ed00ac7..dda75ec 100644
--- a/test/c/testlib/testlib.c
+++ b/test/c/testlib/testlib.c
@@ -784,6 +784,61 @@
return NULL;
}
+const char* do_test__wuffs_base__image_decoder(
+ wuffs_base__image_decoder* b,
+ const char* src_filename,
+ size_t src_ri,
+ size_t src_wi,
+ uint32_t want_width,
+ uint32_t want_height,
+ wuffs_base__color_u32_argb_premul want_final_pixel) {
+ if ((want_width > 16384) || (want_height > 16384) ||
+ ((want_width * want_height * 4) > BUFFER_SIZE)) {
+ return "want dimensions are too large";
+ }
+
+ wuffs_base__image_config ic = ((wuffs_base__image_config){});
+ wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
+ .data = global_src_slice,
+ });
+ CHECK_STRING(read_file_fragment(&src, src_filename, src_ri, src_wi));
+ CHECK_STATUS("decode_image_config",
+ wuffs_base__image_decoder__decode_image_config(b, &ic, &src));
+
+ uint32_t got_width = wuffs_base__pixel_config__width(&ic.pixcfg);
+ if (got_width != want_width) {
+ RETURN_FAIL("width: got %" PRIu32 ", want %" PRIu32, got_width, want_width);
+ }
+ uint32_t got_height = wuffs_base__pixel_config__height(&ic.pixcfg);
+ if (got_height != want_height) {
+ RETURN_FAIL("height: got %" PRIu32 ", want %" PRIu32, got_height,
+ want_height);
+ }
+ wuffs_base__pixel_config__set(
+ &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
+ WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, want_width, want_height);
+
+ wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
+ CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
+ &pb, &ic.pixcfg, global_pixel_slice));
+ CHECK_STATUS("decode_frame", wuffs_base__image_decoder__decode_frame(
+ b, &pb, &src, global_work_slice, NULL));
+
+ uint64_t n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
+ if (n < 4) {
+ RETURN_FAIL("pixbuf_len too small");
+ } else if (n > BUFFER_SIZE) {
+ RETURN_FAIL("pixbuf_len too large");
+ }
+ wuffs_base__color_u32_argb_premul got_final_pixel =
+ wuffs_base__load_u32le(&global_pixel_array[n - 4]);
+ if (got_final_pixel != want_final_pixel) {
+ RETURN_FAIL("final pixel: got 0x%08" PRIX32 ", want 0x%08" PRIX32,
+ got_final_pixel, want_final_pixel);
+ }
+ return NULL;
+}
+
const char* do_test__wuffs_base__io_transformer(wuffs_base__io_transformer* b,
const char* src_filename,
size_t src_ri,