mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:27:45 +00:00
LibWeb: Shrink border radii for background-clip and support with images
Since background layers can have different clipping this has also required doing the corner clipping for each layer, rather than just once.
This commit is contained in:
parent
0070c28714
commit
61b447e53f
1 changed files with 42 additions and 34 deletions
|
@ -20,28 +20,44 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
{
|
||||
auto& painter = context.painter();
|
||||
|
||||
auto get_box = [&](CSS::BackgroundBox box) {
|
||||
auto box_rect = border_rect;
|
||||
switch (box) {
|
||||
struct BackgroundBox {
|
||||
Gfx::FloatRect rect;
|
||||
BorderRadiiData radii;
|
||||
|
||||
inline void shrink(float top, float right, float bottom, float left)
|
||||
{
|
||||
rect.shrink(top, right, bottom, left);
|
||||
radii.shrink(top, right, bottom, left);
|
||||
}
|
||||
};
|
||||
|
||||
BackgroundBox border_box {
|
||||
border_rect,
|
||||
border_radii
|
||||
};
|
||||
|
||||
auto get_box = [&](CSS::BackgroundBox box_clip) {
|
||||
auto box = border_box;
|
||||
switch (box_clip) {
|
||||
case CSS::BackgroundBox::ContentBox: {
|
||||
auto& padding = layout_node.box_model().padding;
|
||||
box_rect.shrink(padding.top, padding.right, padding.bottom, padding.left);
|
||||
box.shrink(padding.top, padding.right, padding.bottom, padding.left);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case CSS::BackgroundBox::PaddingBox: {
|
||||
auto& border = layout_node.box_model().border;
|
||||
box_rect.shrink(border.top, border.right, border.bottom, border.left);
|
||||
box.shrink(border.top, border.right, border.bottom, border.left);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case CSS::BackgroundBox::BorderBox:
|
||||
default:
|
||||
return box_rect;
|
||||
return box;
|
||||
}
|
||||
};
|
||||
|
||||
auto color_rect = border_rect;
|
||||
auto color_box = border_box;
|
||||
if (background_layers && !background_layers->is_empty())
|
||||
color_rect = get_box(background_layers->last().clip);
|
||||
color_box = get_box(background_layers->last().clip);
|
||||
|
||||
auto layer_is_paintable = [&](auto& layer) {
|
||||
return layer.image && layer.image->bitmap();
|
||||
|
@ -57,24 +73,9 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
}
|
||||
}
|
||||
|
||||
Optional<BorderRadiusCornerClipper> corner_radius_clipper {};
|
||||
|
||||
if (border_radii.has_any_radius()) {
|
||||
if (!has_paintable_layers) {
|
||||
Gfx::AntiAliasingPainter aa_painter { painter };
|
||||
aa_painter.fill_rect_with_rounded_corners(color_rect.to_rounded<int>(),
|
||||
background_color, border_radii.top_left.as_corner(), border_radii.top_right.as_corner(), border_radii.bottom_right.as_corner(), border_radii.bottom_left.as_corner());
|
||||
return;
|
||||
}
|
||||
auto clipper = BorderRadiusCornerClipper::create(border_rect.to_rounded<int>(), border_radii);
|
||||
if (!clipper.is_error())
|
||||
corner_radius_clipper = clipper.release_value();
|
||||
}
|
||||
|
||||
if (corner_radius_clipper.has_value())
|
||||
corner_radius_clipper->sample_under_corners(painter);
|
||||
|
||||
painter.fill_rect(color_rect.to_rounded<int>(), background_color);
|
||||
aa_painter.fill_rect_with_rounded_corners(color_box.rect.to_rounded<int>(),
|
||||
background_color, color_box.radii.top_left.as_corner(), color_box.radii.top_right.as_corner(), color_box.radii.bottom_right.as_corner(), color_box.radii.bottom_left.as_corner());
|
||||
|
||||
if (!has_paintable_layers)
|
||||
return;
|
||||
|
@ -84,12 +85,21 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
// TODO: Gradients!
|
||||
if (!layer_is_paintable(layer))
|
||||
continue;
|
||||
Gfx::PainterStateSaver state { painter };
|
||||
auto& image = *layer.image->bitmap();
|
||||
|
||||
// Clip
|
||||
auto clip_rect = get_box(layer.clip);
|
||||
painter.save();
|
||||
painter.add_clip_rect(clip_rect.to_rounded<int>());
|
||||
Optional<BorderRadiusCornerClipper> corner_radius_clipper {};
|
||||
auto clip_box = get_box(layer.clip);
|
||||
auto clip_rect = clip_box.rect.to_rounded<int>();
|
||||
if (clip_box.radii.has_any_radius()) {
|
||||
auto clipper = BorderRadiusCornerClipper::create(clip_rect, clip_box.radii);
|
||||
if (!clipper.is_error()) {
|
||||
corner_radius_clipper = clipper.release_value();
|
||||
corner_radius_clipper->sample_under_corners(painter);
|
||||
}
|
||||
}
|
||||
painter.add_clip_rect(clip_rect);
|
||||
|
||||
Gfx::FloatRect background_positioning_area;
|
||||
|
||||
|
@ -100,7 +110,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
break;
|
||||
case CSS::BackgroundAttachment::Local:
|
||||
case CSS::BackgroundAttachment::Scroll:
|
||||
background_positioning_area = get_box(layer.origin);
|
||||
background_positioning_area = get_box(layer.origin).rect;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -283,11 +293,9 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
|||
image_y += y_step;
|
||||
}
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
if (corner_radius_clipper.has_value())
|
||||
corner_radius_clipper->blit_corner_clipping(painter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue