Add document PPI export boundary
This commit is contained in:
107
src/document/ppi_export.cpp
Normal file
107
src/document/ppi_export.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "document/ppi_export.h"
|
||||
|
||||
#include "assets/image_pixels.h"
|
||||
#include "assets/ppi_header.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
namespace pp::document {
|
||||
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<std::uint32_t> ppi_blend_mode(
|
||||
pp::paint::BlendMode blend_mode) noexcept
|
||||
{
|
||||
switch (blend_mode) {
|
||||
case pp::paint::BlendMode::normal:
|
||||
return pp::foundation::Result<std::uint32_t>::success(0);
|
||||
case pp::paint::BlendMode::multiply:
|
||||
return pp::foundation::Result<std::uint32_t>::success(1);
|
||||
case pp::paint::BlendMode::screen:
|
||||
return pp::foundation::Result<std::uint32_t>::success(2);
|
||||
case pp::paint::BlendMode::color_dodge:
|
||||
return pp::foundation::Result<std::uint32_t>::success(3);
|
||||
case pp::paint::BlendMode::overlay:
|
||||
return pp::foundation::Result<std::uint32_t>::success(4);
|
||||
}
|
||||
|
||||
return pp::foundation::Result<std::uint32_t>::failure(
|
||||
pp::foundation::Status::invalid_argument("document layer blend mode cannot be exported to PPI"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pp::foundation::Result<std::vector<std::byte>> export_ppi_project_document(
|
||||
const CanvasDocument& document)
|
||||
{
|
||||
std::vector<std::vector<pp::assets::PpiFrameConfig>> frame_configs;
|
||||
frame_configs.reserve(document.layers().size());
|
||||
std::vector<pp::assets::PpiLayerConfig> layer_configs;
|
||||
layer_configs.reserve(document.layers().size());
|
||||
std::vector<std::vector<std::byte>> payloads;
|
||||
payloads.reserve(document.face_pixel_payload_count());
|
||||
std::vector<pp::assets::PpiDirtyFacePayloadConfig> dirty_faces;
|
||||
dirty_faces.reserve(document.face_pixel_payload_count());
|
||||
|
||||
for (std::size_t layer_index = 0; layer_index < document.layers().size(); ++layer_index) {
|
||||
const auto& layer = document.layers()[layer_index];
|
||||
const auto blend_mode = ppi_blend_mode(layer.blend_mode);
|
||||
if (!blend_mode) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(blend_mode.status());
|
||||
}
|
||||
|
||||
auto& frames = frame_configs.emplace_back();
|
||||
frames.reserve(layer.frames.size());
|
||||
for (std::size_t frame_index = 0; frame_index < layer.frames.size(); ++frame_index) {
|
||||
const auto& frame = layer.frames[frame_index];
|
||||
frames.push_back(pp::assets::PpiFrameConfig {
|
||||
.duration_ms = frame.duration_ms,
|
||||
});
|
||||
|
||||
for (const auto& face : frame.face_pixels) {
|
||||
const auto encoded = pp::assets::encode_png_rgba8(
|
||||
face.width,
|
||||
face.height,
|
||||
face.rgba8);
|
||||
if (!encoded) {
|
||||
return pp::foundation::Result<std::vector<std::byte>>::failure(encoded.status());
|
||||
}
|
||||
|
||||
payloads.push_back(encoded.value());
|
||||
const auto& payload = payloads.back();
|
||||
dirty_faces.push_back(pp::assets::PpiDirtyFacePayloadConfig {
|
||||
.layer_index = static_cast<std::uint32_t>(layer_index),
|
||||
.frame_index = static_cast<std::uint32_t>(frame_index),
|
||||
.face_index = face.face_index,
|
||||
.x = face.x,
|
||||
.y = face.y,
|
||||
.width = face.width,
|
||||
.height = face.height,
|
||||
.png_rgba8 = std::span<const std::byte>(payload.data(), payload.size()),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
layer_configs.push_back(pp::assets::PpiLayerConfig {
|
||||
.name = layer.name,
|
||||
.metadata = pp::assets::PpiLayerMetadataConfig {
|
||||
.opacity = layer.opacity,
|
||||
.blend_mode = blend_mode.value(),
|
||||
.alpha_locked = layer.alpha_locked,
|
||||
.visible = layer.visible,
|
||||
},
|
||||
.frames = std::span<const pp::assets::PpiFrameConfig>(frames.data(), frames.size()),
|
||||
});
|
||||
}
|
||||
|
||||
return pp::assets::create_ppi_project(pp::assets::PpiProjectConfig {
|
||||
.width = document.width(),
|
||||
.height = document.height(),
|
||||
.layers = std::span<const pp::assets::PpiLayerConfig>(layer_configs.data(), layer_configs.size()),
|
||||
.dirty_faces = std::span<const pp::assets::PpiDirtyFacePayloadConfig>(dirty_faces.data(), dirty_faces.size()),
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
14
src/document/ppi_export.h
Normal file
14
src/document/ppi_export.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "document/document.h"
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::document {
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<std::vector<std::byte>> export_ppi_project_document(
|
||||
const CanvasDocument& document);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user