Serenity Operating System
at master 149 lines 5.0 kB view raw
1/* 2 * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org> 4 * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> 5 * 6 * SPDX-License-Identifier: BSD-2-Clause 7 */ 8 9#pragma once 10 11#include "Selection.h" 12#include <AK/HashTable.h> 13#include <AK/JsonObjectSerializer.h> 14#include <AK/RefCounted.h> 15#include <AK/RefPtr.h> 16#include <AK/Result.h> 17#include <LibGUI/Command.h> 18#include <LibGUI/Forward.h> 19#include <LibGfx/Bitmap.h> 20#include <LibGfx/Forward.h> 21#include <LibGfx/Painter.h> 22#include <LibGfx/Rect.h> 23#include <LibGfx/Size.h> 24 25namespace PixelPaint { 26 27class Layer; 28class Selection; 29 30class ImageClient { 31public: 32 virtual void image_did_add_layer(size_t) { } 33 virtual void image_did_remove_layer(size_t) { } 34 virtual void image_did_modify_layer_properties(size_t) { } 35 virtual void image_did_modify_layer_bitmap(size_t) { } 36 virtual void image_did_modify_layer_stack() { } 37 virtual void image_did_change(Gfx::IntRect const&) { } 38 virtual void image_did_change_rect(Gfx::IntRect const&) { } 39 virtual void image_select_layer(Layer*) { } 40 41protected: 42 virtual ~ImageClient() = default; 43}; 44 45class Image : public RefCounted<Image> { 46public: 47 static ErrorOr<NonnullRefPtr<Image>> create_with_size(Gfx::IntSize); 48 static ErrorOr<NonnullRefPtr<Image>> create_from_pixel_paint_json(JsonObject const&); 49 static ErrorOr<NonnullRefPtr<Image>> create_from_bitmap(NonnullRefPtr<Gfx::Bitmap> const&); 50 51 static ErrorOr<NonnullRefPtr<Gfx::Bitmap>> decode_bitmap(ReadonlyBytes); 52 53 // This generates a new Bitmap with the final image (all layers composed according to their attributes.) 54 ErrorOr<NonnullRefPtr<Gfx::Bitmap>> compose_bitmap(Gfx::BitmapFormat format) const; 55 RefPtr<Gfx::Bitmap> copy_bitmap(Selection const&) const; 56 57 Selection& selection() { return m_selection; } 58 Selection const& selection() const { return m_selection; } 59 60 size_t layer_count() const { return m_layers.size(); } 61 Layer const& layer(size_t index) const { return m_layers.at(index); } 62 Layer& layer(size_t index) { return m_layers.at(index); } 63 64 Gfx::IntSize size() const { return m_size; } 65 Gfx::IntRect rect() const { return { {}, m_size }; } 66 67 void add_layer(NonnullRefPtr<Layer>); 68 ErrorOr<NonnullRefPtr<Image>> take_snapshot() const; 69 ErrorOr<void> restore_snapshot(Image const&); 70 71 void paint_into(GUI::Painter&, Gfx::IntRect const& dest_rect, float scale) const; 72 73 ErrorOr<void> serialize_as_json(JsonObjectSerializer<StringBuilder>& json) const; 74 ErrorOr<void> export_bmp_to_file(NonnullOwnPtr<Stream>, bool preserve_alpha_channel) const; 75 ErrorOr<void> export_png_to_file(NonnullOwnPtr<Stream>, bool preserve_alpha_channel) const; 76 ErrorOr<void> export_qoi_to_file(NonnullOwnPtr<Stream>) const; 77 78 void move_layer_to_front(Layer&); 79 void move_layer_to_back(Layer&); 80 void move_layer_up(Layer&); 81 void move_layer_down(Layer&); 82 void change_layer_index(size_t old_index, size_t new_index); 83 void remove_layer(Layer&); 84 void select_layer(Layer*); 85 ErrorOr<void> flatten_all_layers(); 86 ErrorOr<void> merge_visible_layers(); 87 ErrorOr<void> merge_active_layer_up(Layer& layer); 88 ErrorOr<void> merge_active_layer_down(Layer& layer); 89 90 void add_client(ImageClient&); 91 void remove_client(ImageClient&); 92 93 void layer_did_modify_bitmap(Badge<Layer>, Layer const&, Gfx::IntRect const& modified_layer_rect); 94 void layer_did_modify_properties(Badge<Layer>, Layer const&); 95 96 size_t index_of(Layer const&) const; 97 98 ErrorOr<void> flip(Gfx::Orientation orientation); 99 ErrorOr<void> rotate(Gfx::RotationDirection direction); 100 ErrorOr<void> crop(Gfx::IntRect const& rect); 101 ErrorOr<void> resize(Gfx::IntSize new_size, Gfx::Painter::ScalingMode scaling_mode); 102 103 Optional<Gfx::IntRect> nonempty_content_bounding_rect() const; 104 105 Color color_at(Gfx::IntPoint point) const; 106 107private: 108 enum class LayerMergeMode { 109 All, 110 VisibleOnly 111 }; 112 113 enum class LayerMergeDirection { 114 Up, 115 Down 116 }; 117 118 explicit Image(Gfx::IntSize); 119 120 void did_change(Gfx::IntRect const& modified_rect = {}); 121 void did_change_rect(Gfx::IntRect const& modified_rect = {}); 122 void did_modify_layer_stack(); 123 124 ErrorOr<void> merge_layers(LayerMergeMode); 125 ErrorOr<void> merge_active_layer(NonnullRefPtr<Layer> const&, LayerMergeDirection); 126 127 Gfx::IntSize m_size; 128 Vector<NonnullRefPtr<Layer>> m_layers; 129 130 HashTable<ImageClient*> m_clients; 131 132 Selection m_selection; 133}; 134 135class ImageUndoCommand : public GUI::Command { 136public: 137 ImageUndoCommand(Image&, DeprecatedString action_text); 138 139 virtual void undo() override; 140 virtual void redo() override; 141 virtual DeprecatedString action_text() const override { return m_action_text; } 142 143private: 144 RefPtr<Image> m_snapshot; 145 Image& m_image; 146 DeprecatedString m_action_text; 147}; 148 149}