117 lines
4.4 KiB
C++
117 lines
4.4 KiB
C++
#pragma once
|
|
|
|
#include "foundation/result.h"
|
|
#include "paint/blend.h"
|
|
|
|
#include <cstdint>
|
|
#include <span>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace pp::document {
|
|
|
|
constexpr std::uint32_t max_canvas_dimension = 131072;
|
|
constexpr std::uint32_t max_layer_count = 1024;
|
|
constexpr std::uint32_t max_frame_count = 100000;
|
|
constexpr std::uint32_t min_frame_duration_ms = 1;
|
|
constexpr std::size_t min_document_history_entries = 2;
|
|
constexpr std::size_t max_document_history_entries = 10000;
|
|
constexpr std::size_t max_layer_name_length = 128;
|
|
|
|
struct DocumentConfig {
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
std::uint32_t layer_count = 1;
|
|
};
|
|
|
|
struct Layer {
|
|
std::string name;
|
|
bool visible = true;
|
|
bool alpha_locked = false;
|
|
float opacity = 1.0F;
|
|
pp::paint::BlendMode blend_mode = pp::paint::BlendMode::normal;
|
|
};
|
|
|
|
struct AnimationFrame {
|
|
std::uint32_t duration_ms = 100;
|
|
};
|
|
|
|
struct DocumentLayerConfig {
|
|
std::string_view name;
|
|
bool visible = true;
|
|
bool alpha_locked = false;
|
|
float opacity = 1.0F;
|
|
pp::paint::BlendMode blend_mode = pp::paint::BlendMode::normal;
|
|
};
|
|
|
|
struct DocumentSnapshotConfig {
|
|
std::uint32_t width = 0;
|
|
std::uint32_t height = 0;
|
|
std::span<const DocumentLayerConfig> layers;
|
|
std::span<const AnimationFrame> frames;
|
|
};
|
|
|
|
class CanvasDocument {
|
|
public:
|
|
[[nodiscard]] static pp::foundation::Result<CanvasDocument> create(DocumentConfig config);
|
|
[[nodiscard]] static pp::foundation::Result<CanvasDocument> create_from_snapshot(DocumentSnapshotConfig config);
|
|
|
|
[[nodiscard]] std::uint32_t width() const noexcept;
|
|
[[nodiscard]] std::uint32_t height() const noexcept;
|
|
[[nodiscard]] std::size_t active_layer_index() const noexcept;
|
|
[[nodiscard]] std::size_t active_frame_index() const noexcept;
|
|
[[nodiscard]] std::uint64_t animation_duration_ms() const noexcept;
|
|
[[nodiscard]] std::span<const Layer> layers() const noexcept;
|
|
[[nodiscard]] std::span<const AnimationFrame> frames() const noexcept;
|
|
|
|
[[nodiscard]] pp::foundation::Result<std::size_t> add_layer(std::string_view name);
|
|
[[nodiscard]] pp::foundation::Status remove_layer(std::size_t index);
|
|
[[nodiscard]] pp::foundation::Status move_layer(std::size_t from, std::size_t to);
|
|
[[nodiscard]] pp::foundation::Status set_active_layer(std::size_t index) noexcept;
|
|
[[nodiscard]] pp::foundation::Status rename_layer(std::size_t index, std::string_view name);
|
|
[[nodiscard]] pp::foundation::Status set_layer_visible(std::size_t index, bool visible) noexcept;
|
|
[[nodiscard]] pp::foundation::Status set_layer_alpha_locked(std::size_t index, bool alpha_locked) noexcept;
|
|
[[nodiscard]] pp::foundation::Status set_layer_opacity(std::size_t index, float opacity) noexcept;
|
|
[[nodiscard]] pp::foundation::Status set_layer_blend_mode(std::size_t index, pp::paint::BlendMode blend_mode) noexcept;
|
|
|
|
[[nodiscard]] pp::foundation::Result<std::size_t> add_frame(std::uint32_t duration_ms);
|
|
[[nodiscard]] pp::foundation::Result<std::size_t> duplicate_frame(std::size_t index);
|
|
[[nodiscard]] pp::foundation::Status remove_frame(std::size_t index);
|
|
[[nodiscard]] pp::foundation::Status move_frame(std::size_t from, std::size_t to);
|
|
[[nodiscard]] pp::foundation::Status set_frame_duration(std::size_t index, std::uint32_t duration_ms) noexcept;
|
|
[[nodiscard]] pp::foundation::Status set_active_frame(std::size_t index) noexcept;
|
|
|
|
private:
|
|
std::uint32_t width_ = 0;
|
|
std::uint32_t height_ = 0;
|
|
std::size_t active_layer_index_ = 0;
|
|
std::size_t active_frame_index_ = 0;
|
|
std::vector<Layer> layers_;
|
|
std::vector<AnimationFrame> frames_;
|
|
};
|
|
|
|
class DocumentHistory {
|
|
public:
|
|
[[nodiscard]] static pp::foundation::Result<DocumentHistory> create(
|
|
CanvasDocument initial_document,
|
|
std::size_t max_entries = 256);
|
|
|
|
[[nodiscard]] const CanvasDocument& current() const noexcept;
|
|
[[nodiscard]] std::size_t size() const noexcept;
|
|
[[nodiscard]] std::size_t current_index() const noexcept;
|
|
[[nodiscard]] bool can_undo() const noexcept;
|
|
[[nodiscard]] bool can_redo() const noexcept;
|
|
|
|
[[nodiscard]] pp::foundation::Status apply(CanvasDocument next_document);
|
|
[[nodiscard]] pp::foundation::Status undo() noexcept;
|
|
[[nodiscard]] pp::foundation::Status redo() noexcept;
|
|
|
|
private:
|
|
std::size_t max_entries_ = 0;
|
|
std::size_t current_index_ = 0;
|
|
std::vector<CanvasDocument> entries_;
|
|
};
|
|
|
|
}
|