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:
parent
7e5f1fa895
commit
e3509efc1b
6 changed files with 147 additions and 7 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue