29 procedural-texture inner loops in cli_gen_texture.cpp
open-coded the same 4-line "compute index, write 3 RGB
bytes" block:
size_t idx = (static_cast<size_t>(y) * W + x) * 3;
pixels[idx + 0] = r;
pixels[idx + 1] = g;
pixels[idx + 2] = b;
Hoist into cli_png_emit.hpp as inline setPixelRGB(pixels,
W, x, y, r, g, b). Header-inline because the procedural
handlers call this once per pixel — the abstraction must
not cost a function-call frame per write.
Each call site collapses to 1 line. cli_gen_texture.cpp
loses ~90 lines from inner-loop bodies. Output bytes
verified identical via PNG diff for moss / camo / snake-skin
— byte-for-byte the same files as previously generated.
(One frost-blend site keeps the open-coded form because
it does a read-modify-write alpha blend rather than a
pure write.)
parseHex was a static helper in cli_gen_texture.cpp. 81 sites
across the file each open-coded the same 6-line "if !parseHex
then fprintf 'X is not a valid hex color' and return 1" block.
Hoist parseHex into cli_png_emit.hpp as inline (header-only,
non-trivial but only called once per handler at startup so
inlining cost is negligible). Add inline parseHexOrError that
wraps it with the canonical error message.
Each call site collapses from 6 lines to 1:
if (!parseHexOrError(stoneHex, sr, sg, sb,
"gen-texture-cobble")) return 1;
Bonus: 29 compound-color sites that used a single
"one of the hex colors is invalid" message are split into
separate parseHexOrError calls per color — now the error
identifies WHICH color failed instead of just saying
"one of them".
cli_gen_texture.cpp drops by ~320 lines (4877 → 4557). Output
bytes verified identical for cobble / mosaic / stained-glass.
Error message contract improved: 'NOTHEX' now reports
"'NOTHEX' is not a valid hex color" everywhere instead of
the generic compound message.
58 procedural-texture handlers in cli_gen_texture.cpp ended
with the same 6-line stbi_write_png + error-handling block:
if (!stbi_write_png(outPath.c_str(), W, H, 3,
pixels.data(), W * 3)) {
std::fprintf(stderr,
"gen-texture-foo: stbi_write_png failed for %s\n",
outPath.c_str());
return 1;
}
Hoist into cli_png_emit.hpp as inline savePngOrError, used as
`if (!savePngOrError(outPath, W, H, pixels, "cmd")) return 1;`.
cli_gen_texture.cpp drops by ~118 lines. Output bytes verified
identical via diff: regenerating moss.png with same args
produces byte-for-byte the same file.
This is the texture-side counterpart to saveWomOrError in
cli_box_emitter.hpp — same write-check-fprintf pattern, same
1-line API.