Export layer collections through paint renderer
This commit is contained in:
@@ -41,6 +41,11 @@ struct DocumentCubeFaceExportPayload {
|
||||
std::span<const std::byte> bytes;
|
||||
};
|
||||
|
||||
struct DocumentExportCollectionPngPayload {
|
||||
std::string path_suffix;
|
||||
std::span<const std::byte> bytes;
|
||||
};
|
||||
|
||||
struct DocumentExportSuggestedName {
|
||||
std::string name;
|
||||
};
|
||||
@@ -190,6 +195,16 @@ public:
|
||||
virtual void publish_exported_image(std::string_view path) = 0;
|
||||
};
|
||||
|
||||
class DocumentExportCollectionWriteServices {
|
||||
public:
|
||||
virtual ~DocumentExportCollectionWriteServices() = default;
|
||||
|
||||
virtual pp::foundation::Status write_binary_file(
|
||||
std::string_view path,
|
||||
std::span<const std::byte> bytes) = 0;
|
||||
virtual void publish_exported_image(std::string_view path) = 0;
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr DocumentExportStartDecision plan_document_export_start(
|
||||
bool requires_license,
|
||||
bool license_valid,
|
||||
@@ -608,6 +623,41 @@ document_cube_face_export_names() noexcept
|
||||
return pp::foundation::Result<DocumentCubeFaceExportTarget>::success(std::move(target));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string document_export_two_digit_index(std::size_t index)
|
||||
{
|
||||
auto value = std::to_string(index);
|
||||
if (value.size() < 2U) {
|
||||
value.insert(value.begin(), '0');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string make_document_layer_export_path_suffix(
|
||||
std::size_t layer_index,
|
||||
std::string_view layer_name)
|
||||
{
|
||||
std::string suffix;
|
||||
const auto index = document_export_two_digit_index(layer_index);
|
||||
suffix.reserve(10U + index.size() + layer_name.size());
|
||||
suffix += "-layer";
|
||||
suffix += index;
|
||||
suffix += "-";
|
||||
suffix += layer_name;
|
||||
suffix += ".png";
|
||||
return suffix;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string make_document_animation_frame_export_path_suffix(std::size_t frame_index)
|
||||
{
|
||||
std::string suffix;
|
||||
const auto index = document_export_two_digit_index(frame_index);
|
||||
suffix.reserve(5U + index.size());
|
||||
suffix += "-";
|
||||
suffix += index;
|
||||
suffix += ".png";
|
||||
return suffix;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportSuggestedName> make_document_export_suggested_name(
|
||||
std::string_view document_name,
|
||||
std::string_view suffix)
|
||||
@@ -656,6 +706,41 @@ document_cube_face_export_names() noexcept
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Status execute_document_export_collection_write(
|
||||
const DocumentExportCollectionTarget& target,
|
||||
std::span<const DocumentExportCollectionPngPayload> payloads,
|
||||
DocumentExportCollectionWriteServices& services)
|
||||
{
|
||||
if (target.stem_path.empty()) {
|
||||
return pp::foundation::Status::invalid_argument("export collection target requires a stem path");
|
||||
}
|
||||
|
||||
if (payloads.empty()) {
|
||||
return pp::foundation::Status::invalid_argument("export collection payloads must not be empty");
|
||||
}
|
||||
|
||||
for (const auto& payload : payloads) {
|
||||
if (payload.path_suffix.empty()) {
|
||||
return pp::foundation::Status::invalid_argument("export collection payload suffix must not be empty");
|
||||
}
|
||||
if (payload.bytes.empty()) {
|
||||
return pp::foundation::Status::invalid_argument("export collection payload must not be empty");
|
||||
}
|
||||
|
||||
std::string path;
|
||||
path.reserve(target.stem_path.size() + payload.path_suffix.size());
|
||||
path += target.stem_path;
|
||||
path += payload.path_suffix;
|
||||
const auto write_status = services.write_binary_file(path, payload.bytes);
|
||||
if (!write_status.ok()) {
|
||||
return write_status;
|
||||
}
|
||||
services.publish_exported_image(path);
|
||||
}
|
||||
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Status execute_document_export_file(
|
||||
const DocumentExportFileTarget& target,
|
||||
DocumentExportServices& services)
|
||||
|
||||
@@ -65,9 +65,11 @@ pp::foundation::Status write_export_binary_file(std::string_view path, std::span
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
class LegacyCubeFaceExportWriteServices final : public pp::app::DocumentCubeFaceExportWriteServices {
|
||||
class LegacyExportWriteServices final
|
||||
: public pp::app::DocumentCubeFaceExportWriteServices
|
||||
, public pp::app::DocumentExportCollectionWriteServices {
|
||||
public:
|
||||
explicit LegacyCubeFaceExportWriteServices(App& app) noexcept
|
||||
explicit LegacyExportWriteServices(App& app) noexcept
|
||||
: app_(app)
|
||||
{
|
||||
}
|
||||
@@ -183,10 +185,90 @@ pp::foundation::Status export_cube_faces_from_document_snapshot(
|
||||
payloads[face_index].bytes = std::span<const std::byte>(reports.face_pngs.face_pngs[face_index]);
|
||||
}
|
||||
|
||||
LegacyCubeFaceExportWriteServices services(app);
|
||||
LegacyExportWriteServices services(app);
|
||||
return pp::app::execute_document_cube_face_export_write(target.value(), payloads, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status export_layers_from_document_snapshot(
|
||||
App& app,
|
||||
const pp::app::DocumentExportCollectionTarget& target,
|
||||
const LegacyDocumentExportSnapshotReports& reports)
|
||||
{
|
||||
const auto report = pp::app::make_document_canvas_save_snapshot_report(reports.snapshot);
|
||||
if (!report.payload_complete) {
|
||||
return pp::foundation::Status::invalid_argument(
|
||||
"document snapshot layer export still requires renderer payload readback");
|
||||
}
|
||||
|
||||
auto exported = pp::paint_renderer::export_document_layers_equirectangular_pngs(
|
||||
pp::paint_renderer::DocumentLayerEquirectangularPngExportRequest {
|
||||
.document = &reports.snapshot.document,
|
||||
.frame_index = reports.snapshot.document.active_frame_index(),
|
||||
.clear_color = {},
|
||||
});
|
||||
if (!exported) {
|
||||
return exported.status();
|
||||
}
|
||||
|
||||
auto exported_value = std::move(exported.value());
|
||||
LOG(
|
||||
"export-layers document export PNG writer: layers=%zu bytes=%llu activeFrame=%zu",
|
||||
exported_value.layer_count,
|
||||
static_cast<unsigned long long>(exported_value.encoded_bytes),
|
||||
reports.snapshot.document.active_frame_index());
|
||||
|
||||
std::vector<pp::app::DocumentExportCollectionPngPayload> payloads;
|
||||
payloads.reserve(exported_value.layers.size());
|
||||
for (const auto& layer : exported_value.layers) {
|
||||
payloads.push_back(pp::app::DocumentExportCollectionPngPayload {
|
||||
.path_suffix = pp::app::make_document_layer_export_path_suffix(layer.layer_index, layer.layer_name),
|
||||
.bytes = std::span<const std::byte>(layer.png.data(), layer.png.size()),
|
||||
});
|
||||
}
|
||||
|
||||
LegacyExportWriteServices services(app);
|
||||
return pp::app::execute_document_export_collection_write(target, payloads, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status export_animation_frames_from_document_snapshot(
|
||||
App& app,
|
||||
const pp::app::DocumentExportCollectionTarget& target,
|
||||
const LegacyDocumentExportSnapshotReports& reports)
|
||||
{
|
||||
const auto report = pp::app::make_document_canvas_save_snapshot_report(reports.snapshot);
|
||||
if (!report.payload_complete) {
|
||||
return pp::foundation::Status::invalid_argument(
|
||||
"document snapshot animation-frame export still requires renderer payload readback");
|
||||
}
|
||||
|
||||
auto exported = pp::paint_renderer::export_document_animation_frames_equirectangular_pngs(
|
||||
pp::paint_renderer::DocumentAnimationFrameEquirectangularPngExportRequest {
|
||||
.document = &reports.snapshot.document,
|
||||
.clear_color = {},
|
||||
});
|
||||
if (!exported) {
|
||||
return exported.status();
|
||||
}
|
||||
|
||||
auto exported_value = std::move(exported.value());
|
||||
LOG(
|
||||
"export-animation-frames document export PNG writer: frames=%zu bytes=%llu",
|
||||
exported_value.frame_count,
|
||||
static_cast<unsigned long long>(exported_value.encoded_bytes));
|
||||
|
||||
std::vector<pp::app::DocumentExportCollectionPngPayload> payloads;
|
||||
payloads.reserve(exported_value.frames.size());
|
||||
for (const auto& frame : exported_value.frames) {
|
||||
payloads.push_back(pp::app::DocumentExportCollectionPngPayload {
|
||||
.path_suffix = pp::app::make_document_animation_frame_export_path_suffix(frame.frame_index),
|
||||
.bytes = std::span<const std::byte>(frame.png.data(), frame.png.size()),
|
||||
});
|
||||
}
|
||||
|
||||
LegacyExportWriteServices services(app);
|
||||
return pp::app::execute_document_export_collection_write(target, payloads, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status export_equirectangular_png_from_document_snapshot(
|
||||
App& app,
|
||||
const pp::app::DocumentExportFileTarget& target,
|
||||
@@ -284,7 +366,32 @@ public:
|
||||
void export_layers_to_stem(const pp::app::DocumentExportStemTarget& target) override
|
||||
{
|
||||
auto* app = &app_;
|
||||
#if !__WEB__
|
||||
const auto prepared = prepare_legacy_document_export_snapshot(app_, "export-layers");
|
||||
if (prepared) {
|
||||
const auto collection_target = pp::app::DocumentExportCollectionTarget {
|
||||
.stem_path = target.stem_path,
|
||||
};
|
||||
const auto exported = export_layers_from_document_snapshot(app_, collection_target, prepared.value());
|
||||
if (exported.ok()) {
|
||||
show_export_success_dialog(
|
||||
app_,
|
||||
pp::app::plan_document_export_success_dialog(
|
||||
pp::app::DocumentExportSuccessKind::layers,
|
||||
pp::app::DocumentExportSuccessDestination::path,
|
||||
target.stem_path));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("export-layers document export writer retained legacy export after failure: %s", exported.message);
|
||||
} else {
|
||||
LOG(
|
||||
"export-layers document export snapshot bridge retained legacy export after failure: %s",
|
||||
prepared.status().message);
|
||||
}
|
||||
#else
|
||||
prepare_legacy_document_export_snapshot_or_continue(app_, "export-layers");
|
||||
#endif
|
||||
app_.canvas->m_canvas->export_layers(target.stem_path, [app, target] {
|
||||
show_export_success_dialog(
|
||||
*app,
|
||||
@@ -298,7 +405,28 @@ public:
|
||||
void export_layers_to_collection(const pp::app::DocumentExportCollectionTarget& target) override
|
||||
{
|
||||
auto* app = &app_;
|
||||
#if !__WEB__
|
||||
const auto prepared = prepare_legacy_document_export_snapshot(app_, "export-layers");
|
||||
if (prepared) {
|
||||
const auto exported = export_layers_from_document_snapshot(app_, target, prepared.value());
|
||||
if (exported.ok()) {
|
||||
show_export_success_dialog(
|
||||
app_,
|
||||
pp::app::plan_document_export_success_dialog(
|
||||
pp::app::DocumentExportSuccessKind::layers,
|
||||
pp::app::DocumentExportSuccessDestination::files_panopainter));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("export-layers document export writer retained legacy export after failure: %s", exported.message);
|
||||
} else {
|
||||
LOG(
|
||||
"export-layers document export snapshot bridge retained legacy export after failure: %s",
|
||||
prepared.status().message);
|
||||
}
|
||||
#else
|
||||
prepare_legacy_document_export_snapshot_or_continue(app_, "export-layers");
|
||||
#endif
|
||||
app_.canvas->m_canvas->export_layers(target.stem_path, [app] {
|
||||
show_export_success_dialog(
|
||||
*app,
|
||||
@@ -311,7 +439,37 @@ public:
|
||||
void export_animation_frames_to_stem(const pp::app::DocumentExportStemTarget& target) override
|
||||
{
|
||||
auto* app = &app_;
|
||||
#if !__WEB__
|
||||
const auto prepared = prepare_legacy_document_export_snapshot(app_, "export-animation-frames");
|
||||
if (prepared) {
|
||||
const auto collection_target = pp::app::DocumentExportCollectionTarget {
|
||||
.stem_path = target.stem_path,
|
||||
};
|
||||
const auto exported = export_animation_frames_from_document_snapshot(
|
||||
app_,
|
||||
collection_target,
|
||||
prepared.value());
|
||||
if (exported.ok()) {
|
||||
show_export_success_dialog(
|
||||
app_,
|
||||
pp::app::plan_document_export_success_dialog(
|
||||
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||
pp::app::DocumentExportSuccessDestination::path,
|
||||
target.stem_path));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(
|
||||
"export-animation-frames document export writer retained legacy export after failure: %s",
|
||||
exported.message);
|
||||
} else {
|
||||
LOG(
|
||||
"export-animation-frames document export snapshot bridge retained legacy export after failure: %s",
|
||||
prepared.status().message);
|
||||
}
|
||||
#else
|
||||
prepare_legacy_document_export_snapshot_or_continue(app_, "export-animation-frames");
|
||||
#endif
|
||||
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app, target] {
|
||||
show_export_success_dialog(
|
||||
*app,
|
||||
@@ -325,7 +483,30 @@ public:
|
||||
void export_animation_frames_to_collection(const pp::app::DocumentExportCollectionTarget& target) override
|
||||
{
|
||||
auto* app = &app_;
|
||||
#if !__WEB__
|
||||
const auto prepared = prepare_legacy_document_export_snapshot(app_, "export-animation-frames");
|
||||
if (prepared) {
|
||||
const auto exported = export_animation_frames_from_document_snapshot(app_, target, prepared.value());
|
||||
if (exported.ok()) {
|
||||
show_export_success_dialog(
|
||||
app_,
|
||||
pp::app::plan_document_export_success_dialog(
|
||||
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||
pp::app::DocumentExportSuccessDestination::files_panopainter));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(
|
||||
"export-animation-frames document export writer retained legacy export after failure: %s",
|
||||
exported.message);
|
||||
} else {
|
||||
LOG(
|
||||
"export-animation-frames document export snapshot bridge retained legacy export after failure: %s",
|
||||
prepared.status().message);
|
||||
}
|
||||
#else
|
||||
prepare_legacy_document_export_snapshot_or_continue(app_, "export-animation-frames");
|
||||
#endif
|
||||
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app] {
|
||||
show_export_success_dialog(
|
||||
*app,
|
||||
|
||||
@@ -408,6 +408,77 @@ pp::foundation::Result<DocumentFrameCompositeResult> composite_document_frame(
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentFrameCompositeResult> composite_document_layer_frame(
|
||||
const pp::document::CanvasDocument& document,
|
||||
std::size_t layer_index,
|
||||
std::size_t frame_index,
|
||||
pp::paint::Rgba clear_color)
|
||||
{
|
||||
if (layer_index >= document.layers().size()) {
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::failure(
|
||||
pp::foundation::Status::out_of_range("document layer export index is outside the document"));
|
||||
}
|
||||
|
||||
if (frame_index >= document.frames().size()) {
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::failure(
|
||||
pp::foundation::Status::out_of_range("document layer export frame index is outside the document"));
|
||||
}
|
||||
|
||||
const pp::renderer::Extent2D extent {
|
||||
.width = document.width(),
|
||||
.height = document.height(),
|
||||
};
|
||||
const auto pixel_count = expected_pixel_count(extent);
|
||||
if (!pixel_count) {
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::failure(pixel_count.status());
|
||||
}
|
||||
|
||||
const auto& source_layer = document.layers()[layer_index];
|
||||
auto export_layer = source_layer;
|
||||
export_layer.visible = true;
|
||||
export_layer.opacity = 1.0F;
|
||||
export_layer.blend_mode = pp::paint::BlendMode::normal;
|
||||
|
||||
DocumentFrameCompositeResult result;
|
||||
result.extent = extent;
|
||||
result.visited_layer_count = 1U;
|
||||
|
||||
for (std::uint32_t face_index = 0; face_index < pp::document::cube_face_count; ++face_index) {
|
||||
DocumentFaceCompositeResult face;
|
||||
face.extent = extent;
|
||||
face.pixels.assign(pixel_count.value(), clear_color);
|
||||
face.visited_layer_count = 1U;
|
||||
|
||||
if (frame_index < source_layer.frames.size()) {
|
||||
bool composited_face = false;
|
||||
const auto& frame = source_layer.frames[frame_index];
|
||||
for (const auto& payload : frame.face_pixels) {
|
||||
if (payload.face_index != face_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto status = composite_face_payload(face.pixels, extent, payload, export_layer);
|
||||
if (!status.ok()) {
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::failure(status);
|
||||
}
|
||||
|
||||
composited_face = true;
|
||||
++face.face_payload_count;
|
||||
++result.face_payload_count;
|
||||
}
|
||||
|
||||
if (composited_face) {
|
||||
face.composited_layer_count = 1U;
|
||||
++result.composited_layer_face_count;
|
||||
}
|
||||
}
|
||||
|
||||
result.faces[face_index] = std::move(face);
|
||||
}
|
||||
|
||||
return pp::foundation::Result<DocumentFrameCompositeResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentFrameUploadResult> upload_document_frame_faces(
|
||||
pp::renderer::IRenderDevice& device,
|
||||
DocumentFrameUploadRequest request)
|
||||
@@ -612,6 +683,91 @@ export_document_frame_equirectangular_png(DocumentFrameCompositeRequest request)
|
||||
return export_document_frame_equirectangular_png(composite.value());
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>
|
||||
export_document_layers_equirectangular_pngs(DocumentLayerEquirectangularPngExportRequest request)
|
||||
{
|
||||
if (request.document == nullptr) {
|
||||
return pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>::failure(
|
||||
pp::foundation::Status::invalid_argument("document layer export request requires a document"));
|
||||
}
|
||||
|
||||
if (request.frame_index >= request.document->frames().size()) {
|
||||
return pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>::failure(
|
||||
pp::foundation::Status::out_of_range("document layer export frame index is outside the document"));
|
||||
}
|
||||
|
||||
DocumentLayerEquirectangularPngExportResult result;
|
||||
result.layers.reserve(request.document->layers().size());
|
||||
for (std::size_t layer_index = 0; layer_index < request.document->layers().size(); ++layer_index) {
|
||||
auto composite = composite_document_layer_frame(
|
||||
*request.document,
|
||||
layer_index,
|
||||
request.frame_index,
|
||||
request.clear_color);
|
||||
if (!composite) {
|
||||
return pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>::failure(composite.status());
|
||||
}
|
||||
|
||||
auto exported = export_document_frame_equirectangular_png(composite.value());
|
||||
if (!exported) {
|
||||
return pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>::failure(exported.status());
|
||||
}
|
||||
|
||||
DocumentLayerEquirectangularPng layer;
|
||||
layer.layer_index = layer_index;
|
||||
layer.layer_name = request.document->layers()[layer_index].name;
|
||||
layer.face_extent = exported.value().face_extent;
|
||||
layer.equirectangular_extent = exported.value().equirectangular_extent;
|
||||
layer.encoded_bytes = exported.value().encoded_bytes;
|
||||
layer.face_payload_count = exported.value().face_payload_count;
|
||||
layer.composited_layer_face_count = exported.value().composited_layer_face_count;
|
||||
layer.png = std::move(exported.value().png);
|
||||
result.encoded_bytes += layer.encoded_bytes;
|
||||
result.layers.push_back(std::move(layer));
|
||||
}
|
||||
|
||||
result.layer_count = result.layers.size();
|
||||
return pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentAnimationFrameEquirectangularPngExportResult>
|
||||
export_document_animation_frames_equirectangular_pngs(
|
||||
DocumentAnimationFrameEquirectangularPngExportRequest request)
|
||||
{
|
||||
if (request.document == nullptr) {
|
||||
return pp::foundation::Result<DocumentAnimationFrameEquirectangularPngExportResult>::failure(
|
||||
pp::foundation::Status::invalid_argument("document animation-frame export request requires a document"));
|
||||
}
|
||||
|
||||
DocumentAnimationFrameEquirectangularPngExportResult result;
|
||||
result.frames.reserve(request.document->frames().size());
|
||||
for (std::size_t frame_index = 0; frame_index < request.document->frames().size(); ++frame_index) {
|
||||
auto exported = export_document_frame_equirectangular_png(DocumentFrameCompositeRequest {
|
||||
.document = request.document,
|
||||
.frame_index = frame_index,
|
||||
.clear_color = request.clear_color,
|
||||
});
|
||||
if (!exported) {
|
||||
return pp::foundation::Result<DocumentAnimationFrameEquirectangularPngExportResult>::failure(
|
||||
exported.status());
|
||||
}
|
||||
|
||||
DocumentAnimationFrameEquirectangularPng frame;
|
||||
frame.frame_index = frame_index;
|
||||
frame.face_extent = exported.value().face_extent;
|
||||
frame.equirectangular_extent = exported.value().equirectangular_extent;
|
||||
frame.encoded_bytes = exported.value().encoded_bytes;
|
||||
frame.face_payload_count = exported.value().face_payload_count;
|
||||
frame.composited_layer_face_count = exported.value().composited_layer_face_count;
|
||||
frame.png = std::move(exported.value().png);
|
||||
result.encoded_bytes += frame.encoded_bytes;
|
||||
result.frames.push_back(std::move(frame));
|
||||
}
|
||||
|
||||
result.frame_count = result.frames.size();
|
||||
return pp::foundation::Result<DocumentAnimationFrameEquirectangularPngExportResult>::success(std::move(result));
|
||||
}
|
||||
|
||||
pp::foundation::Result<DocumentFrameExportReadinessResult> prepare_document_frame_export_readiness(
|
||||
DocumentFrameCompositeRequest request)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::paint_renderer {
|
||||
@@ -155,6 +156,50 @@ struct DocumentFrameEquirectangularPngExportResult {
|
||||
std::size_t composited_layer_face_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentLayerEquirectangularPngExportRequest {
|
||||
const pp::document::CanvasDocument* document = nullptr;
|
||||
std::size_t frame_index = 0;
|
||||
pp::paint::Rgba clear_color {};
|
||||
};
|
||||
|
||||
struct DocumentLayerEquirectangularPng {
|
||||
std::size_t layer_index = 0;
|
||||
std::string layer_name;
|
||||
pp::renderer::Extent2D face_extent {};
|
||||
pp::renderer::Extent2D equirectangular_extent {};
|
||||
std::vector<std::byte> png;
|
||||
std::uint64_t encoded_bytes = 0;
|
||||
std::size_t face_payload_count = 0;
|
||||
std::size_t composited_layer_face_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentLayerEquirectangularPngExportResult {
|
||||
std::vector<DocumentLayerEquirectangularPng> layers;
|
||||
std::uint64_t encoded_bytes = 0;
|
||||
std::size_t layer_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentAnimationFrameEquirectangularPngExportRequest {
|
||||
const pp::document::CanvasDocument* document = nullptr;
|
||||
pp::paint::Rgba clear_color {};
|
||||
};
|
||||
|
||||
struct DocumentAnimationFrameEquirectangularPng {
|
||||
std::size_t frame_index = 0;
|
||||
pp::renderer::Extent2D face_extent {};
|
||||
pp::renderer::Extent2D equirectangular_extent {};
|
||||
std::vector<std::byte> png;
|
||||
std::uint64_t encoded_bytes = 0;
|
||||
std::size_t face_payload_count = 0;
|
||||
std::size_t composited_layer_face_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentAnimationFrameEquirectangularPngExportResult {
|
||||
std::vector<DocumentAnimationFrameEquirectangularPng> frames;
|
||||
std::uint64_t encoded_bytes = 0;
|
||||
std::size_t frame_count = 0;
|
||||
};
|
||||
|
||||
struct DocumentFrameExportReadinessResult {
|
||||
RecordedDocumentFrameUploadResult recorded_upload {};
|
||||
DocumentFrameFacePngExportResult face_pngs {};
|
||||
@@ -187,6 +232,13 @@ export_document_frame_equirectangular_png(const DocumentFrameCompositeResult& co
|
||||
[[nodiscard]] pp::foundation::Result<DocumentFrameEquirectangularPngExportResult>
|
||||
export_document_frame_equirectangular_png(DocumentFrameCompositeRequest request);
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<DocumentLayerEquirectangularPngExportResult>
|
||||
export_document_layers_equirectangular_pngs(DocumentLayerEquirectangularPngExportRequest request);
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<DocumentAnimationFrameEquirectangularPngExportResult>
|
||||
export_document_animation_frames_equirectangular_pngs(
|
||||
DocumentAnimationFrameEquirectangularPngExportRequest request);
|
||||
|
||||
[[nodiscard]] pp::foundation::Result<DocumentFrameExportReadinessResult> prepare_document_frame_export_readiness(
|
||||
DocumentFrameCompositeRequest request);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user