Files
panopainter/tests/document/ppi_export_tests.cpp

181 lines
6.4 KiB
C++

#include "assets/ppi_header.h"
#include "document/document.h"
#include "document/ppi_export.h"
#include "document/ppi_import.h"
#include "test_harness.h"
#include <cstdint>
#include <span>
#include <vector>
using pp::document::AnimationFrame;
using pp::document::CanvasDocument;
using pp::document::DocumentLayerConfig;
using pp::document::DocumentSnapshotConfig;
using pp::document::LayerFacePixels;
using pp::document::export_ppi_project_document;
using pp::foundation::StatusCode;
namespace {
void exports_document_metadata_and_face_payloads(pp::tests::Harness& h)
{
std::vector<std::uint8_t> red_pixel { 255, 0, 0, 255 };
std::vector<std::uint8_t> blue_pixel { 0, 0, 255, 128 };
const AnimationFrame root_frames[] {
{ .duration_ms = 100, .face_pixels = {} },
{ .duration_ms = 250, .face_pixels = {} },
};
const AnimationFrame base_frames[] {
{
.duration_ms = 100,
.face_pixels = {
LayerFacePixels {
.face_index = 0,
.x = 2,
.y = 3,
.width = 1,
.height = 1,
.rgba8 = red_pixel,
},
},
},
{ .duration_ms = 250, .face_pixels = {} },
};
const AnimationFrame paint_frames[] {
{
.duration_ms = 333,
.face_pixels = {
LayerFacePixels {
.face_index = 5,
.x = 4,
.y = 5,
.width = 1,
.height = 1,
.rgba8 = blue_pixel,
},
},
},
};
const DocumentLayerConfig layers[] {
{
.name = "Base",
.visible = true,
.alpha_locked = false,
.opacity = 1.0F,
.blend_mode = pp::paint::BlendMode::normal,
.frames = std::span<const AnimationFrame>(base_frames, 2),
},
{
.name = "Paint",
.visible = false,
.alpha_locked = true,
.opacity = 0.5F,
.blend_mode = pp::paint::BlendMode::overlay,
.frames = std::span<const AnimationFrame>(paint_frames, 1),
},
};
const auto document = CanvasDocument::create_from_snapshot(DocumentSnapshotConfig {
.width = 64,
.height = 32,
.layers = std::span<const DocumentLayerConfig>(layers, 2),
.frames = std::span<const AnimationFrame>(root_frames, 2),
.selection_masks = {},
});
PP_EXPECT(h, document.ok());
const auto exported = export_ppi_project_document(document.value());
PP_EXPECT(h, exported.ok());
const auto decoded = pp::assets::decode_ppi_project_images(exported.value());
PP_EXPECT(h, decoded.ok());
PP_EXPECT(h, decoded.value().project.body.summary.width == 64U);
PP_EXPECT(h, decoded.value().project.body.summary.height == 32U);
PP_EXPECT(h, decoded.value().project.body.summary.layer_count == 2U);
PP_EXPECT(h, decoded.value().project.body.summary.declared_frame_count == 3U);
PP_EXPECT(h, decoded.value().project.body.summary.dirty_face_count == 2U);
PP_EXPECT(h, decoded.value().project.body.layers[0].name == "Base");
PP_EXPECT(h, decoded.value().project.body.layers[0].frames.size() == 2U);
PP_EXPECT(h, decoded.value().project.body.layers[0].frames[1].duration_ms == 250U);
PP_EXPECT(h, decoded.value().project.body.layers[1].name == "Paint");
PP_EXPECT(h, decoded.value().project.body.layers[1].opacity == 0.5F);
PP_EXPECT(h, decoded.value().project.body.layers[1].blend_mode == 4U);
PP_EXPECT(h, decoded.value().project.body.layers[1].alpha_locked);
PP_EXPECT(h, !decoded.value().project.body.layers[1].visible);
PP_EXPECT(h, decoded.value().faces.size() == 2U);
PP_EXPECT(h, decoded.value().faces[0].layer_index == 0U);
PP_EXPECT(h, decoded.value().faces[0].frame_index == 0U);
PP_EXPECT(h, decoded.value().faces[0].face_index == 0U);
PP_EXPECT(h, decoded.value().faces[0].descriptor.x0 == 2U);
PP_EXPECT(h, decoded.value().faces[0].image.pixels[0] == 255U);
PP_EXPECT(h, decoded.value().faces[1].layer_index == 1U);
PP_EXPECT(h, decoded.value().faces[1].frame_index == 0U);
PP_EXPECT(h, decoded.value().faces[1].face_index == 5U);
PP_EXPECT(h, decoded.value().faces[1].descriptor.y0 == 5U);
PP_EXPECT(h, decoded.value().faces[1].image.pixels[2] == 255U);
PP_EXPECT(h, decoded.value().faces[1].image.pixels[3] == 128U);
const auto imported = pp::document::import_ppi_project_document(decoded.value());
PP_EXPECT(h, imported.ok());
PP_EXPECT(h, imported.value().layers().size() == 2U);
PP_EXPECT(h, imported.value().layers()[1].alpha_locked);
PP_EXPECT(h, imported.value().face_pixel_payload_count() == 2U);
}
void rejects_export_when_document_payload_cannot_encode(pp::tests::Harness& h)
{
const AnimationFrame root_frames[] {
{ .duration_ms = 100, .face_pixels = {} },
};
const AnimationFrame bad_frames[] {
{
.duration_ms = 100,
.face_pixels = {
LayerFacePixels {
.face_index = 0,
.x = 0,
.y = 0,
.width = 1,
.height = 1,
.rgba8 = {},
},
},
},
};
const DocumentLayerConfig layers[] {
{
.name = "Bad",
.visible = true,
.alpha_locked = false,
.opacity = 1.0F,
.blend_mode = pp::paint::BlendMode::normal,
.frames = std::span<const AnimationFrame>(bad_frames, 1),
},
};
const auto document = CanvasDocument::create_from_snapshot(DocumentSnapshotConfig {
.width = 64,
.height = 32,
.layers = std::span<const DocumentLayerConfig>(layers, 1),
.frames = std::span<const AnimationFrame>(root_frames, 1),
.selection_masks = {},
});
PP_EXPECT(h, document.ok());
const auto exported = export_ppi_project_document(document.value());
PP_EXPECT(h, !exported.ok());
PP_EXPECT(h, exported.status().code == StatusCode::invalid_argument);
}
}
int main()
{
pp::tests::Harness harness;
harness.run("exports_document_metadata_and_face_payloads", exports_document_metadata_and_face_payloads);
harness.run("rejects_export_when_document_payload_cannot_encode", rejects_export_when_document_payload_cannot_encode);
return harness.finish();
}