From 3ae84de12348ecafd096de8f1ef61be03b7f021b Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 2 Jun 2026 17:27:41 +0200 Subject: [PATCH] Expose paint blend references in CLI --- docs/modernization/build-inventory.md | 3 ++ docs/modernization/roadmap.md | 2 + tests/CMakeLists.txt | 6 +++ tools/pano_cli/main.cpp | 63 +++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 2715567..1deec0f 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -149,6 +149,9 @@ Known local toolchain state: - `pano_cli simulate-image-import` decodes an embedded tiny PNG through `pp_assets`, attaches it to `pp_document`, and is covered by `pano_cli_simulate_image_import_smoke`. +- `pano_cli simulate-blend` exposes deterministic final RGBA and stroke-alpha + blend reference vectors through JSON automation and is covered by + `pano_cli_simulate_blend_smoke`. - `pano_cli simulate-stroke` exposes the pure stroke sampler for scripted automation and is covered by `pano_cli_simulate_stroke_smoke`. - `pano_cli simulate-stroke-script` loads a text stroke script fixture and is diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index ad09c98..7830532 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -369,6 +369,8 @@ through `pp_assets` and attaches the resulting RGBA8 payload to `pp_document`. asset-level PPI image decode, and document reimport in one automation command. `pano_cli save-document-project` writes a deterministic pure document export PPI and verifies it through inspect/load smoke coverage. +`pano_cli simulate-blend` exposes deterministic final RGBA and stroke-alpha +blend reference vectors through JSON automation. `pano_cli simulate-stroke` exercises the pure stroke sampler for scripted-stroke automation. `pano_cli simulate-stroke-script` loads stroke script fixtures, parses them through `pp_paint`, and samples every diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 82325d1..0c14bbe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -399,6 +399,12 @@ if(TARGET pano_cli) LABELS "assets;document;integration;desktop-fast" PASS_REGULAR_EXPRESSION "\"command\":\"simulate-image-import\".*\"image\":\\{\"format\":\"png\",\"width\":1,\"height\":1,\"bytes\":4,\"alpha\":0\\}.*\"document\":\\{\"width\":64,\"height\":32,\"layers\":1,\"frames\":1,\"facePayloads\":1\\}.*\"payload\":\\{\"face\":0,\"x\":0,\"y\":0,\"width\":1,\"height\":1,\"bytes\":4\\}") + add_test(NAME pano_cli_simulate_blend_smoke + COMMAND pano_cli simulate-blend) + set_tests_properties(pano_cli_simulate_blend_smoke PROPERTIES + LABELS "paint;integration;desktop-fast" + PASS_REGULAR_EXPRESSION "\"command\":\"simulate-blend\".*\"finalBlendModes\":5.*\"strokeBlendModes\":11.*\"normal\":\\{\"r\":0.44,\"g\":0.32,\"b\":0.4,\"a\":0.625\\}.*\"multiply\":\\{\"r\":0.125,\"g\":0.25,\"b\":0.375,\"a\":1\\}.*\"stroke\":\\{\"normal\":0.35,\"linearHeight\":0.637171,\"height\":0.228217,\"unknown\":1\\}") + add_test(NAME pano_cli_simulate_stroke_smoke COMMAND pano_cli simulate-stroke --x1 0 --y1 0 --x2 10 --y2 0 --spacing 2) set_tests_properties(pano_cli_simulate_stroke_smoke PROPERTIES diff --git a/tools/pano_cli/main.cpp b/tools/pano_cli/main.cpp index aa17e16..5b946b0 100644 --- a/tools/pano_cli/main.cpp +++ b/tools/pano_cli/main.cpp @@ -7,6 +7,7 @@ #include "document/ppi_import.h" #include "foundation/parse.h" #include "foundation/result.h" +#include "paint/blend.h" #include "paint/stroke.h" #include "paint/stroke_script.h" #include "renderer_api/recording_renderer.h" @@ -240,6 +241,7 @@ void print_help() << " simulate-document-edits [--width N] [--height N]\n" << " simulate-document-export [--width N] [--height N]\n" << " simulate-document-history [--width N] [--height N] [--history N]\n" + << " simulate-blend\n" << " simulate-image-import [--width N] [--height N]\n" << " simulate-stroke --x1 N --y1 N --x2 N --y2 N [--spacing N]\n" << " simulate-stroke-script --path FILE\n" @@ -1365,6 +1367,63 @@ int simulate_stroke_script(int argc, char** argv) return 0; } +int simulate_blend(int argc, char**) +{ + if (argc > 2) { + print_error("simulate-blend", "unknown option"); + return 2; + } + + const auto normal = pp::paint::blend_pixels( + pp::paint::Rgba { .r = 0.2F, .g = 0.4F, .b = 0.6F, .a = 0.5F }, + pp::paint::Rgba { .r = 0.8F, .g = 0.2F, .b = 0.1F, .a = 0.25F }, + pp::paint::BlendMode::normal); + const auto multiply = pp::paint::blend_pixels( + pp::paint::Rgba { .r = 0.25F, .g = 0.5F, .b = 0.75F, .a = 1.0F }, + pp::paint::Rgba { .r = 0.5F, .g = 0.5F, .b = 0.5F, .a = 1.0F }, + pp::paint::BlendMode::multiply); + const auto stroke_normal = pp::paint::blend_stroke_alpha( + 0.2F, + 0.8F, + 0.25F, + pp::paint::StrokeBlendMode::normal); + const auto stroke_linear_height = pp::paint::blend_stroke_alpha( + 0.5F, + 0.25F, + 0.16F, + pp::paint::StrokeBlendMode::linear_height); + const auto stroke_height = pp::paint::blend_stroke_alpha( + 0.5F, + 0.25F, + 0.16F, + pp::paint::StrokeBlendMode::height); + const auto stroke_unknown = pp::paint::blend_stroke_alpha( + 0.2F, + 0.2F, + 0.5F, + static_cast(255)); + + std::cout << "{\"ok\":true,\"command\":\"simulate-blend\"" + << ",\"finalBlendModes\":5" + << ",\"strokeBlendModes\":11" + << ",\"normal\":{\"r\":" << normal.r + << ",\"g\":" << normal.g + << ",\"b\":" << normal.b + << ",\"a\":" << normal.a + << "}" + << ",\"multiply\":{\"r\":" << multiply.r + << ",\"g\":" << multiply.g + << ",\"b\":" << multiply.b + << ",\"a\":" << multiply.a + << "}" + << ",\"stroke\":{\"normal\":" << stroke_normal + << ",\"linearHeight\":" << stroke_linear_height + << ",\"height\":" << stroke_height + << ",\"unknown\":" << stroke_unknown + << "}}\n"; + return 0; +} + pp::foundation::Status parse_apply_stroke_script_args(int argc, char** argv, ApplyStrokeScriptArgs& args) { for (int i = 2; i < argc; ++i) { @@ -2814,6 +2873,10 @@ int main(int argc, char** argv) return simulate_stroke_script(argc, argv); } + if (command == "simulate-blend") { + return simulate_blend(argc, argv); + } + if (command == "apply-stroke-script") { return apply_stroke_script(argc, argv); }