/* * Copyright (c) 2020-2021, Andreas Kling * Copyright (c) 2021-2022, Mustafa Quraish * Copyright (c) 2021, Tobias Christiansen * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include "Selection.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace PixelPaint { class Layer; class Selection; class ImageClient { public: virtual void image_did_add_layer(size_t) { } virtual void image_did_remove_layer(size_t) { } virtual void image_did_modify_layer_properties(size_t) { } virtual void image_did_modify_layer_bitmap(size_t) { } virtual void image_did_modify_layer_stack() { } virtual void image_did_change(Gfx::IntRect const&) { } virtual void image_did_change_rect(Gfx::IntRect const&) { } virtual void image_select_layer(Layer*) { } protected: virtual ~ImageClient() = default; }; class Image : public RefCounted { public: static ErrorOr> create_with_size(Gfx::IntSize); static ErrorOr> create_from_pixel_paint_json(JsonObject const&); static ErrorOr> create_from_bitmap(NonnullRefPtr const&); static ErrorOr> decode_bitmap(ReadonlyBytes); // This generates a new Bitmap with the final image (all layers composed according to their attributes.) ErrorOr> compose_bitmap(Gfx::BitmapFormat format) const; RefPtr copy_bitmap(Selection const&) const; Selection& selection() { return m_selection; } Selection const& selection() const { return m_selection; } size_t layer_count() const { return m_layers.size(); } Layer const& layer(size_t index) const { return m_layers.at(index); } Layer& layer(size_t index) { return m_layers.at(index); } Gfx::IntSize size() const { return m_size; } Gfx::IntRect rect() const { return { {}, m_size }; } void add_layer(NonnullRefPtr); void insert_layer(NonnullRefPtr, size_t index); ErrorOr> take_snapshot() const; ErrorOr restore_snapshot(Image const&); void paint_into(GUI::Painter&, Gfx::IntRect const& dest_rect, float scale) const; ErrorOr serialize_as_json(JsonObjectSerializer& json) const; ErrorOr export_bmp_to_file(NonnullOwnPtr, bool preserve_alpha_channel) const; ErrorOr export_png_to_file(NonnullOwnPtr, bool preserve_alpha_channel) const; ErrorOr export_qoi_to_file(NonnullOwnPtr) const; void move_layer_to_front(Layer&); void move_layer_to_back(Layer&); void move_layer_up(Layer&); void move_layer_down(Layer&); void change_layer_index(size_t old_index, size_t new_index); void remove_layer(Layer&); void select_layer(Layer*); ErrorOr flatten_all_layers(); ErrorOr merge_visible_layers(); ErrorOr merge_active_layer_up(Layer& layer); ErrorOr merge_active_layer_down(Layer& layer); void add_client(ImageClient&); void remove_client(ImageClient&); void layer_did_modify_bitmap(Badge, Layer const&, Gfx::IntRect const& modified_layer_rect); void layer_did_modify_properties(Badge, Layer const&); size_t index_of(Layer const&) const; ErrorOr flip(Gfx::Orientation orientation); ErrorOr rotate(Gfx::RotationDirection direction); ErrorOr crop(Gfx::IntRect const& rect); ErrorOr resize(Gfx::IntSize new_size, Gfx::Painter::ScalingMode scaling_mode); Optional nonempty_content_bounding_rect() const; Color color_at(Gfx::IntPoint point) const; private: enum class LayerMergeMode { All, VisibleOnly }; enum class LayerMergeDirection { Up, Down }; explicit Image(Gfx::IntSize); void did_change(Gfx::IntRect const& modified_rect = {}); void did_change_rect(Gfx::IntRect const& modified_rect = {}); void did_modify_layer_stack(); ErrorOr merge_layers(LayerMergeMode); ErrorOr merge_active_layer(NonnullRefPtr const&, LayerMergeDirection); Gfx::IntSize m_size; Vector> m_layers; HashTable m_clients; Selection m_selection; }; class ImageUndoCommand : public GUI::Command { public: ImageUndoCommand(Image&, DeprecatedString action_text); virtual void undo() override; virtual void redo() override; virtual DeprecatedString action_text() const override { return m_action_text; } private: RefPtr m_snapshot; Image& m_image; DeprecatedString m_action_text; }; }