Remove wuffs_base__frame_config__blend
diff --git a/doc/changelog.md b/doc/changelog.md
index 0f07ac9..e18c76d 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -9,6 +9,7 @@
- Made `wuffs_base__pixel_format` a struct.
- Made `wuffs_base__pixel_subsampling` a struct.
- Made `wuffs_base__status` a struct.
+- Removed `wuffs_base__frame_config__blend`.
## 2019-12-19 version 0.2.0
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h
index 1c308e2..27700db 100644
--- a/internal/cgen/base/image-public.h
+++ b/internal/cgen/base/image-public.h
@@ -660,8 +660,9 @@
wuffs_base__flicks duration;
uint64_t index;
uint64_t io_position;
- wuffs_base__animation_blend blend;
wuffs_base__animation_disposal disposal;
+ bool opaque_within_bounds;
+ bool overwrite_instead_of_blend;
wuffs_base__color_u32_argb_premul background_color;
} private_impl;
@@ -670,8 +671,9 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color);
inline wuffs_base__rect_ie_u32 bounds() const;
inline uint32_t width() const;
@@ -679,8 +681,9 @@
inline wuffs_base__flicks duration() const;
inline uint64_t index() const;
inline uint64_t io_position() const;
- inline wuffs_base__animation_blend blend() const;
inline wuffs_base__animation_disposal disposal() const;
+ inline bool opaque_within_bounds() const;
+ inline bool overwrite_instead_of_blend() const;
inline wuffs_base__color_u32_argb_premul background_color() const;
#endif // __cplusplus
@@ -693,8 +696,9 @@
ret.private_impl.duration = 0;
ret.private_impl.index = 0;
ret.private_impl.io_position = 0;
- ret.private_impl.blend = 0;
ret.private_impl.disposal = 0;
+ ret.private_impl.opaque_within_bounds = false;
+ ret.private_impl.overwrite_instead_of_blend = false;
return ret;
}
@@ -705,8 +709,9 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color) {
if (!c) {
return;
@@ -716,8 +721,9 @@
c->private_impl.duration = duration;
c->private_impl.index = index;
c->private_impl.io_position = io_position;
- c->private_impl.blend = blend;
c->private_impl.disposal = disposal;
+ c->private_impl.opaque_within_bounds = opaque_within_bounds;
+ c->private_impl.overwrite_instead_of_blend = overwrite_instead_of_blend;
c->private_impl.background_color = background_color;
}
@@ -766,13 +772,6 @@
return c ? c->private_impl.io_position : 0;
}
-// wuffs_base__frame_config__blend returns, for an animated image, how to blend
-// the transparent pixels of this frame with the existing canvas.
-static inline wuffs_base__animation_blend //
-wuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {
- return c ? c->private_impl.blend : 0;
-}
-
// wuffs_base__frame_config__disposal returns, for an animated image, how to
// dispose of this frame after displaying it.
static inline wuffs_base__animation_disposal //
@@ -780,6 +779,37 @@
return c ? c->private_impl.disposal : 0;
}
+// wuffs_base__frame_config__opaque_within_bounds returns whether all pixels
+// within the frame's bounds are fully opaque. It makes no claim about pixels
+// outside the frame bounds but still inside the overall image. The two
+// bounding rectangles can differ for animated images.
+//
+// Its semantics are conservative. It is valid for a fully opaque frame to have
+// this value be false: a false negative.
+//
+// If true, drawing the frame with WUFFS_BASE__PIXEL_BLEND__SRC and
+// WUFFS_BASE__PIXEL_BLEND__SRC_OVER should be equivalent, in terms of
+// resultant pixels, but the former may be faster.
+static inline bool //
+wuffs_base__frame_config__opaque_within_bounds(
+ const wuffs_base__frame_config* c) {
+ return c && c->private_impl.opaque_within_bounds;
+}
+
+// wuffs_base__frame_config__overwrite_instead_of_blend returns, for an
+// animated image, whether to ignore the previous image state (within the frame
+// bounds) when drawing this incremental frame. Equivalently, whether to use
+// WUFFS_BASE__PIXEL_BLEND__SRC instead of WUFFS_BASE__PIXEL_BLEND__SRC_OVER.
+//
+// The WebP spec (https://developers.google.com/speed/webp/docs/riff_container)
+// calls this the "Blending method" bit. WebP's "Do not blend" corresponds to
+// Wuffs' "overwrite_instead_of_blend".
+static inline bool //
+wuffs_base__frame_config__overwrite_instead_of_blend(
+ const wuffs_base__frame_config* c) {
+ return c && c->private_impl.overwrite_instead_of_blend;
+}
+
static inline wuffs_base__color_u32_argb_premul //
wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
return c ? c->private_impl.background_color : 0;
@@ -793,11 +823,13 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color) {
- wuffs_base__frame_config__update(this, bounds, duration, index, io_position,
- blend, disposal, background_color);
+ wuffs_base__frame_config__update(
+ this, bounds, duration, index, io_position, disposal,
+ opaque_within_bounds, overwrite_instead_of_blend, background_color);
}
inline wuffs_base__rect_ie_u32 //
@@ -830,16 +862,21 @@
return wuffs_base__frame_config__io_position(this);
}
-inline wuffs_base__animation_blend //
-wuffs_base__frame_config::blend() const {
- return wuffs_base__frame_config__blend(this);
-}
-
inline wuffs_base__animation_disposal //
wuffs_base__frame_config::disposal() const {
return wuffs_base__frame_config__disposal(this);
}
+inline bool //
+wuffs_base__frame_config::opaque_within_bounds() const {
+ return wuffs_base__frame_config__opaque_within_bounds(this);
+}
+
+inline bool //
+wuffs_base__frame_config::overwrite_instead_of_blend() const {
+ return wuffs_base__frame_config__overwrite_instead_of_blend(this);
+}
+
inline wuffs_base__color_u32_argb_premul //
wuffs_base__frame_config::background_color() const {
return wuffs_base__frame_config__background_color(this);
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index a1f8eab..7b9decb 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -138,13 +138,14 @@
"" +
"// --------\n\n// wuffs_base__animation_disposal encodes, for an animated image, how to\n// dispose of a frame after displaying it:\n// - None means to draw the next frame on top of this one.\n// - Restore Background means to clear the frame's dirty rectangle to \"the\n// background color\" (in practice, this means transparent black) before\n// drawing the next frame.\n// - Restore Previous means to undo the current frame, so that the next frame\n// is drawn on top of the previous one.\ntypedef uint8_t wuffs_base__animation_disposal;\n\n#define WUFFS_BASE__ANIMATION_DISPOSAL__NONE ((wuffs_base__animation_disposal)0)\n#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND \\\n ((wuffs_base__animation_disposal)1)\n#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS \\\n ((wuffs_base__animation_disposal)2)\n\n" +
"" +
- "// --------\n\ntypedef struct {\n // Do not access the private_impl's fields directly. There is no API/ABI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__rect_ie_u32 bounds;\n wuffs_base__flicks duration;\n uint64_t index;\n uint64_t io_position;\n wuffs_base__animation_blend blend;\n wuffs_base__animation_disposal disposal;\n wuffs_base__color_u32_argb_premul background_color;\n } private_impl;\n\n#ifdef __cplusplus\n inline void update(wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color);\n inline wuffs_base__rect_ie_u32 bounds() const;\n inline uint32_t width() const;\n inline uint32_t height() const;\n inline wuffs_base__flicks duration() const;\n inline uint64_t index()" +
- " const;\n inline uint64_t io_position() const;\n inline wuffs_base__animation_blend blend() const;\n inline wuffs_base__animation_disposal disposal() const;\n inline wuffs_base__color_u32_argb_premul background_color() const;\n#endif // __cplusplus\n\n} wuffs_base__frame_config;\n\nstatic inline wuffs_base__frame_config //\nwuffs_base__null_frame_config() {\n wuffs_base__frame_config ret;\n ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);\n ret.private_impl.duration = 0;\n ret.private_impl.index = 0;\n ret.private_impl.io_position = 0;\n ret.private_impl.blend = 0;\n ret.private_impl.disposal = 0;\n return ret;\n}\n\nstatic inline void //\nwuffs_base__frame_config__update(\n wuffs_base__frame_config* c,\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color) {\n if (!c) {\n return;\n }\n\n c->privat" +
- "e_impl.bounds = bounds;\n c->private_impl.duration = duration;\n c->private_impl.index = index;\n c->private_impl.io_position = io_position;\n c->private_impl.blend = blend;\n c->private_impl.disposal = disposal;\n c->private_impl.background_color = background_color;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {\n if (c) {\n return c->private_impl.bounds;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__width(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__height(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;\n}\n\n// wuffs_base__frame_config__duration returns the amount of time to display\n// this frame. Zero means to d" +
- "isplay forever - a still (non-animated) image.\nstatic inline wuffs_base__flicks //\nwuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.duration : 0;\n}\n\n// wuffs_base__frame_config__index returns the index of this frame. The first\n// frame in an image has index 0, the second frame has index 1, and so on.\nstatic inline uint64_t //\nwuffs_base__frame_config__index(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.index : 0;\n}\n\n// wuffs_base__frame_config__io_position returns the I/O stream position before\n// the frame config.\nstatic inline uint64_t //\nwuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.io_position : 0;\n}\n\n// wuffs_base__frame_config__blend returns, for an animated image, how to blend\n// the transparent pixels of this frame with the existing canvas.\nstatic inline wuffs_base__animation_blend //\nwuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {\n return c ? c->p" +
- "rivate_impl.blend : 0;\n}\n\n// wuffs_base__frame_config__disposal returns, for an animated image, how to\n// dispose of this frame after displaying it.\nstatic inline wuffs_base__animation_disposal //\nwuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.disposal : 0;\n}\n\nstatic inline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.background_color : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__frame_config::update(\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color) {\n wuffs_base__frame_config__update(this, bounds, duration, index, io_position,\n blend, disposal, background_color);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_b" +
- "ase__frame_config::bounds() const {\n return wuffs_base__frame_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::width() const {\n return wuffs_base__frame_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::height() const {\n return wuffs_base__frame_config__height(this);\n}\n\ninline wuffs_base__flicks //\nwuffs_base__frame_config::duration() const {\n return wuffs_base__frame_config__duration(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::index() const {\n return wuffs_base__frame_config__index(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::io_position() const {\n return wuffs_base__frame_config__io_position(this);\n}\n\ninline wuffs_base__animation_blend //\nwuffs_base__frame_config::blend() const {\n return wuffs_base__frame_config__blend(this);\n}\n\ninline wuffs_base__animation_disposal //\nwuffs_base__frame_config::disposal() const {\n return wuffs_base__frame_config__disposal(this);\n}\n\ninline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_confi" +
- "g::background_color() const {\n return wuffs_base__frame_config__background_color(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct {\n // Do not access the private_impl's fields directly. There is no API/ABI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__rect_ie_u32 bounds;\n wuffs_base__flicks duration;\n uint64_t index;\n uint64_t io_position;\n wuffs_base__animation_disposal disposal;\n bool opaque_within_bounds;\n bool overwrite_instead_of_blend;\n wuffs_base__color_u32_argb_premul background_color;\n } private_impl;\n\n#ifdef __cplusplus\n inline void update(wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_disposal disposal,\n bool opaque_within_bounds,\n bool overwrite_instead_of_blend,\n wuffs_base__color_u32_argb_premul background_color);\n inline wuffs_base__rect_ie_u32 bounds() const;\n inline uint32_t width() const;\n inline uint32_t height() con" +
+ "st;\n inline wuffs_base__flicks duration() const;\n inline uint64_t index() const;\n inline uint64_t io_position() const;\n inline wuffs_base__animation_disposal disposal() const;\n inline bool opaque_within_bounds() const;\n inline bool overwrite_instead_of_blend() const;\n inline wuffs_base__color_u32_argb_premul background_color() const;\n#endif // __cplusplus\n\n} wuffs_base__frame_config;\n\nstatic inline wuffs_base__frame_config //\nwuffs_base__null_frame_config() {\n wuffs_base__frame_config ret;\n ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);\n ret.private_impl.duration = 0;\n ret.private_impl.index = 0;\n ret.private_impl.io_position = 0;\n ret.private_impl.disposal = 0;\n ret.private_impl.opaque_within_bounds = false;\n ret.private_impl.overwrite_instead_of_blend = false;\n return ret;\n}\n\nstatic inline void //\nwuffs_base__frame_config__update(\n wuffs_base__frame_config* c,\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_p" +
+ "osition,\n wuffs_base__animation_disposal disposal,\n bool opaque_within_bounds,\n bool overwrite_instead_of_blend,\n wuffs_base__color_u32_argb_premul background_color) {\n if (!c) {\n return;\n }\n\n c->private_impl.bounds = bounds;\n c->private_impl.duration = duration;\n c->private_impl.index = index;\n c->private_impl.io_position = io_position;\n c->private_impl.disposal = disposal;\n c->private_impl.opaque_within_bounds = opaque_within_bounds;\n c->private_impl.overwrite_instead_of_blend = overwrite_instead_of_blend;\n c->private_impl.background_color = background_color;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {\n if (c) {\n return c->private_impl.bounds;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__width(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_" +
+ "u32__width(&c->private_impl.bounds) : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__height(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;\n}\n\n// wuffs_base__frame_config__duration returns the amount of time to display\n// this frame. Zero means to display forever - a still (non-animated) image.\nstatic inline wuffs_base__flicks //\nwuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.duration : 0;\n}\n\n// wuffs_base__frame_config__index returns the index of this frame. The first\n// frame in an image has index 0, the second frame has index 1, and so on.\nstatic inline uint64_t //\nwuffs_base__frame_config__index(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.index : 0;\n}\n\n// wuffs_base__frame_config__io_position returns the I/O stream position before\n// the frame config.\nstatic inline uint64_t //\nwuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {\n " +
+ "return c ? c->private_impl.io_position : 0;\n}\n\n// wuffs_base__frame_config__disposal returns, for an animated image, how to\n// dispose of this frame after displaying it.\nstatic inline wuffs_base__animation_disposal //\nwuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.disposal : 0;\n}\n\n// wuffs_base__frame_config__opaque_within_bounds returns whether all pixels\n// within the frame's bounds are fully opaque. It makes no claim about pixels\n// outside the frame bounds but still inside the overall image. The two\n// bounding rectangles can differ for animated images.\n//\n// Its semantics are conservative. It is valid for a fully opaque frame to have\n// this value be false: a false negative.\n//\n// If true, drawing the frame with WUFFS_BASE__PIXEL_BLEND__SRC and\n// WUFFS_BASE__PIXEL_BLEND__SRC_OVER should be equivalent, in terms of\n// resultant pixels, but the former may be faster.\nstatic inline bool //\nwuffs_base__frame_config__opaque_within_bounds(\n const wuffs_" +
+ "base__frame_config* c) {\n return c && c->private_impl.opaque_within_bounds;\n}\n\n// wuffs_base__frame_config__overwrite_instead_of_blend returns, for an\n// animated image, whether to ignore the previous image state (within the frame\n// bounds) when drawing this incremental frame. Equivalently, whether to use\n// WUFFS_BASE__PIXEL_BLEND__SRC instead of WUFFS_BASE__PIXEL_BLEND__SRC_OVER.\n//\n// The WebP spec (https://developers.google.com/speed/webp/docs/riff_container)\n// calls this the \"Blending method\" bit. WebP's \"Do not blend\" corresponds to\n// Wuffs' \"overwrite_instead_of_blend\".\nstatic inline bool //\nwuffs_base__frame_config__overwrite_instead_of_blend(\n const wuffs_base__frame_config* c) {\n return c && c->private_impl.overwrite_instead_of_blend;\n}\n\nstatic inline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.background_color : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__frame_config::update(\n " +
+ " wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_disposal disposal,\n bool opaque_within_bounds,\n bool overwrite_instead_of_blend,\n wuffs_base__color_u32_argb_premul background_color) {\n wuffs_base__frame_config__update(\n this, bounds, duration, index, io_position, disposal,\n opaque_within_bounds, overwrite_instead_of_blend, background_color);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config::bounds() const {\n return wuffs_base__frame_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::width() const {\n return wuffs_base__frame_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::height() const {\n return wuffs_base__frame_config__height(this);\n}\n\ninline wuffs_base__flicks //\nwuffs_base__frame_config::duration() const {\n return wuffs_base__frame_config__duration(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::index() const {\n return wuffs_b" +
+ "ase__frame_config__index(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::io_position() const {\n return wuffs_base__frame_config__io_position(this);\n}\n\ninline wuffs_base__animation_disposal //\nwuffs_base__frame_config::disposal() const {\n return wuffs_base__frame_config__disposal(this);\n}\n\ninline bool //\nwuffs_base__frame_config::opaque_within_bounds() const {\n return wuffs_base__frame_config__opaque_within_bounds(this);\n}\n\ninline bool //\nwuffs_base__frame_config::overwrite_instead_of_blend() const {\n return wuffs_base__frame_config__overwrite_instead_of_blend(this);\n}\n\ninline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_config::background_color() const {\n return wuffs_base__frame_config__background_color(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
"// --------\n\ntypedef struct {\n wuffs_base__pixel_config pixcfg;\n\n // Do not access the private_impl's fields directly. There is no API/ABI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];\n // TODO: color spaces.\n } private_impl;\n\n#ifdef __cplusplus\n inline wuffs_base__status set_from_slice(\n const wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory);\n inline wuffs_base__status set_from_table(\n const wuffs_base__pixel_config* pixcfg,\n wuffs_base__table_u8 pixbuf_memory);\n inline wuffs_base__slice_u8 palette();\n inline wuffs_base__pixel_format pixel_format() const;\n inline wuffs_base__table_u8 plane(uint32_t p);\n#endif // __cplusplus\n\n} wuffs_base__pixel_buffer;\n\nstatic inline wuffs_base__pixel_buffer //\nwuffs_base__null_pixel_buffer() {\n wuffs_base__pixel_buffer ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.planes[0] = wuffs_base__empty_table_u8" +
"();\n ret.private_impl.planes[1] = wuffs_base__empty_table_u8();\n ret.private_impl.planes[2] = wuffs_base__empty_table_u8();\n ret.private_impl.planes[3] = wuffs_base__empty_table_u8();\n return ret;\n}\n\nstatic inline wuffs_base__status //\nwuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,\n const wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory) {\n if (!b) {\n return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n }\n memset(b, 0, sizeof(*b));\n if (!pixcfg) {\n return wuffs_base__make_status(wuffs_base__error__bad_argument);\n }\n if (wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);\n if ((bits_per_" +
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 4421bfe..473863f 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -318,12 +318,13 @@
"frame_config.index() u64",
"frame_config.io_position() u64",
- "frame_config.update!(bounds: rect_ie_u32, duration: u64[..= 0x7FFFFFFFFFFFFFFF], " +
- "index: u64, io_position: u64, blend: u8, disposal: u8, background_color: u32)",
+ "frame_config.update!(bounds: rect_ie_u32, duration: u64[..= 0x7FFFFFFFFFFFFFFF]," +
+ "index: u64, io_position: u64, disposal: u8, opaque_within_bounds: bool," +
+ "overwrite_instead_of_blend: bool, background_color: u32)",
// ---- image_config
- "image_config.set!(pixfmt: u32, pixsub: u32, width: u32, height: u32, " +
+ "image_config.set!(pixfmt: u32, pixsub: u32, width: u32, height: u32," +
"first_frame_io_position: u64, first_frame_is_opaque: bool)",
// ---- pixel_buffer
@@ -339,7 +340,7 @@
// ---- pixel_swizzler
"pixel_swizzler.prepare!(" +
- "dst_pixfmt: pixel_format, dst_palette: slice u8, " +
+ "dst_pixfmt: pixel_format, dst_palette: slice u8," +
"src_pixfmt: pixel_format, src_palette: slice u8, blend: pixel_blend) status",
"pixel_swizzler.swizzle_interleaved!(" +
"dst: slice u8, dst_palette: slice u8, src: slice u8) u64",
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 6419478..2149bef 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -2112,8 +2112,9 @@
wuffs_base__flicks duration;
uint64_t index;
uint64_t io_position;
- wuffs_base__animation_blend blend;
wuffs_base__animation_disposal disposal;
+ bool opaque_within_bounds;
+ bool overwrite_instead_of_blend;
wuffs_base__color_u32_argb_premul background_color;
} private_impl;
@@ -2122,8 +2123,9 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color);
inline wuffs_base__rect_ie_u32 bounds() const;
inline uint32_t width() const;
@@ -2131,8 +2133,9 @@
inline wuffs_base__flicks duration() const;
inline uint64_t index() const;
inline uint64_t io_position() const;
- inline wuffs_base__animation_blend blend() const;
inline wuffs_base__animation_disposal disposal() const;
+ inline bool opaque_within_bounds() const;
+ inline bool overwrite_instead_of_blend() const;
inline wuffs_base__color_u32_argb_premul background_color() const;
#endif // __cplusplus
@@ -2145,8 +2148,9 @@
ret.private_impl.duration = 0;
ret.private_impl.index = 0;
ret.private_impl.io_position = 0;
- ret.private_impl.blend = 0;
ret.private_impl.disposal = 0;
+ ret.private_impl.opaque_within_bounds = false;
+ ret.private_impl.overwrite_instead_of_blend = false;
return ret;
}
@@ -2157,8 +2161,9 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color) {
if (!c) {
return;
@@ -2168,8 +2173,9 @@
c->private_impl.duration = duration;
c->private_impl.index = index;
c->private_impl.io_position = io_position;
- c->private_impl.blend = blend;
c->private_impl.disposal = disposal;
+ c->private_impl.opaque_within_bounds = opaque_within_bounds;
+ c->private_impl.overwrite_instead_of_blend = overwrite_instead_of_blend;
c->private_impl.background_color = background_color;
}
@@ -2218,13 +2224,6 @@
return c ? c->private_impl.io_position : 0;
}
-// wuffs_base__frame_config__blend returns, for an animated image, how to blend
-// the transparent pixels of this frame with the existing canvas.
-static inline wuffs_base__animation_blend //
-wuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {
- return c ? c->private_impl.blend : 0;
-}
-
// wuffs_base__frame_config__disposal returns, for an animated image, how to
// dispose of this frame after displaying it.
static inline wuffs_base__animation_disposal //
@@ -2232,6 +2231,37 @@
return c ? c->private_impl.disposal : 0;
}
+// wuffs_base__frame_config__opaque_within_bounds returns whether all pixels
+// within the frame's bounds are fully opaque. It makes no claim about pixels
+// outside the frame bounds but still inside the overall image. The two
+// bounding rectangles can differ for animated images.
+//
+// Its semantics are conservative. It is valid for a fully opaque frame to have
+// this value be false: a false negative.
+//
+// If true, drawing the frame with WUFFS_BASE__PIXEL_BLEND__SRC and
+// WUFFS_BASE__PIXEL_BLEND__SRC_OVER should be equivalent, in terms of
+// resultant pixels, but the former may be faster.
+static inline bool //
+wuffs_base__frame_config__opaque_within_bounds(
+ const wuffs_base__frame_config* c) {
+ return c && c->private_impl.opaque_within_bounds;
+}
+
+// wuffs_base__frame_config__overwrite_instead_of_blend returns, for an
+// animated image, whether to ignore the previous image state (within the frame
+// bounds) when drawing this incremental frame. Equivalently, whether to use
+// WUFFS_BASE__PIXEL_BLEND__SRC instead of WUFFS_BASE__PIXEL_BLEND__SRC_OVER.
+//
+// The WebP spec (https://developers.google.com/speed/webp/docs/riff_container)
+// calls this the "Blending method" bit. WebP's "Do not blend" corresponds to
+// Wuffs' "overwrite_instead_of_blend".
+static inline bool //
+wuffs_base__frame_config__overwrite_instead_of_blend(
+ const wuffs_base__frame_config* c) {
+ return c && c->private_impl.overwrite_instead_of_blend;
+}
+
static inline wuffs_base__color_u32_argb_premul //
wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
return c ? c->private_impl.background_color : 0;
@@ -2245,11 +2275,13 @@
wuffs_base__flicks duration,
uint64_t index,
uint64_t io_position,
- wuffs_base__animation_blend blend,
wuffs_base__animation_disposal disposal,
+ bool opaque_within_bounds,
+ bool overwrite_instead_of_blend,
wuffs_base__color_u32_argb_premul background_color) {
- wuffs_base__frame_config__update(this, bounds, duration, index, io_position,
- blend, disposal, background_color);
+ wuffs_base__frame_config__update(
+ this, bounds, duration, index, io_position, disposal,
+ opaque_within_bounds, overwrite_instead_of_blend, background_color);
}
inline wuffs_base__rect_ie_u32 //
@@ -2282,16 +2314,21 @@
return wuffs_base__frame_config__io_position(this);
}
-inline wuffs_base__animation_blend //
-wuffs_base__frame_config::blend() const {
- return wuffs_base__frame_config__blend(this);
-}
-
inline wuffs_base__animation_disposal //
wuffs_base__frame_config::disposal() const {
return wuffs_base__frame_config__disposal(this);
}
+inline bool //
+wuffs_base__frame_config::opaque_within_bounds() const {
+ return wuffs_base__frame_config__opaque_within_bounds(this);
+}
+
+inline bool //
+wuffs_base__frame_config::overwrite_instead_of_blend() const {
+ return wuffs_base__frame_config__overwrite_instead_of_blend(this);
+}
+
inline wuffs_base__color_u32_argb_premul //
wuffs_base__frame_config::background_color() const {
return wuffs_base__frame_config__background_color(this);
@@ -3734,7 +3771,6 @@
wuffs_lzw__decoder f_lzw;
struct {
- uint8_t v_blend;
uint32_t v_background_color;
} s_decode_frame_config[1];
struct {
@@ -10055,7 +10091,6 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = wuffs_base__make_status(NULL);
- uint8_t v_blend = 0;
uint32_t v_background_color = 0;
uint8_t v_flags = 0;
@@ -10072,7 +10107,6 @@
uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
if (coro_susp_point) {
- v_blend = self->private_data.s_decode_frame_config[0].v_blend;
v_background_color =
self->private_data.s_decode_frame_config[0].v_background_color;
}
@@ -10125,10 +10159,8 @@
status = wuffs_base__make_status(wuffs_base__note__end_of_data);
goto ok;
}
- v_blend = 0;
v_background_color = self->private_impl.f_black_color_u32_argb_premul;
if (!self->private_impl.f_gc_has_transparent_index) {
- v_blend = 2;
v_background_color =
self->private_impl.f_background_color_u32_argb_premul;
if (self->private_impl
@@ -10158,8 +10190,10 @@
self->private_impl.f_height)),
((wuffs_base__flicks)(self->private_impl.f_gc_duration)),
self->private_impl.f_num_decoded_frame_configs_value,
- self->private_impl.f_frame_config_io_position, v_blend,
- self->private_impl.f_gc_disposal, v_background_color);
+ self->private_impl.f_frame_config_io_position,
+ self->private_impl.f_gc_disposal,
+ !self->private_impl.f_gc_has_transparent_index, false,
+ v_background_color);
}
wuffs_base__u64__sat_add_indirect(
&self->private_impl.f_num_decoded_frame_configs_value, 1);
@@ -10177,7 +10211,6 @@
wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
self->private_impl.active_coroutine =
wuffs_base__status__is_suspension(&status) ? 3 : 0;
- self->private_data.s_decode_frame_config[0].v_blend = v_blend;
self->private_data.s_decode_frame_config[0].v_background_color =
v_background_color;
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 5a442c3..a08c470 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -324,7 +324,6 @@
}
pub func decoder.decode_frame_config?(dst: nptr base.frame_config, src: base.io_reader) {
- var blend : base.u8
var background_color : base.u32
var flags : base.u8
@@ -348,10 +347,8 @@
return base."@end of data"
}
- blend = 0
background_color = this.black_color_u32_argb_premul
if not this.gc_has_transparent_index {
- blend = 2 // 2 is WUFFS_BASE__ANIMATION_BLEND__OPAQUE.
background_color = this.background_color_u32_argb_premul
// If the quirk is enabled and the first frame has a local color
@@ -385,8 +382,9 @@
duration: this.gc_duration,
index: this.num_decoded_frame_configs_value,
io_position: this.frame_config_io_position,
- blend: blend,
disposal: this.gc_disposal,
+ opaque_within_bounds: not this.gc_has_transparent_index,
+ overwrite_instead_of_blend: false,
background_color: background_color)
}