mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:37:35 +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:
parent
b9ad6058aa
commit
42cb38b71a
2 changed files with 21 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -118,8 +118,9 @@ public:
|
|||
|
||||
void open_menubar_menu(Menu&);
|
||||
|
||||
static void paint_simple_rect_shadow(Gfx::Painter&, const Gfx::IntRect&, const Gfx::Bitmap&, bool shadow_includes_frame = false, bool fill_content = false);
|
||||
|
||||
private:
|
||||
void paint_simple_rect_shadow(Gfx::Painter&, const Gfx::IntRect&, const Gfx::Bitmap&) const;
|
||||
void paint_notification_frame(Gfx::Painter&);
|
||||
void paint_normal_frame(Gfx::Painter&);
|
||||
void paint_tool_window_frame(Gfx::Painter&);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue