1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:17:44 +00:00

PixelPaint: Introduce new mask features

This patch adds a new Editing-Mask type to layers. This kind of mask
is used to restrict changes on the content bitmap only to areas where
the mask is drawn. The intensity of a pixel change is controlled by the
alpha-value of the mask.

Furthermore a function to invert and clear masks has been introduced.
When a new mask is created for a layer the edit mode of the layer is
also changed to Mask so that the user can immediately start to draw the
mask.
This commit is contained in:
Torstennator 2023-05-12 16:07:51 +02:00 committed by Jelle Raaijmakers
parent 7e5f1fa895
commit e3509efc1b
6 changed files with 147 additions and 7 deletions

View file

@ -44,6 +44,7 @@ ErrorOr<NonnullRefPtr<Layer>> Layer::create_snapshot(Image& image, Layer const&
if (layer.is_masked()) {
snapshot->m_mask_bitmap = TRY(layer.mask_bitmap()->clone());
snapshot->m_edit_mode = layer.m_edit_mode;
snapshot->m_mask_type = layer.m_mask_type;
}
/*
@ -273,7 +274,7 @@ ErrorOr<void> Layer::scale(Gfx::IntRect const& new_rect, Gfx::Painter::ScalingMo
void Layer::update_cached_bitmap()
{
if (!is_masked()) {
if (mask_type() == MaskType::None || mask_type() == MaskType::EditingMask) {
if (m_content_bitmap.ptr() == m_cached_display_bitmap.ptr())
return;
m_cached_display_bitmap = m_content_bitmap;
@ -296,10 +297,23 @@ void Layer::update_cached_bitmap()
}
}
ErrorOr<void> Layer::create_mask()
ErrorOr<void> Layer::create_mask(MaskType type)
{
m_mask_bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size()));
m_mask_bitmap->fill(Gfx::Color::White);
m_mask_type = type;
switch (type) {
case MaskType::BasicMask:
m_mask_bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, size()));
m_mask_bitmap->fill(Gfx::Color::White);
break;
case MaskType::EditingMask:
m_mask_bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, size()));
break;
case MaskType::None:
VERIFY_NOT_REACHED();
}
set_edit_mode(EditMode::Mask);
update_cached_bitmap();
return {};
}
@ -307,6 +321,7 @@ ErrorOr<void> Layer::create_mask()
void Layer::delete_mask()
{
m_mask_bitmap = nullptr;
m_mask_type = MaskType::None;
set_edit_mode(EditMode::Content);
update_cached_bitmap();
}
@ -319,6 +334,38 @@ void Layer::apply_mask()
delete_mask();
}
void Layer::invert_mask()
{
VERIFY(mask_type() != MaskType::None);
for (int y = 0; y < size().height(); ++y) {
for (int x = 0; x < size().width(); ++x) {
auto inverted_mask_color = m_mask_bitmap->get_pixel(x, y).inverted();
if (mask_type() == MaskType::EditingMask)
inverted_mask_color.set_alpha(255 - inverted_mask_color.alpha());
m_mask_bitmap->set_pixel(x, y, inverted_mask_color);
}
}
update_cached_bitmap();
}
void Layer::clear_mask()
{
switch (mask_type()) {
case MaskType::None:
VERIFY_NOT_REACHED();
case MaskType::BasicMask:
m_mask_bitmap->fill(Gfx::Color::White);
break;
case MaskType::EditingMask:
m_mask_bitmap->fill(Gfx::Color::Transparent);
break;
}
update_cached_bitmap();
}
Gfx::Bitmap& Layer::currently_edited_bitmap()
{
switch (edit_mode()) {
@ -410,4 +457,11 @@ ErrorOr<NonnullRefPtr<Layer>> Layer::duplicate(DeprecatedString name)
return duplicated_layer;
}
Layer::MaskType Layer::mask_type()
{
if (m_mask_bitmap.is_null())
return MaskType::None;
return m_mask_type;
}
}