Export captured canvas snapshots through document writer
This commit is contained in:
@@ -265,9 +265,12 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
|
||||
state toward `pp_document::CanvasDocument`, including dimensions, active
|
||||
layer/frame, layer visibility/opacity/alpha/blend metadata, frame durations,
|
||||
captured RGBA8 face payloads, and remaining renderer payload-readback counts,
|
||||
plus the save-readiness report now consumed before retained live saves, and
|
||||
is covered by `pano_cli_plan_canvas_document_snapshot_smoke` plus the
|
||||
payload-bearing snapshot smoke.
|
||||
plus the save-readiness report now consumed before retained live saves. For
|
||||
payload-complete or metadata-only snapshots, the same app-core boundary now
|
||||
exports through the pure `pp_document` PPI writer and reports generated byte
|
||||
counts plus decoded dirty-face counts in `ppiExport` JSON. It is covered by
|
||||
`pano_cli_plan_canvas_document_snapshot_smoke` plus the payload-bearing
|
||||
snapshot smoke.
|
||||
- `pano_cli save-document-project` writes that pure document export to a PPI
|
||||
file and is covered by `pano_cli_save_document_project_roundtrip_smoke`,
|
||||
which inspects and loads the generated file.
|
||||
@@ -1094,8 +1097,10 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
|
||||
cleanup. Existing Save, Save As, Save Version, and save-before-workflow
|
||||
prepare and log a payload-bearing canvas document snapshot report before
|
||||
delegating to retained `Canvas::project_save`. Retained legacy UI/canvas
|
||||
execution and actual save serialization remain tracked by `DEBT-0040`,
|
||||
`DEBT-0041`, and `DEBT-0042`.
|
||||
execution and actual live save serialization remain tracked by `DEBT-0040`,
|
||||
`DEBT-0041`, and `DEBT-0042`; the pure snapshot-to-PPI export handoff is
|
||||
already validated in `pp_app_core_document_canvas_tests` and
|
||||
`pano_cli_plan_canvas_document_snapshot_payload_smoke`.
|
||||
- `src/legacy_document_export_services.*` is the current app-shell bridge
|
||||
between `pp_app_core` document export execution plans and live equirectangular,
|
||||
layers, animation-frame, depth, and cube-face export calls. It preserves
|
||||
|
||||
@@ -11,7 +11,7 @@ and validation command.
|
||||
|
||||
| Capability | Current Area | Target Owner | Required Tests |
|
||||
| --- | --- | --- | --- |
|
||||
| PPI open/save | `Canvas`, serializer, dialogs | `pp_document`, `pp_assets`, `pano_cli` | Round-trip tiny project, old-version fixture, corrupt/truncated fixture, live-canvas-to-`pp_document` snapshot projection with captured RGBA8 payloads, pending renderer-readback counts, and save-readiness reporting before retained live saves |
|
||||
| PPI open/save | `Canvas`, serializer, dialogs | `pp_document`, `pp_assets`, `pano_cli` | Round-trip tiny project, old-version fixture, corrupt/truncated fixture, live-canvas-to-`pp_document` snapshot projection with captured RGBA8 payloads, pending renderer-readback counts, save-readiness reporting before retained live saves, and pure PPI export from payload-complete snapshots |
|
||||
| Open-document routing | `App::open_document` | `pp_app_core`, `pano_cli`, `pp_panopainter_ui`, `pp_document`, `pp_assets` | Project/ABR/PPBR route tests, malformed path tests, open-action plan tests, CLI route/action smoke, app open smoke |
|
||||
| Document session decisions | `App::open_document`, `App::request_close`, save hotkeys, file menu, dialogs | `pp_app_core`, `pano_cli`, `pp_panopainter_ui` | Clean/dirty/prompt-open/save/save-as/save-version/save-before-workflow/name/new-document resolution/overwrite/version-target decision tests, CLI session, new-document, document-file, and document-version smoke, app close/open/save/new/browse smoke |
|
||||
| Version metadata | `scripts/pre-build.py`, `version.*` | build system, `pp_foundation` | Generated header smoke test, missing-tag behavior |
|
||||
|
||||
@@ -479,6 +479,11 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
report before delegating to retained `Canvas::project_save`. The retained
|
||||
writer still owns PPI serialization, progress/threading, and compatibility
|
||||
quirks, so pure writer replacement remains open.
|
||||
- 2026-06-05: DEBT-0010/DEBT-0013 were narrowed again. `pp_app_core` now
|
||||
exports payload-complete or metadata-only canvas document snapshots through
|
||||
the pure `pp_document` PPI writer and rejects snapshots that still require
|
||||
renderer readback; `pano_cli plan-canvas-document-snapshot` reports
|
||||
`ppiExport` readiness, byte counts, and decoded dirty-face counts.
|
||||
|
||||
## Open Debt
|
||||
|
||||
@@ -492,10 +497,10 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
| DEBT-0007 | Open | Modernization | `vcpkg.json` and `windows-msvc-vcpkg-headless` are validated for the headless Windows component matrix, and root CMake now exposes a focused `panopainter_platform_build_vcpkg_ui_core` target for the vcpkg-backed `pp_ui_core`/tinyxml2 boundary, but app targets still use vendored libraries and Android/Apple triplets are not proven | Dependency migration must stay incremental while SDK/patched/vendor dependencies remain in use | `cmake --preset windows-msvc-vcpkg-headless`; `ctest --preset desktop-fast-vcpkg --build-config Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_vcpkg_ui_core` | Component targets consume vcpkg packages where reliable and desktop app, Android, and Apple triplets are validated or explicitly documented as permanent vendor exceptions |
|
||||
| DEBT-0008 | Open | Modernization | `windows-msvc-default` and `windows-msvc-vcpkg-headless` explicitly select Visual Studio 18 2026 for local validation, but non-VS2026 CMake executables on PATH may not know that generator | The local machine has VS 2026, but using an older CMake can still default to Ninja or reject the VS 2026 generator | `cmake --preset windows-msvc-default`; `cmake --build --preset windows-msvc-default --config Debug --target PanoPainter`; `ctest --preset desktop-fast --build-config Debug` | The repo automation invokes or locates a CMake executable that supports `Visual Studio 18 2026`, and VS 2026 generator validation is the normal Windows path without manual tool selection |
|
||||
| DEBT-0009 | Open | Modernization | Android root CMake validation currently builds headless targets only, while retained standard/Quest/Focus package CMake paths now have a refreshed CMake 3.10/C++23 baseline outside root CMake; automation queries `sdkmanager`, installs newer or missing SDK Manager NDK/CMake packages, selects the resulting pair before configure, and reports update decisions; root CMake exposes non-default platform-build and retained native package validation targets | Platform app entrypoints still live in legacy Gradle/CMake projects and need Phase 6 alignment | `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64`; `cmake --build --preset android-x64`; `cmake --build --preset android-quest-arm64`; `cmake --build --preset android-focus-arm64`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_android_assets`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages quest,focus -ConfigureOnly`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke` | Android standard, Quest, and Focus/Wave package targets consume shared component targets and have package smoke commands |
|
||||
| DEBT-0010 | Open | Modernization | `pp_document` is a pure layer/frame/document/undo-history model with alpha-lock metadata, snapshot construction, per-layer frame metadata, renderer-free RGBA8 face payload storage, snapshot-embedded face-payload validation, renderer-free alpha8 selection-mask storage, PPI import/export helpers, stroke-script-to-face-payload CLI automation, `pp_paint_renderer` document face/frame compositors, renderer-neutral six-face texture upload, OpenGL command-planner validation through CLI render automation, live Canvas snapshot projection through `pp_app_core`/`legacy_document_canvas_services`, captured RGBA8 payload attachment to `pp_document`, and live Save/Save As/Save Version/save-before-workflow snapshot-readiness reporting before retained save execution, but export/action-command adoption, pure save-writer replacement, and renderer-owned cube-face readback ownership are not yet wired | Keep extraction incremental while preserving app behavior | `ctest --preset desktop-fast --build-config Debug`; `pano_cli create-document --width 64 --height 32 --layers 2`; `pano_cli load-project --path tests\data\projects\minimal-project.ppi`; `pano_cli simulate-document-render --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --captured-face-payloads-per-layer 1`; `pp_document_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pp_paint_renderer_compositor_tests`; `pp_app_core_document_canvas_tests`; `pano_cli_simulate_document_edits_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_simulate_document_render_smoke`; `pano_cli_plan_canvas_document_snapshot_smoke`; `pano_cli_plan_canvas_document_snapshot_payload_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Legacy document behavior is represented by `pp_document`/`pp_paint_renderer` tests and the app consumes it through a boundary/facade |
|
||||
| DEBT-0010 | Open | Modernization | `pp_document` is a pure layer/frame/document/undo-history model with alpha-lock metadata, snapshot construction, per-layer frame metadata, renderer-free RGBA8 face payload storage, snapshot-embedded face-payload validation, renderer-free alpha8 selection-mask storage, PPI import/export helpers, stroke-script-to-face-payload CLI automation, `pp_paint_renderer` document face/frame compositors, renderer-neutral six-face texture upload, OpenGL command-planner validation through CLI render automation, live Canvas snapshot projection through `pp_app_core`/`legacy_document_canvas_services`, captured RGBA8 payload attachment to `pp_document`, live Save/Save As/Save Version/save-before-workflow snapshot-readiness reporting before retained save execution, and pure app-core PPI export for payload-complete canvas snapshots, but export/action-command adoption, live save-writer replacement, and renderer-owned cube-face readback ownership are not yet wired | Keep extraction incremental while preserving app behavior | `ctest --preset desktop-fast --build-config Debug`; `pano_cli create-document --width 64 --height 32 --layers 2`; `pano_cli load-project --path tests\data\projects\minimal-project.ppi`; `pano_cli simulate-document-render --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --captured-face-payloads-per-layer 1`; `pp_document_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pp_paint_renderer_compositor_tests`; `pp_app_core_document_canvas_tests`; `pano_cli_simulate_document_edits_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_simulate_document_render_smoke`; `pano_cli_plan_canvas_document_snapshot_smoke`; `pano_cli_plan_canvas_document_snapshot_payload_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Legacy document behavior is represented by `pp_document`/`pp_paint_renderer` tests and the app consumes it through a boundary/facade |
|
||||
| DEBT-0011 | Open | Modernization | `package-smoke` validates the Windows CMake app artifact and launch-folder DLL payload, and reports a structured package readiness matrix for Windows AppX, Android standard/Quest/Focus APKs, Apple bundles, Linux app output, and WebGL output; the Windows app smoke passes the configure-time CMake executable so VS 2026 generator validation does not depend on `cmake` from PATH, retained Android package native CMake paths, and retained Linux/WebGL CMake baseline metadata are reachable from package validation and root CMake package-readiness targets, but Windows AppX/APK/Linux/Apple/WebGL package outputs are still `blocked` because root CMake package targets do not exist yet | Platform package targets are not migrated to root CMake yet | `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_app_package_smoke`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_linux_webgl_package_readiness`; `python scripts/dev/check_package_smoke_readiness.py`; `bash -n scripts/automation/package-smoke.sh` | Package-smoke builds and validates Windows AppX, Android APK variants, Linux app, Apple bundles, and WebGL output where local toolchains are present |
|
||||
| DEBT-0012 | Open | Modernization | `pp_ui_core` uses vcpkg tinyxml2 on `windows-msvc-vcpkg-headless`, but retains `pp_vendor_tinyxml2` for default and unproven platform presets | Mobile/AppX/Apple triplets and app packaging still need validation before removing the vendored fallback | `ctest --preset desktop-fast-vcpkg --build-config Debug`; `ctest --preset desktop-fast --build-config Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64` | All supported presets consume vcpkg tinyxml2 or document a permanent vendored exception |
|
||||
| DEBT-0013 | Open | Modernization | `pp_assets`, `pp_document`, `pano_cli inspect-project`, `pano_cli load-project`, and `pano_cli save-project` validate the fixed PPI header, thumbnail/body byte layout, generated multi-layer/multi-frame PPI writing with explicit layer opacity/blend/alpha-lock/visibility metadata, per-layer frame durations, metadata-only and targeted dirty-face-payload save/load round-trips, layer/frame index, dirty-face descriptors, dirty-face PNG payload metadata, asset-level RGBA PNG payload decoding, pure document-to-PPI export, CLI document export automation, file-writing document export automation, stroke-script-generated document payload export, decoded pixel attachment to `pp_document`, and live save-path snapshot-readiness reporting, but full legacy PPI round-trip parity and pure live save writer replacement are not yet extracted | Full PPI save parity requires staged extraction of legacy `Canvas` serialization and image/layer payload handling | `ctest --preset desktop-fast --build-config Debug`; `pp_assets_image_pixels_tests`; `pp_assets_ppi_header_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_inspect_project_layout_smoke`; `pano_cli_load_project_metadata_smoke`; `pano_cli_save_project_roundtrip_smoke`; `pano_cli_save_project_payload_roundtrip_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Full PPI load/save fixtures cover thumbnails, decoded layer face payloads attached to documents, frames, corrupt payloads, dirty-face payload saving, arbitrary legacy canvas payload/layout combinations, and legacy app round-trip compatibility |
|
||||
| DEBT-0013 | Open | Modernization | `pp_assets`, `pp_document`, `pano_cli inspect-project`, `pano_cli load-project`, and `pano_cli save-project` validate the fixed PPI header, thumbnail/body byte layout, generated multi-layer/multi-frame PPI writing with explicit layer opacity/blend/alpha-lock/visibility metadata, per-layer frame durations, metadata-only and targeted dirty-face-payload save/load round-trips, layer/frame index, dirty-face descriptors, dirty-face PNG payload metadata, asset-level RGBA PNG payload decoding, pure document-to-PPI export, CLI document export automation, file-writing document export automation, stroke-script-generated document payload export, decoded pixel attachment to `pp_document`, live save-path snapshot-readiness reporting, and app-core canvas-snapshot-to-PPI export automation, but full legacy PPI round-trip parity and pure live save writer replacement are not yet extracted | Full PPI save parity requires staged extraction of legacy `Canvas` serialization and image/layer payload handling | `ctest --preset desktop-fast --build-config Debug`; `pp_assets_image_pixels_tests`; `pp_assets_ppi_header_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_inspect_project_layout_smoke`; `pano_cli_load_project_metadata_smoke`; `pano_cli_save_project_roundtrip_smoke`; `pano_cli_save_project_payload_roundtrip_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Full PPI load/save fixtures cover thumbnails, decoded layer face payloads attached to documents, frames, corrupt payloads, dirty-face payload saving, arbitrary legacy canvas payload/layout combinations, and legacy app round-trip compatibility |
|
||||
| DEBT-0014 | Open | Modernization | `windows-clangcl-asan` now configures as a headless Ninja/clang-cl preset and uses the release MSVC runtime required by ASan, but local builds still fail because installed clang-cl 18.1.8 is paired with VS 2026-preview STL headers that require Clang 20 or newer | Sanitizer validation should be local and repeatable, but this machine's compiler/header pairing is incompatible | `cmake --fresh --preset windows-clangcl-asan`; `cmake --build --preset windows-clangcl-asan --target pp_foundation` | Install/use Clang 20+ with the VS 2026 STL, or point the preset at a compatible VS 2022 toolchain, then make `platform-build.ps1 -Presets windows-clangcl-asan` pass for the headless matrix |
|
||||
| DEBT-0015 | Open | Modernization | Cursor visibility requests now consume pure `pp_app_core` planning through `pano_cli plan-cursor-visibility`, `App::show_cursor`/`App::hide_cursor` dispatch through `PlatformServices` without platform guards, and Windows live execution uses injected `WindowsPlatformServices`, but macOS cursor execution still reaches the retained fallback adapter | Keep canvas cursor behavior stable while platform shells are extracted incrementally | `pp_app_core_document_platform_io_tests`; `pano_cli plan-cursor-visibility --visible`; `ctest --preset desktop-fast --build-config Debug` | Cursor visibility execution is owned by injected `pp_platform_*` services for every supported platform |
|
||||
| DEBT-0016 | Open | Modernization | Clipboard get/set requests now consume pure `pp_app_core` planning through `pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write`, and Windows live execution uses injected `WindowsPlatformServices`, but Apple/Android clipboard execution still reaches retained fallback adapter branches from `App::clipboard_get_text` and `App::clipboard_set_text` | Keep picker/color text clipboard behavior stable while platform shells are extracted incrementally | `pp_app_core_document_platform_io_tests`; `pano_cli plan-clipboard-write --text #ff00aa`; `ctest --preset desktop-fast --build-config Debug` | Clipboard execution is owned by injected `pp_platform_*` services for every supported platform |
|
||||
|
||||
@@ -671,8 +671,11 @@ now builds the same metadata snapshot from live `Canvas` state and has an
|
||||
opt-in dirty-face payload snapshot path backed by retained `Layer::snapshot()`
|
||||
readback. Live Save, Save As, Save Version, and save-before-workflow paths now
|
||||
prepare and log a payload-completeness report from that snapshot before
|
||||
delegating to retained `Canvas::project_save`; pure PPI writer replacement,
|
||||
export adoption, and renderer-owned readback remain under
|
||||
delegating to retained `Canvas::project_save`; the app-core snapshot boundary
|
||||
also has a tested pure PPI export helper, and
|
||||
`pano_cli plan-canvas-document-snapshot` runs that helper for payload-complete
|
||||
snapshots and reports generated byte/dirty-face summaries. Live save writer
|
||||
replacement, export adoption, and renderer-owned readback remain under
|
||||
`DEBT-0010`/`DEBT-0013`/`DEBT-0036`.
|
||||
`pano_cli plan-image-import` exposes app-core planning for File > Import image
|
||||
route decisions, including wide equirectangular images, legacy vertical cube
|
||||
@@ -2213,7 +2216,9 @@ Results:
|
||||
retained `Canvas::project_save` writer, keeping behavior stable while moving
|
||||
the app path onto the document/canvas boundary.
|
||||
- `pano_cli plan-canvas-document-snapshot` now emits the same save-readiness
|
||||
report (`payloadComplete` and `canExportPpi`) used by the live save bridge.
|
||||
report (`payloadComplete` and `canExportPpi`) used by the live save bridge,
|
||||
and payload-complete snapshots now run the pure `pp_document` PPI exporter
|
||||
and decoded-project summary before emitting `ppiExport` JSON.
|
||||
- `pp_app_core_document_import_tests` passed, covering wide equirectangular,
|
||||
legacy vertical cube strip, regular transform-placement, and invalid-dimension
|
||||
import route decisions, equirectangular service dispatch, transform import
|
||||
@@ -2485,6 +2490,13 @@ Results:
|
||||
Version, and save-before-workflow now log payload completeness and PPI
|
||||
readiness from `pp_app_core` while legacy `Canvas::project_save` still owns
|
||||
the actual file write, progress/threading behavior, and compatibility quirks.
|
||||
- `pp_app_core` now exposes
|
||||
`export_document_canvas_save_snapshot_to_ppi`, which refuses snapshots that
|
||||
still need renderer payload readback and exports payload-complete or
|
||||
metadata-only snapshots through the pure `pp_document` PPI writer. The
|
||||
document-canvas tests decode the generated bytes, and
|
||||
`pano_cli plan-canvas-document-snapshot` reports `ppiExport` readiness,
|
||||
byte count, and dirty-face count for agent automation.
|
||||
- Snapshot creation now rejects invalid embedded RGBA8 face payloads before
|
||||
document export or history can persist malformed state.
|
||||
- Package-smoke wrappers validate the Windows CMake app executable/runtime
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "document/document.h"
|
||||
#include "document/ppi_export.h"
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -77,6 +78,11 @@ struct DocumentCanvasSaveSnapshotReport {
|
||||
bool can_export_ppi = false;
|
||||
};
|
||||
|
||||
struct DocumentCanvasPpiExportResult {
|
||||
DocumentCanvasSaveSnapshotReport report;
|
||||
std::vector<std::byte> bytes;
|
||||
};
|
||||
|
||||
class DocumentCanvasClearServices {
|
||||
public:
|
||||
virtual ~DocumentCanvasClearServices() = default;
|
||||
@@ -242,6 +248,27 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentCanvasPpiExportResult>
|
||||
export_document_canvas_save_snapshot_to_ppi(const DocumentCanvasSnapshotResult& snapshot)
|
||||
{
|
||||
const auto report = make_document_canvas_save_snapshot_report(snapshot);
|
||||
if (!report.can_export_ppi) {
|
||||
return pp::foundation::Result<DocumentCanvasPpiExportResult>::failure(
|
||||
pp::foundation::Status::invalid_argument(
|
||||
"canvas document snapshot still requires renderer payload readback"));
|
||||
}
|
||||
|
||||
auto bytes = pp::document::export_ppi_project_document(snapshot.document);
|
||||
if (!bytes) {
|
||||
return pp::foundation::Result<DocumentCanvasPpiExportResult>::failure(bytes.status());
|
||||
}
|
||||
|
||||
return pp::foundation::Result<DocumentCanvasPpiExportResult>::success(DocumentCanvasPpiExportResult {
|
||||
.report = report,
|
||||
.bytes = std::move(bytes.value()),
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentCanvasClearPlan> plan_document_canvas_clear(
|
||||
bool has_canvas,
|
||||
float r = 0.0F,
|
||||
|
||||
@@ -1474,13 +1474,13 @@ if(TARGET pano_cli)
|
||||
COMMAND pano_cli plan-canvas-document-snapshot --width 128 --height 64 --layers 3 --frames 2 --current-layer 2 --current-frame 1 --hidden-layer 0 --alpha-locked-layer 2 --opacity 0.5 --blend-mode 4 --pending-face-payloads-per-layer 6)
|
||||
set_tests_properties(pano_cli_plan_canvas_document_snapshot_smoke PROPERTIES
|
||||
LABELS "app;document;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-document-snapshot\".*\"width\":128.*\"height\":64.*\"layers\":3.*\"frames\":2.*\"activeLayer\":2.*\"activeFrame\":1.*\"activeLayerName\":\"Layer 3\".*\"activeLayerOpacity\":0.5.*\"activeLayerBlend\":\"overlay\".*\"activeLayerAlphaLocked\":true.*\"pendingFacePayloads\":18.*\"metadataOnly\":true.*\"requiresRendererPayloadReadback\":true.*\"documentFacePayloads\":0.*\"saveReport\":\\{\"payloadComplete\":false,\"canExportPpi\":false\\}")
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-document-snapshot\".*\"width\":128.*\"height\":64.*\"layers\":3.*\"frames\":2.*\"activeLayer\":2.*\"activeFrame\":1.*\"activeLayerName\":\"Layer 3\".*\"activeLayerOpacity\":0.5.*\"activeLayerBlend\":\"overlay\".*\"activeLayerAlphaLocked\":true.*\"pendingFacePayloads\":18.*\"metadataOnly\":true.*\"requiresRendererPayloadReadback\":true.*\"documentFacePayloads\":0.*\"saveReport\":\\{\"payloadComplete\":false,\"canExportPpi\":false\\}.*\"ppiExport\":\\{\"ready\":false,\"bytes\":0,\"dirtyFaces\":0\\}")
|
||||
|
||||
add_test(NAME pano_cli_plan_canvas_document_snapshot_payload_smoke
|
||||
COMMAND pano_cli plan-canvas-document-snapshot --width 128 --height 64 --layers 2 --frames 2 --current-layer 1 --current-frame 1 --pending-face-payloads-per-layer 2 --captured-face-payloads-per-layer 2)
|
||||
set_tests_properties(pano_cli_plan_canvas_document_snapshot_payload_smoke PROPERTIES
|
||||
LABELS "app;document;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-document-snapshot\".*\"layers\":2.*\"frames\":2.*\"activeLayer\":1.*\"activeFrame\":1.*\"pendingFacePayloads\":4.*\"capturedFacePayloads\":4.*\"metadataOnly\":false.*\"requiresRendererPayloadReadback\":false.*\"documentFacePayloads\":4.*\"saveReport\":\\{\"payloadComplete\":true,\"canExportPpi\":true\\}")
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-document-snapshot\".*\"layers\":2.*\"frames\":2.*\"activeLayer\":1.*\"activeFrame\":1.*\"pendingFacePayloads\":4.*\"capturedFacePayloads\":4.*\"metadataOnly\":false.*\"requiresRendererPayloadReadback\":false.*\"documentFacePayloads\":4.*\"saveReport\":\\{\"payloadComplete\":true,\"canExportPpi\":true\\}.*\"ppiExport\":\\{\"ready\":true,\"bytes\":[1-9][0-9]*,\"dirtyFaces\":4\\}")
|
||||
|
||||
add_test(NAME pano_cli_plan_canvas_document_snapshot_no_canvas
|
||||
COMMAND pano_cli plan-canvas-document-snapshot --no-canvas)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "app_core/document_canvas.h"
|
||||
#include "assets/ppi_header.h"
|
||||
#include "test_harness.h"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -89,6 +90,10 @@ void snapshot_plan_projects_canvas_metadata(pp::tests::Harness& harness)
|
||||
PP_EXPECT(harness, value.document.layers()[1].blend_mode == pp::paint::BlendMode::overlay);
|
||||
PP_EXPECT(harness, value.document.layers()[1].frames.size() == 1U);
|
||||
PP_EXPECT(harness, value.document.face_pixel_payload_count() == 0U);
|
||||
|
||||
const auto export_result = pp::app::export_document_canvas_save_snapshot_to_ppi(value);
|
||||
PP_EXPECT(harness, !export_result);
|
||||
PP_EXPECT(harness, export_result.status().code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void snapshot_plan_defaults_empty_names_and_frames(pp::tests::Harness& harness)
|
||||
@@ -117,6 +122,16 @@ void snapshot_plan_defaults_empty_names_and_frames(pp::tests::Harness& harness)
|
||||
PP_EXPECT(harness, !result.value().requires_renderer_payload_readback);
|
||||
PP_EXPECT(harness, result.value().document.layers()[0].name == "Layer 1");
|
||||
PP_EXPECT(harness, result.value().document.frames()[0].duration_ms == 100U);
|
||||
|
||||
const auto export_result = pp::app::export_document_canvas_save_snapshot_to_ppi(result.value());
|
||||
PP_EXPECT(harness, export_result);
|
||||
if (export_result) {
|
||||
const auto decoded = pp::assets::decode_ppi_project_images(export_result.value().bytes);
|
||||
PP_EXPECT(harness, decoded);
|
||||
if (decoded) {
|
||||
PP_EXPECT(harness, decoded.value().project.body.summary.dirty_face_count == 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void snapshot_plan_attaches_captured_face_payloads(pp::tests::Harness& harness)
|
||||
@@ -177,6 +192,20 @@ void snapshot_plan_attaches_captured_face_payloads(pp::tests::Harness& harness)
|
||||
PP_EXPECT(harness, report.captured_face_payloads == 1U);
|
||||
PP_EXPECT(harness, report.payload_complete);
|
||||
PP_EXPECT(harness, report.can_export_ppi);
|
||||
|
||||
const auto export_result = pp::app::export_document_canvas_save_snapshot_to_ppi(result.value());
|
||||
PP_EXPECT(harness, export_result);
|
||||
if (export_result) {
|
||||
PP_EXPECT(harness, export_result.value().report.can_export_ppi);
|
||||
PP_EXPECT(harness, export_result.value().bytes.size() > 0U);
|
||||
|
||||
const auto decoded = pp::assets::decode_ppi_project_images(export_result.value().bytes);
|
||||
PP_EXPECT(harness, decoded);
|
||||
if (decoded) {
|
||||
PP_EXPECT(harness, decoded.value().project.body.summary.dirty_face_count == 1U);
|
||||
PP_EXPECT(harness, decoded.value().project.body.summary.rgba_face_payload_count == 1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void snapshot_plan_rejects_invalid_canvas_state(pp::tests::Harness& harness)
|
||||
|
||||
@@ -5995,6 +5995,27 @@ int plan_canvas_document_snapshot(int argc, char** argv)
|
||||
const auto& document = value.document;
|
||||
const auto& active_layer = document.layers()[document.active_layer_index()];
|
||||
const auto save_report = pp::app::make_document_canvas_save_snapshot_report(value);
|
||||
bool ppi_export_ready = false;
|
||||
std::size_t ppi_export_bytes = 0;
|
||||
std::uint32_t ppi_export_dirty_faces = 0;
|
||||
if (save_report.can_export_ppi) {
|
||||
const auto exported = pp::app::export_document_canvas_save_snapshot_to_ppi(value);
|
||||
if (!exported) {
|
||||
print_error("plan-canvas-document-snapshot", exported.status().message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const auto decoded = pp::assets::decode_ppi_project_images(exported.value().bytes);
|
||||
if (!decoded) {
|
||||
print_error("plan-canvas-document-snapshot", decoded.status().message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
ppi_export_ready = true;
|
||||
ppi_export_bytes = exported.value().bytes.size();
|
||||
ppi_export_dirty_faces = decoded.value().project.body.summary.dirty_face_count;
|
||||
}
|
||||
|
||||
std::cout << "{\"ok\":true,\"command\":\"plan-canvas-document-snapshot\""
|
||||
<< ",\"state\":{\"hasCanvas\":" << json_bool(args.has_canvas)
|
||||
<< ",\"width\":" << args.width
|
||||
@@ -6021,6 +6042,9 @@ int plan_canvas_document_snapshot(int argc, char** argv)
|
||||
<< ",\"documentFacePayloads\":" << document.face_pixel_payload_count()
|
||||
<< ",\"saveReport\":{\"payloadComplete\":" << json_bool(save_report.payload_complete)
|
||||
<< ",\"canExportPpi\":" << json_bool(save_report.can_export_ppi)
|
||||
<< "},\"ppiExport\":{\"ready\":" << json_bool(ppi_export_ready)
|
||||
<< ",\"bytes\":" << ppi_export_bytes
|
||||
<< ",\"dirtyFaces\":" << ppi_export_dirty_faces
|
||||
<< "}"
|
||||
<< "}}\n";
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user