Project legacy canvas metadata into documents

This commit is contained in:
2026-06-05 17:54:45 +02:00
parent a9ef2c598c
commit d0412e3bf9
11 changed files with 580 additions and 4 deletions

View File

@@ -1,7 +1,9 @@
#include "app_core/document_canvas.h"
#include "test_harness.h"
#include <cstdint>
#include <limits>
#include <span>
#include <string>
namespace {
@@ -26,6 +28,153 @@ public:
std::string call_order;
};
void snapshot_plan_projects_canvas_metadata(pp::tests::Harness& harness)
{
const std::uint32_t base_frames[] { 120U, 240U };
const std::uint32_t paint_frames[] { 180U };
const pp::app::DocumentCanvasLayerSnapshotInput layers[] {
{
.name = "Base",
.visible = false,
.alpha_locked = true,
.opacity = 0.5F,
.blend_mode = 2,
.frame_durations_ms = std::span<const std::uint32_t>(base_frames),
.pending_face_payloads = 6U,
},
{
.name = "Paint",
.visible = true,
.alpha_locked = false,
.opacity = 0.75F,
.blend_mode = 4,
.frame_durations_ms = std::span<const std::uint32_t>(paint_frames),
.pending_face_payloads = 3U,
},
};
const auto result = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = true,
.width = 64U,
.height = 32U,
.active_layer_index = 1U,
.active_frame_index = 1U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(layers),
});
PP_EXPECT(harness, result);
if (!result) {
return;
}
const auto& value = result.value();
PP_EXPECT(harness, value.layer_count == 2U);
PP_EXPECT(harness, value.frame_count == 2U);
PP_EXPECT(harness, value.pending_face_payloads == 9U);
PP_EXPECT(harness, value.metadata_only);
PP_EXPECT(harness, value.requires_renderer_payload_readback);
PP_EXPECT(harness, value.document.width() == 64U);
PP_EXPECT(harness, value.document.height() == 32U);
PP_EXPECT(harness, value.document.active_layer_index() == 1U);
PP_EXPECT(harness, value.document.active_frame_index() == 1U);
PP_EXPECT(harness, value.document.layers().size() == 2U);
PP_EXPECT(harness, value.document.frames().size() == 2U);
PP_EXPECT(harness, value.document.layers()[0].name == "Base");
PP_EXPECT(harness, !value.document.layers()[0].visible);
PP_EXPECT(harness, value.document.layers()[0].alpha_locked);
PP_EXPECT(harness, value.document.layers()[0].opacity == 0.5F);
PP_EXPECT(harness, value.document.layers()[0].blend_mode == pp::paint::BlendMode::screen);
PP_EXPECT(harness, value.document.layers()[0].frames[1].duration_ms == 240U);
PP_EXPECT(harness, value.document.layers()[1].name == "Paint");
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);
}
void snapshot_plan_defaults_empty_names_and_frames(pp::tests::Harness& harness)
{
const pp::app::DocumentCanvasLayerSnapshotInput layers[] {
{
.name = "",
.frame_durations_ms = {},
},
};
const auto result = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = true,
.width = 16U,
.height = 8U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(layers),
});
PP_EXPECT(harness, result);
if (!result) {
return;
}
PP_EXPECT(harness, result.value().frame_count == 1U);
PP_EXPECT(harness, result.value().pending_face_payloads == 0U);
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);
}
void snapshot_plan_rejects_invalid_canvas_state(pp::tests::Harness& harness)
{
const std::uint32_t frames[] { 100U };
const pp::app::DocumentCanvasLayerSnapshotInput layers[] {
{
.name = "Layer",
.frame_durations_ms = std::span<const std::uint32_t>(frames),
},
};
const auto no_canvas = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = false,
.width = 16U,
.height = 8U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(layers),
});
const auto bad_layer = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = true,
.width = 16U,
.height = 8U,
.active_layer_index = 1U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(layers),
});
const pp::app::DocumentCanvasLayerSnapshotInput bad_blend_layers[] {
{
.name = "Layer",
.blend_mode = 64,
.frame_durations_ms = std::span<const std::uint32_t>(frames),
},
};
const auto bad_blend = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = true,
.width = 16U,
.height = 8U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(bad_blend_layers),
});
const std::uint32_t bad_frames[] { 0U };
const pp::app::DocumentCanvasLayerSnapshotInput bad_duration_layers[] {
{
.name = "Layer",
.frame_durations_ms = std::span<const std::uint32_t>(bad_frames),
},
};
const auto bad_duration = pp::app::plan_document_canvas_snapshot(pp::app::DocumentCanvasSnapshotInput {
.has_canvas = true,
.width = 16U,
.height = 8U,
.layers = std::span<const pp::app::DocumentCanvasLayerSnapshotInput>(bad_duration_layers),
});
PP_EXPECT(harness, !no_canvas);
PP_EXPECT(harness, !bad_layer);
PP_EXPECT(harness, !bad_blend);
PP_EXPECT(harness, !bad_duration);
}
void clear_plan_records_legacy_canvas_effects(pp::tests::Harness& harness)
{
const auto plan = pp::app::plan_document_canvas_clear(true, 0.0F, 0.1F, 0.2F, 0.3F);
@@ -119,6 +268,9 @@ void clear_executor_rejects_invalid_color(pp::tests::Harness& harness)
int main()
{
pp::tests::Harness harness;
harness.run("snapshot plan projects canvas metadata", snapshot_plan_projects_canvas_metadata);
harness.run("snapshot plan defaults empty names and frames", snapshot_plan_defaults_empty_names_and_frames);
harness.run("snapshot plan rejects invalid canvas state", snapshot_plan_rejects_invalid_canvas_state);
harness.run("clear plan records legacy canvas effects", clear_plan_records_legacy_canvas_effects);
harness.run("clear plan noops without canvas", clear_plan_noops_without_canvas);
harness.run("clear plan rejects bad color channels", clear_plan_rejects_bad_color_channels);