mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:02:43 +00:00 
			
		
		
		
	LibWeb: Don't clip to containing block when painting abspos descendants
This commit is contained in:
		
							parent
							
								
									f941b7aefe
								
							
						
					
					
						commit
						63c727a4a3
					
				
					 10 changed files with 37 additions and 25 deletions
				
			
		|  | @ -83,8 +83,13 @@ public: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     virtual void paint(PaintContext&, PaintPhase) const { } |     virtual void paint(PaintContext&, PaintPhase) const { } | ||||||
|     virtual void before_children_paint(PaintContext&, PaintPhase) const { } | 
 | ||||||
|     virtual void after_children_paint(PaintContext&, PaintPhase) const { } |     enum class ShouldClipOverflow { | ||||||
|  |         No, | ||||||
|  |         Yes | ||||||
|  |     }; | ||||||
|  |     virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const { } | ||||||
|  |     virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const { } | ||||||
| 
 | 
 | ||||||
|     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const; |     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -257,11 +257,14 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders | ||||||
|     return border_radius_data; |     return border_radius_data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase) const | void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground)) |     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground)) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     if (should_clip_overflow == ShouldClipOverflow::No) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     // 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>(); | ||||||
|     auto overflow_x = computed_values().overflow_x(); |     auto overflow_x = computed_values().overflow_x(); | ||||||
|  | @ -293,11 +296,14 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase) const | void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground)) |     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground)) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     if (should_clip_overflow == ShouldClipOverflow::No) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     // FIXME: Support more overflow variations.
 |     // FIXME: Support more overflow variations.
 | ||||||
|     if (m_clipping_overflow) { |     if (m_clipping_overflow) { | ||||||
|         context.painter().restore(); |         context.painter().restore(); | ||||||
|  |  | ||||||
|  | @ -107,8 +107,8 @@ public: | ||||||
|     DOM::Document const& document() const { return layout_box().document(); } |     DOM::Document const& document() const { return layout_box().document(); } | ||||||
|     DOM::Document& document() { return layout_box().document(); } |     DOM::Document& document() { return layout_box().document(); } | ||||||
| 
 | 
 | ||||||
|     virtual void before_children_paint(PaintContext&, PaintPhase) const override; |     virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
|     virtual void after_children_paint(PaintContext&, PaintPhase) const override; |     virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
| 
 | 
 | ||||||
|     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const override; |     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,9 +19,9 @@ Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const | ||||||
|     return static_cast<Layout::SVGGraphicsBox const&>(layout_node()); |     return static_cast<Layout::SVGGraphicsBox const&>(layout_node()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const | void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     SVGPaintable::before_children_paint(context, phase); |     SVGPaintable::before_children_paint(context, phase, should_clip_overflow); | ||||||
|     if (phase != PaintPhase::Foreground) |     if (phase != PaintPhase::Foreground) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ namespace Web::Painting { | ||||||
| 
 | 
 | ||||||
| class SVGGraphicsPaintable : public SVGPaintable { | class SVGGraphicsPaintable : public SVGPaintable { | ||||||
| public: | public: | ||||||
|     virtual void before_children_paint(PaintContext&, PaintPhase) const override; |     virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
| 
 | 
 | ||||||
|     Layout::SVGGraphicsBox const& layout_box() const; |     Layout::SVGGraphicsBox const& layout_box() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -20,17 +20,17 @@ Layout::SVGBox const& SVGPaintable::layout_box() const | ||||||
|     return static_cast<Layout::SVGBox const&>(layout_node()); |     return static_cast<Layout::SVGBox const&>(layout_node()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const | void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     PaintableBox::before_children_paint(context, phase); |     PaintableBox::before_children_paint(context, phase, should_clip_overflow); | ||||||
|     if (phase != PaintPhase::Foreground) |     if (phase != PaintPhase::Foreground) | ||||||
|         return; |         return; | ||||||
|     context.svg_context().save(); |     context.svg_context().save(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const | void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     PaintableBox::after_children_paint(context, phase); |     PaintableBox::after_children_paint(context, phase, should_clip_overflow); | ||||||
|     if (phase != PaintPhase::Foreground) |     if (phase != PaintPhase::Foreground) | ||||||
|         return; |         return; | ||||||
|     context.svg_context().restore(); |     context.svg_context().restore(); | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ namespace Web::Painting { | ||||||
| 
 | 
 | ||||||
| class SVGPaintable : public PaintableBox { | class SVGPaintable : public PaintableBox { | ||||||
| public: | public: | ||||||
|     virtual void before_children_paint(PaintContext&, PaintPhase) const override; |     virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
|     virtual void after_children_paint(PaintContext&, PaintPhase) const override; |     virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
| 
 | 
 | ||||||
|     Layout::SVGBox const& layout_box() const; |     Layout::SVGBox const& layout_box() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const | ||||||
|     return static_cast<Layout::SVGSVGBox const&>(layout_node()); |     return static_cast<Layout::SVGSVGBox const&>(layout_node()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const | void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     if (phase != PaintPhase::Foreground) |     if (phase != PaintPhase::Foreground) | ||||||
|         return; |         return; | ||||||
|  | @ -32,12 +32,12 @@ void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase ph | ||||||
|     if (!context.has_svg_context()) |     if (!context.has_svg_context()) | ||||||
|         context.set_svg_context(SVGContext(absolute_rect())); |         context.set_svg_context(SVGContext(absolute_rect())); | ||||||
| 
 | 
 | ||||||
|     PaintableBox::before_children_paint(context, phase); |     PaintableBox::before_children_paint(context, phase, should_clip_overflow); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const | void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const | ||||||
| { | { | ||||||
|     PaintableBox::after_children_paint(context, phase); |     PaintableBox::after_children_paint(context, phase, should_clip_overflow); | ||||||
|     if (phase != PaintPhase::Foreground) |     if (phase != PaintPhase::Foreground) | ||||||
|         return; |         return; | ||||||
|     context.clear_svg_context(); |     context.clear_svg_context(); | ||||||
|  |  | ||||||
|  | @ -15,8 +15,8 @@ class SVGSVGPaintable : public PaintableBox { | ||||||
| public: | public: | ||||||
|     static NonnullRefPtr<SVGSVGPaintable> create(Layout::SVGSVGBox const&); |     static NonnullRefPtr<SVGSVGPaintable> create(Layout::SVGSVGBox const&); | ||||||
| 
 | 
 | ||||||
|     virtual void before_children_paint(PaintContext&, PaintPhase) const override; |     virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
|     virtual void after_children_paint(PaintContext&, PaintPhase) const override; |     virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; | ||||||
| 
 | 
 | ||||||
|     Layout::SVGSVGBox const& layout_box() const; |     Layout::SVGSVGBox const& layout_box() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas | ||||||
| void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const | void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const | ||||||
| { | { | ||||||
|     if (auto* paintable = box.paintable()) |     if (auto* paintable = box.paintable()) | ||||||
|         paintable->before_children_paint(context, to_paint_phase(phase)); |         paintable->before_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes); | ||||||
| 
 | 
 | ||||||
|     box.for_each_child([&](auto& child) { |     box.for_each_child([&](auto& child) { | ||||||
|         // If `child` establishes its own stacking context, skip over it.
 |         // If `child` establishes its own stacking context, skip over it.
 | ||||||
|  | @ -123,7 +123,7 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (auto* paintable = box.paintable()) |     if (auto* paintable = box.paintable()) | ||||||
|         paintable->after_children_paint(context, to_paint_phase(phase)); |         paintable->after_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StackingContext::paint_internal(PaintContext& context) const | void StackingContext::paint_internal(PaintContext& context) const | ||||||
|  | @ -135,12 +135,13 @@ void StackingContext::paint_internal(PaintContext& context) const | ||||||
| 
 | 
 | ||||||
|     auto paint_child = [&](auto* child) { |     auto paint_child = [&](auto* child) { | ||||||
|         auto parent = child->m_box.parent(); |         auto parent = child->m_box.parent(); | ||||||
|  |         auto should_clip_overflow = child->m_box.is_positioned() ? Paintable::ShouldClipOverflow::No : Paintable::ShouldClipOverflow::Yes; | ||||||
|         auto* paintable = parent ? parent->paintable() : nullptr; |         auto* paintable = parent ? parent->paintable() : nullptr; | ||||||
|         if (paintable) |         if (paintable) | ||||||
|             paintable->before_children_paint(context, PaintPhase::Foreground); |             paintable->before_children_paint(context, PaintPhase::Foreground, should_clip_overflow); | ||||||
|         child->paint(context); |         child->paint(context); | ||||||
|         if (paintable) |         if (paintable) | ||||||
|             paintable->after_children_paint(context, PaintPhase::Foreground); |             paintable->after_children_paint(context, PaintPhase::Foreground, should_clip_overflow); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     // Draw positioned descendants with negative z-indices (step 3)
 |     // Draw positioned descendants with negative z-indices (step 3)
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling