Add more pixel_buffer fill_rect cases
diff --git a/internal/cgen/base/pixconv-submodule.c b/internal/cgen/base/pixconv-submodule.c
index 72cf03e..30d1792 100644
--- a/internal/cgen/base/pixconv-submodule.c
+++ b/internal/cgen/base/pixconv-submodule.c
@@ -218,14 +218,75 @@
// --------
static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint16_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u16le__no_bounds_check(ptr, color);
+ ptr += 2;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (2 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u16le__no_bounds_check(ptr, color);
+ ptr += 2;
+ }
+ }
+}
+
+static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint32_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u24le__no_bounds_check(ptr, color);
+ ptr += 3;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (3 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u24le__no_bounds_check(ptr, color);
+ ptr += 3;
+ }
+ }
+}
+
+static inline void //
wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
wuffs_base__pixel_buffer* pb,
wuffs_base__rect_ie_u32 rect,
uint32_t color) {
size_t stride = pb->private_impl.planes[0].stride;
uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
- if (((stride & 3) == 0) && ((stride >> 2) == width) &&
- (rect.min_incl_x == 0)) {
+ if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
uint8_t* ptr =
pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
@@ -249,6 +310,37 @@
}
}
+static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint64_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u64le__no_bounds_check(ptr, color);
+ ptr += 8;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (8 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u64le__no_bounds_check(ptr, color);
+ ptr += 8;
+ }
+ }
+}
+
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_base__pixel_buffer__set_color_u32_fill_rect(
wuffs_base__pixel_buffer* pb,
@@ -271,6 +363,23 @@
}
switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
+ return wuffs_base__make_status(NULL);
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
+ return wuffs_base__make_status(NULL);
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color);
+ return wuffs_base__make_status(NULL);
+
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
pb, rect,
@@ -278,12 +387,25 @@
color));
return wuffs_base__make_status(NULL);
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
+ color));
return wuffs_base__make_status(NULL);
- // TODO: fast paths for other formats.
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ wuffs_base__swap_u32_argb_abgr(color)));
+ return wuffs_base__make_status(NULL);
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
+ pb, rect, wuffs_base__swap_u32_argb_abgr(color));
+ return wuffs_base__make_status(NULL);
}
uint32_t y;
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index a617b6b..1143893 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -559,9 +559,13 @@
"alette(pb),\n pb->pixcfg.private_impl.pixfmt, color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n wuffs_base__poke_u16le__no_bounds_check(\n row + (2 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n wuffs_base__poke_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n wuffs_base__poke_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:\n wuffs_base__poke_u64le__no_bounds_check(\n row + (8 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(\n color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n wuffs_base__poke_u24le__no_bounds_c" +
"heck(\n row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n wuffs_base__poke_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n wuffs_base__swap_u32_argb_abgr(color)));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n wuffs_base__poke_u32le__no_bounds_check(\n row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n\n default:\n // TODO: support more formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n return wuffs_base__make_status(NULL);\n}\n\n" +
"" +
- "// --------\n\nstatic inline void //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n uint32_t color) {\n size_t stride = pb->private_impl.planes[0].stride;\n uint32_t width = wuffs_base__rect_ie_u32__width(&rect);\n if (((stride & 3) == 0) && ((stride >> 2) == width) &&\n (rect.min_incl_x == 0)) {\n uint8_t* ptr =\n pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));\n uint32_t height = wuffs_base__rect_ie_u32__height(&rect);\n size_t n;\n for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {\n wuffs_base__poke_u32le__no_bounds_check(ptr, color);\n ptr += 4;\n }\n return;\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +\n (4 * ((size_t)rect.min_incl_x));\n uint32_t n;\n for (n = width; n > 0; n--) {\n wuffs_base__poke_u32le__no_bounds_check(ptr, color)" +
- ";\n ptr += 4;\n }\n }\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__status //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n wuffs_base__color_u32_argb_premul color) {\n if (!pb) {\n return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) {\n return wuffs_base__make_status(NULL);\n }\n wuffs_base__rect_ie_u32 bounds =\n wuffs_base__pixel_config__bounds(&pb->pixcfg);\n if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) {\n return wuffs_base__make_status(wuffs_base__error__bad_argument);\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n " +
- "pb, rect,\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n color));\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);\n return wuffs_base__make_status(NULL);\n\n // TODO: fast paths for other formats.\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint32_t x;\n for (x = rect.min_incl_x; x < rect.max_excl_x; x++) {\n wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color);\n }\n }\n return wuffs_base__make_status(NULL);\n}\n\n" +
+ "// --------\n\nstatic inline void //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n uint16_t color) {\n size_t stride = pb->private_impl.planes[0].stride;\n uint32_t width = wuffs_base__rect_ie_u32__width(&rect);\n if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {\n uint8_t* ptr =\n pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));\n uint32_t height = wuffs_base__rect_ie_u32__height(&rect);\n size_t n;\n for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {\n wuffs_base__poke_u16le__no_bounds_check(ptr, color);\n ptr += 2;\n }\n return;\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +\n (2 * ((size_t)rect.min_incl_x));\n uint32_t n;\n for (n = width; n > 0; n--) {\n wuffs_base__poke_u16le__no_bounds_check(ptr, color);\n ptr += 2;\n " +
+ " }\n }\n}\n\nstatic inline void //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n uint32_t color) {\n size_t stride = pb->private_impl.planes[0].stride;\n uint32_t width = wuffs_base__rect_ie_u32__width(&rect);\n if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {\n uint8_t* ptr =\n pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));\n uint32_t height = wuffs_base__rect_ie_u32__height(&rect);\n size_t n;\n for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {\n wuffs_base__poke_u24le__no_bounds_check(ptr, color);\n ptr += 3;\n }\n return;\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +\n (3 * ((size_t)rect.min_incl_x));\n uint32_t n;\n for (n = width; n > 0; n--) {\n wuffs_base__poke_u24le__no_bounds_check(ptr, color);\n ptr += 3;\n " +
+ " }\n }\n}\n\nstatic inline void //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n uint32_t color) {\n size_t stride = pb->private_impl.planes[0].stride;\n uint32_t width = wuffs_base__rect_ie_u32__width(&rect);\n if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {\n uint8_t* ptr =\n pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));\n uint32_t height = wuffs_base__rect_ie_u32__height(&rect);\n size_t n;\n for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {\n wuffs_base__poke_u32le__no_bounds_check(ptr, color);\n ptr += 4;\n }\n return;\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +\n (4 * ((size_t)rect.min_incl_x));\n uint32_t n;\n for (n = width; n > 0; n--) {\n wuffs_base__poke_u32le__no_bounds_check(ptr, color);\n ptr += 4;\n " +
+ " }\n }\n}\n\nstatic inline void //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n uint64_t color) {\n size_t stride = pb->private_impl.planes[0].stride;\n uint32_t width = wuffs_base__rect_ie_u32__width(&rect);\n if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {\n uint8_t* ptr =\n pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));\n uint32_t height = wuffs_base__rect_ie_u32__height(&rect);\n size_t n;\n for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {\n wuffs_base__poke_u64le__no_bounds_check(ptr, color);\n ptr += 8;\n }\n return;\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +\n (8 * ((size_t)rect.min_incl_x));\n uint32_t n;\n for (n = width; n > 0; n--) {\n wuffs_base__poke_u64le__no_bounds_check(ptr, color);\n ptr += 8;" +
+ "\n }\n }\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__status //\nwuffs_base__pixel_buffer__set_color_u32_fill_rect(\n wuffs_base__pixel_buffer* pb,\n wuffs_base__rect_ie_u32 rect,\n wuffs_base__color_u32_argb_premul color) {\n if (!pb) {\n return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) {\n return wuffs_base__make_status(NULL);\n }\n wuffs_base__rect_ie_u32 bounds =\n wuffs_base__pixel_config__bounds(&pb->pixcfg);\n if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) {\n return wuffs_base__make_status(wuffs_base__error__bad_argument);\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n wuffs_base__pixel_buffer__set_color_u32_fill_r" +
+ "ect__xxxx(pb, rect, color);\n return wuffs_base__make_status(NULL);\n\n // Common formats above. Rarer formats below.\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(\n pb, rect,\n wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color);\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n pb, rect,\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n color));\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(\n pb, rect,\n wuffs_base__color_u32_argb_premul__as__color_u64_argb_no" +
+ "npremul(\n color));\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n pb, rect,\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n wuffs_base__swap_u32_argb_abgr(color)));\n return wuffs_base__make_status(NULL);\n\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(\n pb, rect, wuffs_base__swap_u32_argb_abgr(color));\n return wuffs_base__make_status(NULL);\n }\n\n uint32_t y;\n for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {\n uint32_t x;\n for (x = rect.min_incl_x; x < rect.max_excl_x; x++) {\n wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color);\n }\n }\n return wuffs_base__make_status(NULL);\n}\n\n" +
"" +
"// --------\n\nWUFFS_BASE__MAYBE_STATIC uint8_t //\nwuffs_base__pixel_palette__closest_element(\n wuffs_base__slice_u8 palette_slice,\n wuffs_base__pixel_format palette_format,\n wuffs_base__color_u32_argb_premul c) {\n size_t n = palette_slice.len / 4;\n if (n > 256) {\n n = 256;\n }\n size_t best_index = 0;\n uint64_t best_score = 0xFFFFFFFFFFFFFFFF;\n\n // Work in 16-bit color.\n uint32_t ca = 0x101 * (0xFF & (c >> 24));\n uint32_t cr = 0x101 * (0xFF & (c >> 16));\n uint32_t cg = 0x101 * (0xFF & (c >> 8));\n uint32_t cb = 0x101 * (0xFF & (c >> 0));\n\n switch (palette_format.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {\n bool nonpremul = palette_format.repr ==\n WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;\n\n size_t i;\n for (i = 0; i < n; i++) {\n // Work in 16-bit color.\n uint32_t pb = 0x101 * ((uint32_t)(palette" +
"_slice.ptr[(4 * i) + 0]));\n uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));\n uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));\n uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));\n\n // Convert to premultiplied alpha.\n if (nonpremul && (pa != 0xFFFF)) {\n pb = (pb * pa) / 0xFFFF;\n pg = (pg * pa) / 0xFFFF;\n pr = (pr * pa) / 0xFFFF;\n }\n\n // These deltas are conceptually int32_t (signed) but after squaring,\n // it's equivalent to work in uint32_t (unsigned).\n pb -= cb;\n pg -= cg;\n pr -= cr;\n pa -= ca;\n uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +\n ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));\n if (best_score > score) {\n best_score = score;\n best_index = i;\n }\n }\n break;\n }\n }\n\n return (uint8_t)best_index;\n}\n\n" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 604f212..d548daa 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -14924,14 +14924,75 @@
// --------
static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint16_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u16le__no_bounds_check(ptr, color);
+ ptr += 2;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (2 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u16le__no_bounds_check(ptr, color);
+ ptr += 2;
+ }
+ }
+}
+
+static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint32_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u24le__no_bounds_check(ptr, color);
+ ptr += 3;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (3 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u24le__no_bounds_check(ptr, color);
+ ptr += 3;
+ }
+ }
+}
+
+static inline void //
wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
wuffs_base__pixel_buffer* pb,
wuffs_base__rect_ie_u32 rect,
uint32_t color) {
size_t stride = pb->private_impl.planes[0].stride;
uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
- if (((stride & 3) == 0) && ((stride >> 2) == width) &&
- (rect.min_incl_x == 0)) {
+ if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
uint8_t* ptr =
pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
@@ -14955,6 +15016,37 @@
}
}
+static inline void //
+wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
+ wuffs_base__pixel_buffer* pb,
+ wuffs_base__rect_ie_u32 rect,
+ uint64_t color) {
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
+ if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
+ uint8_t* ptr =
+ pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
+ uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
+ size_t n;
+ for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
+ wuffs_base__poke_u64le__no_bounds_check(ptr, color);
+ ptr += 8;
+ }
+ return;
+ }
+
+ uint32_t y;
+ for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
+ uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
+ (8 * ((size_t)rect.min_incl_x));
+ uint32_t n;
+ for (n = width; n > 0; n--) {
+ wuffs_base__poke_u64le__no_bounds_check(ptr, color);
+ ptr += 8;
+ }
+ }
+}
+
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_base__pixel_buffer__set_color_u32_fill_rect(
wuffs_base__pixel_buffer* pb,
@@ -14977,6 +15069,23 @@
}
switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
+ return wuffs_base__make_status(NULL);
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
+ return wuffs_base__make_status(NULL);
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color);
+ return wuffs_base__make_status(NULL);
+
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
pb, rect,
@@ -14984,12 +15093,25 @@
color));
return wuffs_base__make_status(NULL);
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
+ color));
return wuffs_base__make_status(NULL);
- // TODO: fast paths for other formats.
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
+ pb, rect,
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ wuffs_base__swap_u32_argb_abgr(color)));
+ return wuffs_base__make_status(NULL);
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
+ pb, rect, wuffs_base__swap_u32_argb_abgr(color));
+ return wuffs_base__make_status(NULL);
}
uint32_t y;
diff --git a/test/c/std/wbmp.c b/test/c/std/wbmp.c
index 332bc6c..b0e3059 100644
--- a/test/c/std/wbmp.c
+++ b/test/c/std/wbmp.c
@@ -117,6 +117,103 @@
}
const char* //
+test_wuffs_pixel_buffer_fill_rect() {
+ CHECK_FOCUS(__func__);
+
+ const uint32_t width = 5;
+ const uint32_t height = 5;
+
+ const struct {
+ wuffs_base__color_u32_argb_premul color;
+ uint32_t pixfmt_repr;
+ } dsts[] = {
+ {
+ .color = 0xFF000010,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGR_565,
+ },
+ {
+ .color = 0xFF000040,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGR,
+ },
+ {
+ .color = 0x88000048,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL,
+ },
+ {
+ .color = 0x88000048,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE,
+ },
+ {
+ .color = 0x88000048,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
+ },
+ {
+ .color = 0xFF000040,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRX,
+ },
+ {
+ .color = 0x88000048,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL,
+ },
+ {
+ .color = 0x88000048,
+ .pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
+ },
+ };
+
+ int d;
+ for (d = 0; d < WUFFS_TESTLIB_ARRAY_SIZE(dsts); d++) {
+ // Allocate the dst_pixbuf.
+ wuffs_base__pixel_config dst_pixcfg = ((wuffs_base__pixel_config){});
+ wuffs_base__pixel_config__set(&dst_pixcfg, dsts[d].pixfmt_repr,
+ WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, width,
+ height);
+ wuffs_base__pixel_buffer dst_pixbuf = ((wuffs_base__pixel_buffer){});
+ CHECK_STATUS("set_from_slice",
+ wuffs_base__pixel_buffer__set_from_slice(
+ &dst_pixbuf, &dst_pixcfg, g_have_slice_u8));
+
+ int orientation;
+ for (orientation = 0; orientation < 2; orientation++) {
+ // Reset to transparent black (or its closest approximation).
+ uint32_t y;
+ for (y = 0; y < height; y++) {
+ uint32_t x;
+ for (x = 0; x < width; x++) {
+ CHECK_STATUS(
+ "set_color_u32_at",
+ wuffs_base__pixel_buffer__set_color_u32_at(&dst_pixbuf, x, y, 0));
+ }
+ }
+
+ // Fill a rectangle:
+ // - orientation == 0 means 1 pixel wide.
+ // - orientation == 1 means 1 pixel high.
+ wuffs_base__rect_ie_u32 rect =
+ orientation ? wuffs_base__make_rect_ie_u32(0, height / 2, width,
+ 1 + (height / 2))
+ : wuffs_base__make_rect_ie_u32(width / 2, 0,
+ 1 + (width / 2), height);
+ CHECK_STATUS("set_color_u32_fill_rect",
+ wuffs_base__pixel_buffer__set_color_u32_fill_rect(
+ &dst_pixbuf, rect, dsts[d].color));
+
+ // Check the middle dst pixel.
+ wuffs_base__color_u32_argb_premul want_dst_pixel = dsts[d].color;
+ wuffs_base__color_u32_argb_premul have_dst_pixel =
+ wuffs_base__pixel_buffer__color_u32_at(&dst_pixbuf, width / 2,
+ height / 2);
+ if (colors_differ(have_dst_pixel, want_dst_pixel, 0)) {
+ RETURN_FAIL("d=%d, orientation=%d: dst_pixel: have 0x%08" PRIX32
+ ", want 0x%08" PRIX32,
+ d, orientation, have_dst_pixel, want_dst_pixel);
+ }
+ }
+ }
+ return NULL;
+}
+
+const char* //
test_wuffs_pixel_swizzler_swizzle() {
CHECK_FOCUS(__func__);
@@ -126,69 +223,69 @@
wuffs_base__pixel_swizzler swizzler;
const struct {
- wuffs_base__color_u32_argb_premul pixel;
+ wuffs_base__color_u32_argb_premul color;
uint32_t pixfmt_repr;
} srcs[] = {
{
- .pixel = 0xFF444444,
+ .color = 0xFF444444,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__Y,
},
{
- .pixel = 0xFF444444,
+ .color = 0xFF444444,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__Y_16BE,
},
{
- .pixel = 0x55443300,
+ .color = 0x55443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL,
},
{
- .pixel = 0xFF444444,
+ .color = 0xFF444444,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY,
},
{
- .pixel = 0xFF443300,
+ .color = 0xFF443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGR,
},
{
- .pixel = 0x55443300,
+ .color = 0x55443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL,
},
{
- .pixel = 0x55443300,
+ .color = 0x55443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE,
},
{
- .pixel = 0xFF443300,
+ .color = 0xFF443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRX,
},
{
- .pixel = 0xFF443300,
+ .color = 0xFF443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__RGB,
},
{
- .pixel = 0x55443300,
+ .color = 0x55443300,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL,
},
};
const struct {
- wuffs_base__color_u32_argb_premul pixel;
+ wuffs_base__color_u32_argb_premul color;
uint32_t pixfmt_repr;
} dsts[] = {
{
- .pixel = 0xFF000010,
+ .color = 0xFF000010,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGR_565,
},
{
- .pixel = 0xFF000040,
+ .color = 0xFF000040,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGR,
},
{
- .pixel = 0x80000040,
+ .color = 0x80000040,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL,
},
{
- .pixel = 0x80000040,
+ .color = 0x80000040,
.pixfmt_repr = WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
},
};
@@ -219,13 +316,13 @@
// Set and check the middle src pixel.
CHECK_STATUS("set_color_u32_at",
wuffs_base__pixel_buffer__set_color_u32_at(
- &src_pixbuf, width / 2, height / 2, srcs[s].pixel));
+ &src_pixbuf, width / 2, height / 2, srcs[s].color));
wuffs_base__color_u32_argb_premul have_src_pixel =
wuffs_base__pixel_buffer__color_u32_at(&src_pixbuf, width / 2,
height / 2);
- if (have_src_pixel != srcs[s].pixel) {
+ if (have_src_pixel != srcs[s].color) {
RETURN_FAIL("s=%d: src_pixel: have 0x%08" PRIX32 ", want 0x%08" PRIX32, s,
- have_src_pixel, srcs[s].pixel);
+ have_src_pixel, srcs[s].color);
}
int d;
@@ -257,7 +354,7 @@
// Set the middle dst pixel.
CHECK_STATUS("set_color_u32_at",
wuffs_base__pixel_buffer__set_color_u32_at(
- &dst_pixbuf, width / 2, height / 2, dsts[d].pixel));
+ &dst_pixbuf, width / 2, height / 2, dsts[d].color));
// Swizzle.
CHECK_STATUS(
@@ -279,11 +376,11 @@
(dsts[d].pixfmt_repr == WUFFS_BASE__PIXEL_FORMAT__BGR_565) ? 4 : 0;
wuffs_base__color_u32_argb_premul want_dst_pixel = 0;
if (blends[b] == WUFFS_BASE__PIXEL_BLEND__SRC) {
- want_dst_pixel = srcs[s].pixel;
+ want_dst_pixel = srcs[s].color;
} else if (blends[b] == WUFFS_BASE__PIXEL_BLEND__SRC_OVER) {
tolerance += 1;
want_dst_pixel = wuffs_base__composite_premul_premul_u32_axxx(
- dsts[d].pixel, srcs[s].pixel);
+ dsts[d].color, srcs[s].color);
} else {
return "unsupported blend";
}
@@ -529,9 +626,10 @@
proc g_tests[] = {
- // These pixel_swizzler tests are really testing the Wuffs base library.
- // They aren't specific to the std/wbmp code, but putting them here is as
- // good as any other place.
+ // These pixel_buffer / pixel_swizzler tests are really testing the Wuffs
+ // base library. They aren't specific to the std/wbmp code, but putting
+ // them here is as good as any other place.
+ test_wuffs_pixel_buffer_fill_rect,
test_wuffs_pixel_swizzler_swizzle,
test_wuffs_wbmp_decode_frame_config,