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

WindowServer: Enhance simple shadow function to include optional frame

If the shadow bitmap contains portions of the frame then we need to
slightly tweak the logic dealing with very small width and/or height.
This commit is contained in:
Tom 2021-06-25 09:09:41 -06:00 committed by Andreas Kling
parent b9ad6058aa
commit 42cb38b71a
2 changed files with 21 additions and 10 deletions

View file

@ -884,7 +884,7 @@ void WindowFrame::start_flash_animation()
m_flash_timer->start();
}
void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::IntRect& containing_rect, const Gfx::Bitmap& shadow_bitmap) const
void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::IntRect& containing_rect, const Gfx::Bitmap& shadow_bitmap, bool shadow_includes_frame, bool fill_content)
{
// The layout of the shadow_bitmap is defined like this:
// +---------+----+---------+----+----+----+
@ -902,6 +902,7 @@ void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::Int
// The height divided by two defines a cell size, and width of each
// column must be the same as the height of the cell, except for the
// first an third column, which are twice as wide.
// If fill_content is true, it will use the RGBA color of right-bottom pixel of TL to fill the rectangle enclosed
if (shadow_bitmap.height() % 2 != 0) {
dbgln("Can't paint simple rect shadow, shadow bitmap height {} is not even", shadow_bitmap.height());
return;
@ -923,21 +924,21 @@ void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::Int
auto containing_horizontal_rect = containing_rect;
int horizontal_shift = 0;
if (half_height < base_size) {
// If the height is too small we need to shift the left/right accordingly
if (half_height < base_size && !shadow_includes_frame) {
// If the height is too small we need to shift the left/right accordingly, unless the shadow includes portions of the frame
horizontal_shift = base_size - half_height;
containing_horizontal_rect.set_left(containing_horizontal_rect.left() + horizontal_shift);
containing_horizontal_rect.set_right(containing_horizontal_rect.right() - 2 * horizontal_shift);
}
auto half_width = containing_horizontal_rect.width() / 2;
int corner_piece_width = min(containing_horizontal_rect.width() / 2, base_size * 2);
int left_corners_right = containing_horizontal_rect.left() + corner_piece_width;
int right_corners_left = max(containing_horizontal_rect.right() - corner_piece_width + 1, left_corners_right + 1);
auto paint_horizontal = [&](int y, int src_row) {
if (half_width <= 0)
return;
Gfx::PainterStateSaver save(painter);
painter.add_clip_rect({ containing_horizontal_rect.left(), y, containing_horizontal_rect.width(), base_size });
int corner_piece_width = min(containing_horizontal_rect.width() / 2, base_size * 2);
int left_corners_right = containing_horizontal_rect.left() + corner_piece_width;
int right_corners_left = max(containing_horizontal_rect.right() - corner_piece_width + 1, left_corners_right + 1);
painter.blit({ containing_horizontal_rect.left(), y }, shadow_bitmap, { 0, src_row * base_size, corner_piece_width, base_size });
painter.blit({ right_corners_left, y }, shadow_bitmap, { 5 * base_size - corner_piece_width, src_row * base_size, corner_piece_width, base_size });
for (int x = left_corners_right; x < right_corners_left; x += base_size) {
@ -949,12 +950,12 @@ void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::Int
paint_horizontal(containing_rect.top(), 0);
paint_horizontal(containing_rect.bottom() - base_size + 1, 1);
int corner_piece_height = min(half_height, base_size);
int top_corners_bottom = base_size + corner_piece_height;
int bottom_corners_top = base_size + max(half_height, sides_height - corner_piece_height);
auto paint_vertical = [&](int x, int src_row, int hshift, int hsrcshift) {
Gfx::PainterStateSaver save(painter);
painter.add_clip_rect({ x, containing_rect.y() + base_size, base_size, containing_rect.height() - 2 * base_size });
int corner_piece_height = min(half_height, base_size);
int top_corners_bottom = base_size + corner_piece_height;
int bottom_corners_top = base_size + max(half_height, sides_height - corner_piece_height);
painter.blit({ x + hshift, containing_rect.top() + top_corners_bottom - corner_piece_height }, shadow_bitmap, { base_size * 5 + hsrcshift, src_row * base_size, base_size - hsrcshift, corner_piece_height });
painter.blit({ x + hshift, containing_rect.top() + bottom_corners_top }, shadow_bitmap, { base_size * 7 + hsrcshift, src_row * base_size + base_size - corner_piece_height, base_size - hsrcshift, corner_piece_height });
for (int y = top_corners_bottom; y < bottom_corners_top; y += base_size) {
@ -964,7 +965,16 @@ void WindowFrame::paint_simple_rect_shadow(Gfx::Painter& painter, const Gfx::Int
};
paint_vertical(containing_rect.left(), 0, horizontal_shift, 0);
if (shadow_includes_frame)
horizontal_shift = 0; // TODO: fix off-by-one on rectangles barely wide enough
paint_vertical(containing_rect.right() - base_size + 1, 1, 0, horizontal_shift);
if (fill_content) {
// Fill the enclosed rectangle with the RGBA color of the right-bottom pixel of the TL tile
auto inner_rect = containing_rect.shrunken(2 * base_size, 2 * base_size);
if (!inner_rect.is_empty())
painter.fill_rect(inner_rect, shadow_bitmap.get_pixel(2 * base_size - 1, base_size - 1));
}
}
int WindowFrame::menu_row_count() const