1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 20:47:43 +00:00
serenity/Userland/Applications/PixelPaint/Layer.h
Timothy Slater 0d7d759095 PixelPaint: Limit editing tools to selection
This effectively creates a double-buffer for tools to use when modifying
the layer's bitmap (content or mask). Once the changes have been made
the tool reports to the layer that it has made changes along with a Rect
of the changed region. The layer will then merge the changes from the
scratch image to the real bitmap. This merge is done as follows: If a
given pixel is inside the selected region, the pixel from the scratch
bitmap is copied to the real bitmap. If the pixel is not inside the
selected region, the pixel from the real bitmap is copied to the scratch
bitmap.

As an optimization, when there is no selection active, the new method
for getting the scratch bitmap will return the real bitmap and no
merging will need to take place.
2022-10-24 23:46:22 +01:00

121 lines
3.7 KiB
C++

/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Noncopyable.h>
#include <AK/RefCounted.h>
#include <AK/String.h>
#include <AK/Weakable.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Painter.h>
namespace PixelPaint {
class Image;
class Selection;
class Layer
: public RefCounted<Layer>
, public Weakable<Layer> {
AK_MAKE_NONCOPYABLE(Layer);
AK_MAKE_NONMOVABLE(Layer);
public:
static ErrorOr<NonnullRefPtr<Layer>> try_create_with_size(Image&, Gfx::IntSize const&, String name);
static ErrorOr<NonnullRefPtr<Layer>> try_create_with_bitmap(Image&, NonnullRefPtr<Gfx::Bitmap>, String name);
static ErrorOr<NonnullRefPtr<Layer>> try_create_snapshot(Image&, Layer const&);
~Layer() = default;
Gfx::IntPoint const& location() const { return m_location; }
void set_location(Gfx::IntPoint const& location) { m_location = location; }
Gfx::Bitmap const& display_bitmap() const { return m_cached_display_bitmap; }
Gfx::Bitmap const& content_bitmap() const { return m_content_bitmap; }
Gfx::Bitmap& content_bitmap() { return m_content_bitmap; }
Gfx::Bitmap const* mask_bitmap() const { return m_mask_bitmap; }
Gfx::Bitmap* mask_bitmap() { return m_mask_bitmap; }
void create_mask();
Gfx::Bitmap& get_scratch_edited_bitmap();
Gfx::IntSize size() const { return content_bitmap().size(); }
Gfx::IntRect relative_rect() const { return { location(), size() }; }
Gfx::IntRect rect() const { return { {}, size() }; }
String const& name() const { return m_name; }
void set_name(String);
void flip(Gfx::Orientation orientation);
void rotate(Gfx::RotationDirection direction);
void crop(Gfx::IntRect const& rect);
void resize(Gfx::IntSize const& new_size, Gfx::Painter::ScalingMode scaling_mode);
void resize(Gfx::IntRect const& new_rect, Gfx::Painter::ScalingMode scaling_mode);
void resize(Gfx::IntSize const& new_size, Gfx::IntPoint const& new_location, Gfx::Painter::ScalingMode scaling_mode);
Optional<Gfx::IntRect> nonempty_content_bounding_rect() const;
ErrorOr<void> try_set_bitmaps(NonnullRefPtr<Gfx::Bitmap> content, RefPtr<Gfx::Bitmap> mask);
void did_modify_bitmap(Gfx::IntRect const& = {});
void set_selected(bool selected) { m_selected = selected; }
bool is_selected() const { return m_selected; }
bool is_visible() const { return m_visible; }
void set_visible(bool visible);
int opacity_percent() const { return m_opacity_percent; }
void set_opacity_percent(int);
RefPtr<Gfx::Bitmap> try_copy_bitmap(Selection const&) const;
Image const& image() const { return m_image; }
void erase_selection(Selection const&);
bool is_masked() const { return !m_mask_bitmap.is_null(); }
enum class EditMode {
Content,
Mask,
};
EditMode edit_mode() { return m_edit_mode; }
void set_edit_mode(EditMode mode);
Gfx::Bitmap& currently_edited_bitmap();
private:
Layer(Image&, NonnullRefPtr<Gfx::Bitmap>, String name);
Image& m_image;
String m_name;
Gfx::IntPoint m_location;
NonnullRefPtr<Gfx::Bitmap> m_content_bitmap;
RefPtr<Gfx::Bitmap> m_scratch_edited_bitmap { nullptr };
RefPtr<Gfx::Bitmap> m_mask_bitmap { nullptr };
NonnullRefPtr<Gfx::Bitmap> m_cached_display_bitmap;
bool m_selected { false };
bool m_visible { true };
int m_opacity_percent { 100 };
EditMode m_edit_mode { EditMode::Content };
void update_cached_bitmap();
};
}