Skip to content

Commit ee4ba76

Browse files
kalenikaliaksandrawesomekling
authored andcommitted
LibWeb: Fix clip of hidden overflow when translated boxes are involved
There is a problem with current approach where overflow clip rectange is calculated by aggregating intersection of absolute padding boxes of boxes in containing block chain that resulting rectangle doesn't respect transform properties. To solve this problem `PaintableBox` is changed to store clip rectangle saved from painter because it does respect transform properties of all previously applied clip rectangles.
1 parent b0846ec commit ee4ba76

File tree

3 files changed

+18
-24
lines changed

3 files changed

+18
-24
lines changed

Userland/Libraries/LibGfx/Painter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class Painter {
177177
}
178178

179179
IntRect clip_rect() const { return state().clip_rect; }
180+
void set_clip_rect(IntRect const& rect) { state().clip_rect = rect; }
180181

181182
int scale() const { return state().scale; }
182183

Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -313,24 +313,8 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders
313313
return border_radius_data;
314314
}
315315

316-
Optional<CSSPixelRect> PaintableBox::clip_rect() const
316+
Optional<Gfx::IntRect> PaintableBox::clip_rect() const
317317
{
318-
if (!m_clip_rect.has_value()) {
319-
if (containing_block() && containing_block()->paint_box())
320-
m_clip_rect = containing_block()->paint_box()->clip_rect();
321-
322-
auto overflow_x = computed_values().overflow_x();
323-
auto overflow_y = computed_values().overflow_y();
324-
325-
if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) {
326-
if (m_clip_rect.has_value()) {
327-
m_clip_rect->intersect(absolute_padding_box_rect());
328-
} else {
329-
m_clip_rect = absolute_padding_box_rect();
330-
}
331-
}
332-
}
333-
334318
return m_clip_rect;
335319
}
336320

@@ -339,27 +323,36 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase
339323
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
340324
return;
341325

342-
// FIXME: Support more overflow variations.
343-
auto clip_rect = this->clip_rect();
326+
auto clip_rect = context.painter().clip_rect();
327+
if (containing_block() && containing_block()->paint_box()) {
328+
if (containing_block()->paint_box()->clip_rect().has_value()) {
329+
clip_rect = *containing_block()->paint_box()->clip_rect();
330+
}
331+
}
332+
context.painter().set_clip_rect(clip_rect);
333+
344334
auto overflow_x = computed_values().overflow_x();
345335
auto overflow_y = computed_values().overflow_y();
346336

347337
auto clip_overflow = [&] {
348338
if (!m_clipping_overflow) {
349339
context.painter().save();
350-
context.painter().add_clip_rect(context.rounded_device_rect(*clip_rect).to_type<int>());
340+
context.painter().add_clip_rect(context.rounded_device_rect(absolute_padding_box_rect()).to_type<int>());
351341
m_clipping_overflow = true;
352342
}
353343
};
354344

355-
if (clip_rect.has_value()) {
345+
// FIXME: Support more overflow variations.
346+
if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) {
356347
clip_overflow();
357348
}
358349

350+
m_clip_rect = context.painter().clip_rect();
351+
359352
if (overflow_y == CSS::Overflow::Hidden || overflow_x == CSS::Overflow::Hidden) {
360353
auto border_radii_data = normalized_border_radii_data(ShrinkRadiiForBorders::Yes);
361354
if (border_radii_data.has_any_radius()) {
362-
auto corner_clipper = BorderRadiusCornerClipper::create(context, context.rounded_device_rect(*clip_rect), border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No);
355+
auto corner_clipper = BorderRadiusCornerClipper::create(context, context.rounded_device_rect(absolute_padding_box_rect()), border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No);
363356
if (corner_clipper.is_error()) {
364357
dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error());
365358
return;

Userland/Libraries/LibWeb/Painting/PaintableBox.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class PaintableBox : public Paintable {
9898
return m_overflow_data->scrollable_overflow_rect;
9999
}
100100

101-
Optional<CSSPixelRect> clip_rect() const;
101+
Optional<Gfx::IntRect> clip_rect() const;
102102

103103
void set_overflow_data(Optional<OverflowData> data) { m_overflow_data = move(data); }
104104
void set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoordinate>);
@@ -157,7 +157,7 @@ class PaintableBox : public Paintable {
157157
Optional<CSSPixelRect> mutable m_absolute_rect;
158158
Optional<CSSPixelRect> mutable m_absolute_paint_rect;
159159

160-
Optional<CSSPixelRect> mutable m_clip_rect;
160+
Gfx::IntRect mutable m_clip_rect;
161161

162162
mutable bool m_clipping_overflow { false };
163163
Optional<BorderRadiusCornerClipper> mutable m_overflow_corner_radius_clipper;

0 commit comments

Comments
 (0)