mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:07:46 +00:00
LibWeb: Support overflow: hidden with a border-radius
Note: With this change the border-radius is clipped if ethier the overflow-x or overflow-y is hidden (it is a little unclear what happens if just one is set, but it seems like most browsers treat one set + border-radius the same as if overflow: hidden was set).
This commit is contained in:
parent
2ceb143571
commit
f283e0ddc5
2 changed files with 53 additions and 5 deletions
|
@ -246,17 +246,48 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) cons
|
||||||
{
|
{
|
||||||
// FIXME: Support more overflow variations.
|
// FIXME: Support more overflow variations.
|
||||||
auto clip_rect = absolute_padding_box_rect().to_rounded<int>();
|
auto clip_rect = absolute_padding_box_rect().to_rounded<int>();
|
||||||
if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
auto overflow_x = computed_values().overflow_x();
|
||||||
context.painter().save();
|
auto overflow_y = computed_values().overflow_y();
|
||||||
context.painter().add_clip_rect(clip_rect);
|
|
||||||
|
auto clip_overflow = [&] {
|
||||||
|
if (!m_clipping_overflow) {
|
||||||
|
context.painter().save();
|
||||||
|
context.painter().add_clip_rect(clip_rect);
|
||||||
|
m_clipping_overflow = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) {
|
||||||
|
clip_overflow();
|
||||||
|
}
|
||||||
|
if (overflow_y == CSS::Overflow::Hidden || overflow_x == CSS::Overflow::Hidden) {
|
||||||
|
auto border_radii_data = normalized_border_radii_data();
|
||||||
|
auto const& border = box_model().border;
|
||||||
|
border_radii_data.shrink(border.top, border.right, border.bottom, border.left);
|
||||||
|
if (border_radii_data.has_any_radius()) {
|
||||||
|
auto corner_clipper = BorderRadiusCornerClipper::create(clip_rect, border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No);
|
||||||
|
if (corner_clipper.is_error()) {
|
||||||
|
dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clip_overflow();
|
||||||
|
m_overflow_corner_radius_clipper = corner_clipper.release_value();
|
||||||
|
m_overflow_corner_radius_clipper->sample_under_corners(context.painter());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintableBox::after_children_paint(PaintContext& context, PaintPhase) const
|
void PaintableBox::after_children_paint(PaintContext& context, PaintPhase) const
|
||||||
{
|
{
|
||||||
// FIXME: Support more overflow variations.
|
// FIXME: Support more overflow variations.
|
||||||
if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden)
|
if (m_clipping_overflow) {
|
||||||
context.painter().restore();
|
context.painter().restore();
|
||||||
|
m_clipping_overflow = false;
|
||||||
|
}
|
||||||
|
if (m_overflow_corner_radius_clipper.has_value()) {
|
||||||
|
m_overflow_corner_radius_clipper->blit_corner_clipping(context.painter());
|
||||||
|
m_overflow_corner_radius_clipper = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment)
|
static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment)
|
||||||
|
@ -416,13 +447,24 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool should_clip_overflow = computed_values().overflow_x() != CSS::Overflow::Visible && computed_values().overflow_y() != CSS::Overflow::Visible;
|
bool should_clip_overflow = computed_values().overflow_x() != CSS::Overflow::Visible && computed_values().overflow_y() != CSS::Overflow::Visible;
|
||||||
|
Optional<BorderRadiusCornerClipper> corner_clipper;
|
||||||
|
|
||||||
if (should_clip_overflow) {
|
if (should_clip_overflow) {
|
||||||
context.painter().save();
|
context.painter().save();
|
||||||
// FIXME: Handle overflow-x and overflow-y being different values.
|
// FIXME: Handle overflow-x and overflow-y being different values.
|
||||||
context.painter().add_clip_rect(enclosing_int_rect(absolute_padding_box_rect()));
|
auto clip_box = absolute_padding_box_rect().to_rounded<int>();
|
||||||
|
context.painter().add_clip_rect(clip_box);
|
||||||
auto scroll_offset = static_cast<Layout::BlockContainer const&>(layout_box()).scroll_offset();
|
auto scroll_offset = static_cast<Layout::BlockContainer const&>(layout_box()).scroll_offset();
|
||||||
context.painter().translate(-scroll_offset.to_type<int>());
|
context.painter().translate(-scroll_offset.to_type<int>());
|
||||||
|
|
||||||
|
auto border_radii = normalized_border_radii_data();
|
||||||
|
if (border_radii.has_any_radius()) {
|
||||||
|
auto clipper = BorderRadiusCornerClipper::create(clip_box, border_radii);
|
||||||
|
if (!clipper.is_error()) {
|
||||||
|
corner_clipper = clipper.release_value();
|
||||||
|
corner_clipper->sample_under_corners(context.painter());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text shadows
|
// Text shadows
|
||||||
|
@ -470,6 +512,8 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
||||||
|
|
||||||
if (should_clip_overflow) {
|
if (should_clip_overflow) {
|
||||||
context.painter().restore();
|
context.painter().restore();
|
||||||
|
if (corner_clipper.has_value())
|
||||||
|
corner_clipper->blit_corner_clipping(context.painter());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Merge this loop with the above somehow..
|
// FIXME: Merge this loop with the above somehow..
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibWeb/Painting/BorderPainting.h>
|
#include <LibWeb/Painting/BorderPainting.h>
|
||||||
|
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
|
||||||
#include <LibWeb/Painting/Paintable.h>
|
#include <LibWeb/Painting/Paintable.h>
|
||||||
|
|
||||||
namespace Web::Painting {
|
namespace Web::Painting {
|
||||||
|
@ -135,6 +136,9 @@ private:
|
||||||
OwnPtr<Painting::StackingContext> m_stacking_context;
|
OwnPtr<Painting::StackingContext> m_stacking_context;
|
||||||
|
|
||||||
Optional<Gfx::FloatRect> mutable m_absolute_rect;
|
Optional<Gfx::FloatRect> mutable m_absolute_rect;
|
||||||
|
|
||||||
|
mutable bool m_clipping_overflow { false };
|
||||||
|
Optional<BorderRadiusCornerClipper> mutable m_overflow_corner_radius_clipper;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PaintableWithLines : public PaintableBox {
|
class PaintableWithLines : public PaintableBox {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue