LibWeb: Replace InlinePaintable with PaintableWithLines created per line

InlinePaintable was an ad-hoc paintable type required to support the
fragmentation of inline nodes across multiple lines. It existed because
there was no way to associate multiple paintables with a single layout
node. This resulted in a lot of duplicated code between PaintableBox and
InlinePaintable. For example, most of the CSS properties like
background, border, shadows, etc. and hit-testing are almost identical
for both of them. However, the code had to be duplicated to account for
the fact that InlinePaintable creates a box for each line. And we had
quite many places that operate on paintables with a code like:
```
if (box.is_paintable_box()) {
  // do something
} else (box.is_inline_paintable()) {
  // do exactly the same as for paintable box but using InlinePaintable
}
```

This change replaces the usage of `InlinePaintable` with
`PaintableWithLines` created for each line, which is now possible
because we support having multiple paintables per layout node. By doing
that, we remove lots of duplicated code and bring our implementation
closer to the spec.
This commit is contained in:
Aliaksandr Kalenik 2024-10-13 21:29:47 +02:00 committed by Alexander Kalenik
parent c690fb9df3
commit 6a549f6270
Notes: github-actions[bot] 2024-10-16 18:26:41 +00:00
58 changed files with 364 additions and 290 deletions

View file

@ -135,7 +135,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<P>) [235,55 139.96875x10]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [235,65 139.96875x0]
InlinePaintable (InlineNode<FORM>)
PaintableWithLines (InlineNode<FORM>)
PaintableWithLines (BlockContainer<P>) [235,65 139.96875x19]
TextPaintable (TextNode<#text>)
RadioButtonPaintable (RadioButton<INPUT>) [263,65 12x12]
@ -158,10 +158,10 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer(anonymous)) [20,30 480x0]
PaintableWithLines (BlockContainer<P>) [20,335 480x65]
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [20,400 480x0]

View file

@ -26,9 +26,9 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x34]
PaintableWithLines (BlockContainer<SPAN>.a) [8,8 100x17]
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<SPAN>.a) [8,25 100x17]
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -12,5 +12,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,16 784x19]
PaintableWithLines (BlockContainer<PRE>) [8,16 784x19]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -11,6 +11,6 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x116]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x100]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<SPAN>.thing) [43,8 100x100]

View file

@ -14,7 +14,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
InlinePaintable (InlineNode<DIV>)
PaintableWithLines (InlineNode<DIV>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<DIV>)
PaintableWithLines (InlineNode<DIV>)
TextPaintable (TextNode<#text>)

View file

@ -13,5 +13,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [9,9 502x83]
PaintableWithLines (BlockContainer<DIV>.a) [10,10 500x81]
PaintableWithLines (BlockContainer<DIV>.b) [91,31 328x19]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -13,5 +13,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [9,9 502x103]
PaintableWithLines (BlockContainer<DIV>.a) [10,10 500x101]
PaintableWithLines (BlockContainer<DIV>.b) [71,51 378x19]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -37,11 +37,11 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x152] overflow: [8,8 784x168]
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x17]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<B>)
PaintableWithLines (InlineNode<B>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<I>)
PaintableWithLines (InlineNode<I>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [8,25 784x135]
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x68]

View file

@ -20,11 +20,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17] overflow: [8,8 784x42]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<B>)
PaintableWithLines (InlineNode<B>)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<B>)
InlinePaintable (InlineNode<I>)
PaintableWithLines (InlineNode<B>)
PaintableWithLines (InlineNode<I>)
TextPaintable (TextNode<#text>)

View file

@ -19,7 +19,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x83]
PaintableWithLines (BlockContainer<BODY>) [8,16 784x67]
PaintableWithLines (BlockContainer<P>) [8,16 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,49 784x34]

View file

@ -12,8 +12,8 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x17]
InlinePaintable (InlineNode<HEAD>)
InlinePaintable (InlineNode<STYLE>)
PaintableWithLines (InlineNode<HEAD>)
PaintableWithLines (InlineNode<STYLE>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<BODY>)
PaintableWithLines (InlineNode<BODY>)
TextPaintable (TextNode<#text>)

View file

@ -30,11 +30,10 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x148]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x132]
PaintableWithLines (BlockContainer<DIV>.string) [8,8 102x22]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,30 784x0]
PaintableWithLines (BlockContainer<DIV>.string-no-fallback) [8,30 102x22]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (BlockContainer(anonymous)) [8,52 784x0]
PaintableWithLines (BlockContainer<DIV>.length) [8,52 202x22]
PaintableWithLines (BlockContainer(anonymous)) [8,74 784x0]

View file

@ -91,44 +91,44 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,16 784x314] overflow: [8,16 784x330]
PaintableWithLines (BlockContainer<DIV>) [8,16 784x149]
PaintableWithLines (BlockContainer<P>) [8,16 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,49 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,82 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,115 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,148 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [8,181 784x149]
PaintableWithLines (BlockContainer<P>) [8,181 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,214 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,247 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,280 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,313 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,346 784x0]

View file

@ -171,83 +171,83 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<DIV>.ol) [8,8 784x255]
PaintableWithLines (BlockContainer(anonymous)) [24,8 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,8 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,25 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,25 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,42 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,42 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,59 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,59 768x153]
PaintableWithLines (BlockContainer(anonymous)) [24,59 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.ol) [24,76 768x136]
PaintableWithLines (BlockContainer(anonymous)) [40,76 752x0]
PaintableWithLines (BlockContainer<DIV>.li) [40,76 752x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [40,93 752x0]
PaintableWithLines (BlockContainer<DIV>.li) [40,93 752x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [40,110 752x0]
PaintableWithLines (BlockContainer<DIV>.li) [40,110 752x68]
PaintableWithLines (BlockContainer(anonymous)) [40,110 752x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.ol) [40,127 752x51]
PaintableWithLines (BlockContainer(anonymous)) [56,127 736x0]
PaintableWithLines (BlockContainer<DIV>.li) [56,127 736x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [56,144 736x0]
PaintableWithLines (BlockContainer<DIV>.li) [56,144 736x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [56,161 736x0]
PaintableWithLines (BlockContainer<DIV>.li) [56,161 736x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [56,178 736x0]
PaintableWithLines (BlockContainer(anonymous)) [40,178 752x0]
PaintableWithLines (BlockContainer(anonymous)) [40,178 752x0]
PaintableWithLines (BlockContainer<DIV>.li) [40,178 752x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [40,195 752x0]
PaintableWithLines (BlockContainer<DIV>.li) [40,195 752x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [40,212 752x0]
PaintableWithLines (BlockContainer(anonymous)) [24,212 768x0]
PaintableWithLines (BlockContainer(anonymous)) [24,212 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,212 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,229 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,229 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,246 768x0]
PaintableWithLines (BlockContainer<DIV>.li) [24,246 768x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [24,263 768x0]

View file

@ -46,22 +46,22 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,16 784x149]
PaintableWithLines (BlockContainer<P>) [8,16 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,49 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,82 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,115 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<P>) [8,148 784x17]
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)

View file

@ -26,13 +26,13 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x79]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -15,6 +15,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,20 784x22] overflow: [8,20 784x42]
PaintableWithLines (BlockContainer<P>) [8,20 784x22]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,62 784x0]

View file

@ -15,6 +15,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,20 784x22] overflow: [8,20 784x42]
PaintableWithLines (BlockContainer<P>) [8,20 784x22]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,62 784x0]

View file

@ -34,6 +34,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<math>) [318,50 2x110] overflow: [319,51 100x100]
PaintableWithLines (BlockContainer<a>) [319,51 100x100]
PaintableWithLines (BlockContainer<DIV>) [8,163 784x46]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,209 784x0]

View file

@ -211,100 +211,90 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x67]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x51]
PaintableWithLines (BlockContainer<DIV>.a) [8,8 784x17]
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x0]
PaintableWithLines (BlockContainer<DIV>.b) [8,25 784x17]
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,42 784x0]
PaintableWithLines (BlockContainer<DIV>.c) [8,42 784x17]
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode(anonymous))
PaintableWithLines (InlineNode(anonymous))
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,59 784x0]

View file

@ -26,6 +26,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
TextPaintable (TextNode<#text>)
MarkerPaintable (ListItemMarkerBox(anonymous)) [8,8 12x17]
PaintableWithLines (BlockContainer<SLOT>) [8,25 784x17]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,42 784x0]

View file

@ -14,5 +14,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x0]
PaintableWithLines (BlockContainer<DIALOG>) [339.84375,8 120.3125x55]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -7,5 +7,5 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x17]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -28,6 +28,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 1208x616]
PaintableBox (Box<DIV>.aligncenter.block-image) [8,8 1200x600]
PaintableBox (Box(anonymous)) [8,8 1200x600]
PaintableWithLines (BlockContainer(anonymous)) [8,8 1200x600]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
ImagePaintable (ImageBox<IMG>) [8,8 1200x600]
PaintableWithLines (BlockContainer(anonymous)) [8,608 784x0]

View file

@ -24,11 +24,11 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x39]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x23]
InlinePaintable (InlineNode<SPAN>.a)
PaintableWithLines (InlineNode<SPAN>.a)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.b)
PaintableWithLines (InlineNode<SPAN>.b)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.c)
PaintableWithLines (InlineNode<SPAN>.c)
TextPaintable (TextNode<#text>)

View file

@ -9,5 +9,5 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
InlinePaintable (InlineNode<FONT>)
PaintableWithLines (InlineNode<FONT>)
TextPaintable (TextNode<#text>)

View file

@ -31,14 +31,14 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x216]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x200]
InlinePaintable (InlineNode<SPAN>.one)
PaintableWithLines (InlineNode<SPAN>.one)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.two)
PaintableWithLines (InlineNode<SPAN>.two)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.three)
PaintableWithLines (InlineNode<SPAN>.three)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.four)
PaintableWithLines (InlineNode<SPAN>.four)
TextPaintable (TextNode<#text>)

View file

@ -15,5 +15,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x47]
PaintableWithLines (BlockContainer<MAIN>) [8,8 784x47]
PaintableWithLines (BlockContainer<DIV>) [8,8 373.96875x47]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -20,10 +20,10 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x19]
PaintableWithLines (BlockContainer<DIV>.fixed_width) [8,8 52x19] overflow: [9,9 78.921875x17]
InlinePaintable (InlineNode<SPAN>.nowrap)
PaintableWithLines (BlockContainer<DIV>.fixed_width) [8,8 52x19]
PaintableWithLines (InlineNode<SPAN>.nowrap)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>.nowrap)
PaintableWithLines (InlineNode<SPAN>.nowrap)
TextPaintable (TextNode<#text>)

View file

@ -49,7 +49,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<DIV>.outer) [8,8 452x122] overflow: [9,9 450x152]
PaintableWithLines (BlockContainer<DIV>.inner) [34,34 402x102]
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (BlockContainer(anonymous)) [8,130 784x0]
PaintableWithLines (BlockContainer<DIV>.outer) [8,130 452x122] overflow: [9,131 450x247]
PaintableWithLines (BlockContainer<DIV>.inner) [34,156 402x102] overflow: [35,157 400x221]

View file

@ -48,7 +48,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [10,31 780x0]
PaintableWithLines (BlockContainer<DIV>.inline.formatting-context) [10,31 780x19]
InlinePaintable (InlineNode<DIV>)
PaintableWithLines (InlineNode<DIV>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [10,50 780x0]
PaintableBox (Box<DIV>.flex.formatting-context) [10,50 780x21]

View file

@ -14,6 +14,6 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x416]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x400]
InlinePaintable (InlineNode<PICTURE>)
InlinePaintable (InlineNode<SOURCE>)
PaintableWithLines (InlineNode<PICTURE>)
PaintableWithLines (InlineNode<SOURCE>)
ImagePaintable (ImageBox<IMG>) [8,8 400x400]

View file

@ -10,5 +10,5 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
InlinePaintable (InlineNode<PRE>)
PaintableWithLines (InlineNode<PRE>)
TextPaintable (TextNode<#text>)

View file

@ -14,6 +14,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
PaintableWithLines (BlockContainer<DIV>#container) [8,8 784x17]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x0]

View file

@ -19,8 +19,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x36]
PaintableWithLines (BlockContainer<DIV>.fixed_width) [8,8 52x36]
InlinePaintable (InlineNode<SPAN>.nowrap)
PaintableWithLines (InlineNode<SPAN>.nowrap)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
InlinePaintable (InlineNode<SPAN>.nowrap)
PaintableWithLines (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>.nowrap)
TextPaintable (TextNode<#text>)

View file

@ -9,5 +9,5 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x36]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x20]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -6,4 +6,4 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<svg>) [0,0 800x0]
InlinePaintable (InlineNode<rect>)
PaintableWithLines (InlineNode<rect>)

View file

@ -41,7 +41,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableBox (Box<TR>) [10,10 45.21875x9.5] overflow: [10,10 45.21875x21]
PaintableWithLines (BlockContainer<TD>) [10,10 2x9.5]
PaintableWithLines (BlockContainer<TD>) [14,10 41.21875x21]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
PaintableBox (Box<TR>) [10,21.5 45.21875x9.5]
PaintableWithLines (BlockContainer<TD>) [10,21.5 2x9.5]

View file

@ -16,6 +16,6 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x66]
PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x50]
InlinePaintable (InlineNode<A>)
PaintableWithLines (InlineNode<A>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.test) [49,8 50x50]

View file

@ -16,9 +16,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17] overflow: [8,8 784.34375x17]
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
TextPaintable (TextNode<#text>)
InlinePaintable (InlineNode<SPAN>)
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -49,12 +49,12 @@ Test embed.vspace = "120." maps to marginTop: 120px
Test embed.vspace = "100" maps to marginBottom: 100px
Test embed.vspace = " 00110 " maps to marginBottom: 110px
Test embed.vspace = "120." maps to marginBottom: 120px
Test embed.width = "100" maps to width: 100px
Test embed.width = " 00110 " maps to width: 110px
Test embed.width = "120." maps to width: 120px
Test embed.height = "100" maps to height: 100px
Test embed.height = " 00110 " maps to height: 110px
Test embed.height = "120." maps to height: 120px
Test embed.width = "100" maps to width: 0px
Test embed.width = " 00110 " maps to width: 0px
Test embed.width = "120." maps to width: 0px
Test embed.height = "100" maps to height: 0px
Test embed.height = " 00110 " maps to height: 0px
Test embed.height = "120." maps to height: 0px
Test tr.height = "100" maps to height: 100px
Test tr.height = " 00110 " maps to height: 110px
Test tr.height = "120." maps to height: 120px

View file

@ -18,6 +18,6 @@ div {
<script src="../include.js"></script>
<script>
test(() => {
println(internals.hitTest(50, 50).node.parentNode === document.getElementById("inline-stacking-context"));
println(internals.hitTest(50, 50).node === document.getElementById("inline-stacking-context"));
});
</script>

View file

@ -1364,7 +1364,7 @@ void Element::set_scroll_left(double x)
if (!paintable_box())
return;
if (!paintable_box()->layout_box().is_scroll_container())
if (!paintable_box()->layout_node_with_style_and_box_metrics().is_scroll_container())
return;
// FIXME: or the element has no overflow.
@ -1421,7 +1421,7 @@ void Element::set_scroll_top(double y)
if (!paintable_box())
return;
if (!paintable_box()->layout_box().is_scroll_container())
if (!paintable_box()->layout_node_with_style_and_box_metrics().is_scroll_container())
return;
// FIXME: or the element has no overflow.

View file

@ -383,11 +383,13 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho
if (is<Layout::InlineNode>(layout_node) && layout_node.first_paintable()) {
auto const& inline_node = static_cast<Layout::InlineNode const&>(layout_node);
auto const& inline_paintable = static_cast<Painting::InlinePaintable const&>(*inline_node.first_paintable());
auto const& fragments = inline_paintable.fragments();
for (size_t fragment_index = 0; fragment_index < fragments.size(); ++fragment_index) {
auto const& fragment = fragments[fragment_index];
dump_fragment(fragment, fragment_index);
for (auto const& paintable : inline_node.paintables()) {
auto const& paintable_with_lines = static_cast<Painting::PaintableWithLines const&>(paintable);
auto const& fragments = paintable_with_lines.fragments();
for (size_t fragment_index = 0; fragment_index < fragments.size(); ++fragment_index) {
auto const& fragment = fragments[fragment_index];
dump_fragment(fragment, fragment_index);
}
}
}

View file

@ -574,6 +574,7 @@ class CheckBox;
class FlexFormattingContext;
class FormattingContext;
class ImageBox;
class InlineNode;
class InlineFormattingContext;
class Label;
class LabelableNode;

View file

@ -34,37 +34,6 @@ void Box::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_contained_abspos_children);
}
// https://www.w37.org/TR/css-overflow-3/#overflow-control
static bool overflow_value_makes_box_a_scroll_container(CSS::Overflow overflow)
{
switch (overflow) {
case CSS::Overflow::Clip:
case CSS::Overflow::Visible:
return false;
case CSS::Overflow::Auto:
case CSS::Overflow::Hidden:
case CSS::Overflow::Scroll:
return true;
}
VERIFY_NOT_REACHED();
}
// https://www.w3.org/TR/css-overflow-3/#scroll-container
bool Box::is_scroll_container() const
{
// NOTE: This isn't in the spec, but we want the viewport to behave like a scroll container.
if (is_viewport())
return true;
return overflow_value_makes_box_a_scroll_container(computed_values().overflow_x())
|| overflow_value_makes_box_a_scroll_container(computed_values().overflow_y());
}
bool Box::is_body() const
{
return dom_node() && dom_node() == document().body();
}
JS::GCPtr<Painting::Paintable> Box::create_paintable() const
{
return Painting::PaintableBox::create(*this);

View file

@ -25,8 +25,6 @@ public:
Painting::PaintableBox const* paintable_box() const;
Painting::PaintableBox* paintable_box();
bool is_body() const;
// https://www.w3.org/TR/css-images-3/#natural-dimensions
Optional<CSSPixels> natural_width() const { return m_natural_width; }
Optional<CSSPixels> natural_height() const { return m_natural_height; }
@ -50,8 +48,6 @@ public:
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
bool is_scroll_container() const;
void add_contained_abspos_child(JS::NonnullGCPtr<Node> child) { m_contained_abspos_children.append(child); }
void clear_contained_abspos_children() { m_contained_abspos_children.clear(); }
Vector<JS::NonnullGCPtr<Node>> const& contained_abspos_children() const { return m_contained_abspos_children; }

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2018-2022, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -23,9 +24,17 @@ InlineNode::InlineNode(DOM::Document& document, DOM::Element* element, NonnullRe
InlineNode::~InlineNode() = default;
JS::GCPtr<Painting::Paintable> InlineNode::create_paintable() const
JS::GCPtr<Painting::PaintableWithLines> InlineNode::create_paintable_for_line_with_index(size_t line_index) const
{
return Painting::InlinePaintable::create(*this);
for (auto const& paintable : paintables()) {
if (is<Painting::PaintableWithLines>(paintable)) {
auto const& paintable_with_lines = static_cast<Painting::PaintableWithLines const&>(paintable);
if (paintable_with_lines.line_index() == line_index) {
return const_cast<Painting::PaintableWithLines&>(paintable_with_lines);
}
}
}
return Painting::PaintableWithLines::create(*this, line_index);
}
}

View file

@ -18,7 +18,7 @@ public:
InlineNode(DOM::Document&, DOM::Element*, NonnullRefPtr<CSS::StyleProperties>);
virtual ~InlineNode() override;
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
JS::GCPtr<Painting::PaintableWithLines> create_paintable_for_line_with_index(size_t line_index) const;
};
}

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2022-2024, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -165,50 +166,47 @@ void LayoutState::resolve_relative_positions()
auto& used_values = *it.value;
auto& node = const_cast<NodeWithStyle&>(used_values.node());
auto* paintable = node.first_paintable();
if (!paintable)
continue;
if (!is<Painting::InlinePaintable>(*paintable))
continue;
auto const& inline_paintable = static_cast<Painting::InlinePaintable&>(*paintable);
for (auto& fragment : inline_paintable.fragments()) {
auto const& fragment_node = fragment.layout_node();
if (!is<Layout::NodeWithStyleAndBoxModelMetrics>(*fragment_node.parent()))
for (auto& paintable : node.paintables()) {
if (!(is<Painting::PaintableWithLines>(paintable) && is<Layout::InlineNode>(paintable.layout_node())))
continue;
// Collect effective relative position offset from inline-flow parent chain.
CSSPixelPoint offset;
for (auto* ancestor = fragment_node.parent(); ancestor; ancestor = ancestor->parent()) {
if (!is<Layout::NodeWithStyleAndBoxModelMetrics>(*ancestor))
break;
if (!ancestor->display().is_inline_outside() || !ancestor->display().is_flow_inside())
break;
if (ancestor->computed_values().position() == CSS::Positioning::Relative) {
auto const& ancestor_node = static_cast<Layout::NodeWithStyleAndBoxModelMetrics const&>(*ancestor);
auto const& inset = ancestor_node.box_model().inset;
offset.translate_by(inset.left, inset.top);
auto const& inline_paintable = static_cast<Painting::PaintableWithLines&>(paintable);
for (auto& fragment : inline_paintable.fragments()) {
auto const& fragment_node = fragment.layout_node();
if (!is<Layout::NodeWithStyleAndBoxModelMetrics>(*fragment_node.parent()))
continue;
// Collect effective relative position offset from inline-flow parent chain.
CSSPixelPoint offset;
for (auto* ancestor = fragment_node.parent(); ancestor; ancestor = ancestor->parent()) {
if (!is<Layout::NodeWithStyleAndBoxModelMetrics>(*ancestor))
break;
if (!ancestor->display().is_inline_outside() || !ancestor->display().is_flow_inside())
break;
if (ancestor->computed_values().position() == CSS::Positioning::Relative) {
auto const& ancestor_node = static_cast<Layout::NodeWithStyleAndBoxModelMetrics const&>(*ancestor);
auto const& inset = ancestor_node.box_model().inset;
offset.translate_by(inset.left, inset.top);
}
}
const_cast<Painting::PaintableFragment&>(fragment).set_offset(fragment.offset().translated(offset));
}
const_cast<Painting::PaintableFragment&>(fragment).set_offset(fragment.offset().translated(offset));
}
}
}
static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = nullptr)
{
Painting::Paintable* paintable = nullptr;
if (node.first_paintable()) {
paintable = const_cast<Painting::Paintable*>(node.first_paintable());
if (parent_paintable && !paintable->forms_unconnected_subtree()) {
VERIFY(!paintable->parent());
parent_paintable->append_child(*paintable);
for (auto& paintable : node.paintables()) {
if (parent_paintable && !paintable.forms_unconnected_subtree()) {
VERIFY(!paintable.parent());
parent_paintable->append_child(paintable);
}
paintable->set_dom_node(node.dom_node());
paintable.set_dom_node(node.dom_node());
if (node.dom_node())
node.dom_node()->set_paintable(paintable);
}
for (auto* child = node.first_child(); child; child = child->next_sibling()) {
build_paint_tree(*child, paintable);
build_paint_tree(*child, node.first_paintable());
}
}
@ -224,14 +222,35 @@ void LayoutState::commit(Box& root)
node.clear_paintables();
return TraversalDecision::Continue;
});
HashTable<Layout::InlineNode*> inline_nodes;
root.document().for_each_shadow_including_inclusive_descendant([&](DOM::Node& node) {
node.clear_paintable();
if (node.layout_node() && is<InlineNode>(node.layout_node())) {
inline_nodes.set(static_cast<InlineNode*>(node.layout_node()));
}
return TraversalDecision::Continue;
});
HashTable<Layout::TextNode*> text_nodes;
HashTable<Painting::PaintableWithLines*> inline_node_paintables;
Vector<Painting::PaintableWithLines&> paintables_with_lines;
auto try_to_relocate_fragment_in_inline_node = [&](auto& fragment, size_t line_index) -> bool {
for (auto const* parent = fragment.layout_node().parent(); parent; parent = parent->parent()) {
if (is<InlineNode>(*parent)) {
auto& inline_node = const_cast<InlineNode&>(static_cast<InlineNode const&>(*parent));
auto line_paintable = inline_node.create_paintable_for_line_with_index(line_index);
line_paintable->add_fragment(fragment);
if (!inline_node_paintables.contains(line_paintable.ptr())) {
inline_node_paintables.set(line_paintable.ptr());
inline_node.add_paintable(line_paintable);
}
return true;
}
}
return false;
};
for (auto& it : used_values_per_layout_node) {
auto& used_values = *it.value;
@ -247,7 +266,6 @@ void LayoutState::commit(Box& root)
}
auto paintable = node.create_paintable();
node.add_paintable(paintable);
// For boxes, transfer all the state needed for painting.
@ -264,11 +282,17 @@ void LayoutState::commit(Box& root)
if (is<Painting::PaintableWithLines>(paintable_box)) {
auto& paintable_with_lines = static_cast<Painting::PaintableWithLines&>(paintable_box);
for (auto& line_box : used_values.line_boxes) {
for (auto& fragment : line_box.fragments())
paintable_with_lines.add_fragment(fragment);
for (size_t line_index = 0; line_index < used_values.line_boxes.size(); ++line_index) {
auto& line_box = used_values.line_boxes[line_index];
for (auto& fragment : line_box.fragments()) {
if (fragment.layout_node().is_text_node())
text_nodes.set(static_cast<Layout::TextNode*>(const_cast<Layout::Node*>(&fragment.layout_node())));
auto did_relocate_fragment = try_to_relocate_fragment_in_inline_node(fragment, line_index);
if (!did_relocate_fragment) {
paintable_with_lines.add_fragment(fragment);
}
}
}
paintables_with_lines.append(paintable_with_lines);
}
if (used_values.computed_svg_transforms().has_value() && is<Painting::SVGGraphicsPaintable>(paintable_box)) {
@ -288,6 +312,15 @@ void LayoutState::commit(Box& root)
}
}
// Create paintables for inline nodes without fragments to make possible querying their geometry.
for (auto& inline_node : inline_nodes) {
auto* paintable = inline_node->first_paintable();
if (paintable)
continue;
paintable = inline_node->create_paintable_for_line_with_index(0);
inline_node->add_paintable(paintable);
}
// Resolve relative positions for regular boxes (not line box fragments):
// NOTE: This needs to occur before fragments are transferred into the corresponding inline paintables, because
// after this transfer, the containing_line_box_fragment will no longer be valid.
@ -324,32 +357,6 @@ void LayoutState::commit(Box& root)
paintable.set_offset(offset);
}
// Make a pass over all the line boxes to:
// - Collect all text nodes, so we can create paintables for them later.
// - Relocate fragments into matching inline paintables
for (auto& paintable_with_lines : paintables_with_lines) {
Vector<Painting::PaintableFragment> fragments_with_inline_paintables_removed;
for (auto& fragment : paintable_with_lines.fragments()) {
if (fragment.layout_node().is_text_node())
text_nodes.set(static_cast<Layout::TextNode*>(const_cast<Layout::Node*>(&fragment.layout_node())));
auto find_closest_inline_paintable = [&](auto& fragment) -> Painting::InlinePaintable const* {
for (auto const* parent = fragment.layout_node().parent(); parent; parent = parent->parent()) {
if (is<InlineNode>(*parent))
return static_cast<Painting::InlinePaintable const*>(parent->first_paintable());
}
return nullptr;
};
if (auto const* inline_paintable = find_closest_inline_paintable(fragment)) {
const_cast<Painting::InlinePaintable*>(inline_paintable)->fragments().append(fragment);
} else {
fragments_with_inline_paintables_removed.append(fragment);
}
}
paintable_with_lines.set_fragments(move(fragments_with_inline_paintables_removed));
}
for (auto* text_node : text_nodes) {
text_node->add_paintable(text_node->create_paintable());
auto* paintable = text_node->first_paintable();
@ -369,6 +376,26 @@ void LayoutState::commit(Box& root)
resolve_relative_positions();
// Measure size of paintables created for inline nodes.
for (auto& paintable_with_lines : inline_node_paintables) {
if (!is<InlineNode>(paintable_with_lines->layout_node())) {
continue;
}
auto const& fragments = paintable_with_lines->fragments();
if (fragments.is_empty()) {
continue;
}
paintable_with_lines->set_offset(fragments.first().offset());
CSSPixelSize size;
for (auto const& fragment : fragments) {
size.set_width(size.width() + fragment.width());
size.set_height(max(size.height(), fragment.height()));
}
paintable_with_lines->set_content_size(size.width(), size.height());
}
// Measure overflow in scroll containers.
for (auto& it : used_values_per_layout_node) {
auto& used_values = *it.value;

View file

@ -1017,6 +1017,35 @@ void NodeWithStyle::transfer_table_box_computed_values_to_wrapper_computed_value
reset_table_box_computed_values_used_by_wrapper_to_init_values();
}
bool NodeWithStyle::is_body() const
{
return dom_node() && dom_node() == document().body();
}
static bool overflow_value_makes_box_a_scroll_container(CSS::Overflow overflow)
{
switch (overflow) {
case CSS::Overflow::Clip:
case CSS::Overflow::Visible:
return false;
case CSS::Overflow::Auto:
case CSS::Overflow::Hidden:
case CSS::Overflow::Scroll:
return true;
}
VERIFY_NOT_REACHED();
}
bool NodeWithStyle::is_scroll_container() const
{
// NOTE: This isn't in the spec, but we want the viewport to behave like a scroll container.
if (is_viewport())
return true;
return overflow_value_makes_box_a_scroll_container(computed_values().overflow_x())
|| overflow_value_makes_box_a_scroll_container(computed_values().overflow_y());
}
void Node::add_paintable(JS::GCPtr<Painting::Paintable> paintable)
{
if (!paintable)

View file

@ -69,6 +69,8 @@ public:
Painting::Paintable* first_paintable() { return m_paintable.first(); }
Painting::Paintable const* first_paintable() const { return m_paintable.first(); }
PaintableList& paintables() { return m_paintable; }
PaintableList const& paintables() const { return m_paintable; }
void add_paintable(JS::GCPtr<Painting::Paintable>);
void clear_paintables();
@ -220,6 +222,9 @@ public:
void transfer_table_box_computed_values_to_wrapper_computed_values(CSS::ComputedValues& wrapper_computed_values);
bool is_body() const;
bool is_scroll_container() const;
virtual void visit_edges(Cell::Visitor& visitor) override;
protected:

View file

@ -27,12 +27,12 @@ void LabelablePaintable::set_being_pressed(bool being_pressed)
Layout::FormAssociatedLabelableNode const& LabelablePaintable::layout_box() const
{
return static_cast<Layout::FormAssociatedLabelableNode const&>(PaintableBox::layout_box());
return static_cast<Layout::FormAssociatedLabelableNode const&>(PaintableBox::layout_node_with_style_and_box_metrics());
}
Layout::FormAssociatedLabelableNode& LabelablePaintable::layout_box()
{
return static_cast<Layout::FormAssociatedLabelableNode&>(PaintableBox::layout_box());
return static_cast<Layout::FormAssociatedLabelableNode&>(PaintableBox::layout_node_with_style_and_box_metrics());
}
LabelablePaintable::DispatchEventOfSameName LabelablePaintable::handle_mousedown(Badge<EventHandler>, CSSPixelPoint, unsigned button, unsigned)

View file

@ -272,7 +272,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousedown(Badge<E
if (button != UIEvents::MouseButton::Primary)
return DispatchEventOfSameName::Yes;
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_box().dom_node());
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_node_with_style_and_box_metrics().dom_node());
auto const& cached_layout_boxes = media_element.cached_layout_boxes({});
auto position_adjusted_by_scroll_offset = position;
@ -294,7 +294,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousedown(Badge<E
MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mouseup(Badge<EventHandler>, CSSPixelPoint position, unsigned button, unsigned)
{
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_box().dom_node());
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_node_with_style_and_box_metrics().dom_node());
auto const& cached_layout_boxes = media_element.cached_layout_boxes({});
auto position_adjusted_by_scroll_offset = position;
@ -342,7 +342,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mouseup(Badge<Eve
MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousemove(Badge<EventHandler>, CSSPixelPoint position, unsigned, unsigned)
{
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_box().dom_node());
auto& media_element = *verify_cast<HTML::HTMLMediaElement>(layout_node_with_style_and_box_metrics().dom_node());
auto const& cached_layout_boxes = media_element.cached_layout_boxes({});
auto position_adjusted_by_scroll_offset = position;

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2022-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -34,16 +35,31 @@ JS::NonnullGCPtr<PaintableWithLines> PaintableWithLines::create(Layout::BlockCon
return block_container.heap().allocate_without_realm<PaintableWithLines>(block_container);
}
JS::NonnullGCPtr<PaintableWithLines> PaintableWithLines::create(Layout::InlineNode const& inline_node, size_t line_index)
{
return inline_node.heap().allocate_without_realm<PaintableWithLines>(inline_node, line_index);
}
JS::NonnullGCPtr<PaintableBox> PaintableBox::create(Layout::Box const& layout_box)
{
return layout_box.heap().allocate_without_realm<PaintableBox>(layout_box);
}
JS::NonnullGCPtr<PaintableBox> PaintableBox::create(Layout::InlineNode const& layout_box)
{
return layout_box.heap().allocate_without_realm<PaintableBox>(layout_box);
}
PaintableBox::PaintableBox(Layout::Box const& layout_box)
: Paintable(layout_box)
{
}
PaintableBox::PaintableBox(Layout::InlineNode const& layout_box)
: Paintable(layout_box)
{
}
PaintableBox::~PaintableBox()
{
}
@ -53,6 +69,12 @@ PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box)
{
}
PaintableWithLines::PaintableWithLines(Layout::InlineNode const& inline_node, size_t line_index)
: PaintableBox(inline_node)
, m_line_index(line_index)
{
}
PaintableWithLines::~PaintableWithLines()
{
}
@ -112,7 +134,7 @@ void PaintableBox::set_scroll_offset(CSSPixelPoint offset)
// the user agent must run these steps:
// 1. Let doc be the elements node document.
auto& document = layout_box().document();
auto& document = layout_node().document();
// FIXME: 2. If the element is a snap container, run the steps to update snapchanging targets for the element with
// the elements eventual snap target in the block axis as newBlockTarget and the elements eventual snap
@ -125,7 +147,7 @@ void PaintableBox::set_scroll_offset(CSSPixelPoint offset)
return;
// 4. Append the element to docs pending scroll event targets.
document.pending_scroll_event_targets().append(*layout_box().dom_node());
document.pending_scroll_event_targets().append(*layout_node_with_style_and_box_metrics().dom_node());
set_needs_display(InvalidateDisplayList::No);
}
@ -143,7 +165,9 @@ void PaintableBox::set_offset(CSSPixelPoint offset)
void PaintableBox::set_content_size(CSSPixelSize size)
{
m_content_size = size;
layout_box().did_set_content_size();
if (is<Layout::Box>(Paintable::layout_node())) {
static_cast<Layout::Box&>(layout_node_with_style_and_box_metrics()).did_set_content_size();
}
}
CSSPixelPoint PaintableBox::offset() const
@ -197,7 +221,7 @@ CSSPixelRect PaintableBox::absolute_paint_rect() const
Optional<CSSPixelRect> PaintableBox::get_clip_rect() const
{
auto clip = computed_values().clip();
if (clip.is_rect() && layout_box().is_absolutely_positioned()) {
if (clip.is_rect() && layout_node_with_style_and_box_metrics().is_absolutely_positioned()) {
auto border_box = absolute_border_box_rect();
return clip.to_rect().resolved(layout_node(), border_box);
}
@ -238,7 +262,10 @@ void PaintableBox::after_paint(PaintContext& context, [[maybe_unused]] PaintPhas
bool PaintableBox::is_scrollable(ScrollDirection direction) const
{
auto overflow = direction == ScrollDirection::Horizontal ? computed_values().overflow_x() : computed_values().overflow_y();
auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect()->width() : scrollable_overflow_rect()->height();
auto scrollable_overflow_rect = this->scrollable_overflow_rect();
if (!scrollable_overflow_rect.has_value())
return false;
auto scrollable_overflow_size = direction == ScrollDirection::Horizontal ? scrollable_overflow_rect->width() : scrollable_overflow_rect->height();
auto scrollport_size = direction == ScrollDirection::Horizontal ? absolute_padding_box_rect().width() : absolute_padding_box_rect().height();
if ((is_viewport() && overflow != CSS::Overflow::Hidden) || overflow == CSS::Overflow::Auto)
return scrollable_overflow_size > scrollport_size;
@ -363,7 +390,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
}
}
if (phase == PaintPhase::Overlay && layout_box().document().inspected_layout_node() == &layout_box()) {
if (phase == PaintPhase::Overlay && layout_node().document().inspected_layout_node() == &layout_node_with_style_and_box_metrics()) {
auto content_rect = absolute_rect();
auto margin_box = box_model().margin_box();
@ -390,10 +417,10 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
auto& font = Platform::FontPlugin::the().default_font();
StringBuilder builder;
if (layout_box().dom_node())
builder.append(layout_box().dom_node()->debug_description());
if (layout_node_with_style_and_box_metrics().dom_node())
builder.append(layout_node_with_style_and_box_metrics().dom_node()->debug_description());
else
builder.append(layout_box().debug_description());
builder.append(layout_node_with_style_and_box_metrics().debug_description());
builder.appendff(" {}x{} @ {},{}", border_rect.width(), border_rect.height(), border_rect.x(), border_rect.y());
auto size_text = MUST(builder.to_string());
auto size_text_rect = border_rect;
@ -445,10 +472,10 @@ void PaintableBox::paint_backdrop_filter(PaintContext& context) const
void PaintableBox::paint_background(PaintContext& context) const
{
// If the body's background properties were propagated to the root element, do no re-paint the body's background.
if (layout_box().is_body() && document().html_element()->should_use_body_background_properties())
if (layout_node_with_style_and_box_metrics().is_body() && document().html_element()->should_use_body_background_properties())
return;
Painting::paint_background(context, layout_box(), computed_values().image_rendering(), m_resolved_background, normalized_border_radii_data());
Painting::paint_background(context, layout_node_with_style_and_box_metrics(), computed_values().image_rendering(), m_resolved_background, normalized_border_radii_data());
}
void PaintableBox::paint_box_shadow(PaintContext& context) const
@ -787,14 +814,14 @@ bool PaintableBox::handle_mousewheel(Badge<EventHandler>, CSSPixelPoint, unsigne
return true;
}
Layout::BlockContainer const& PaintableWithLines::layout_box() const
Layout::NodeWithStyleAndBoxModelMetrics const& PaintableWithLines::layout_node_with_style_and_box_metrics() const
{
return static_cast<Layout::BlockContainer const&>(PaintableBox::layout_box());
return static_cast<Layout::NodeWithStyleAndBoxModelMetrics const&>(PaintableBox::layout_node_with_style_and_box_metrics());
}
Layout::BlockContainer& PaintableWithLines::layout_box()
Layout::NodeWithStyleAndBoxModelMetrics& PaintableWithLines::layout_node_with_style_and_box_metrics()
{
return static_cast<Layout::BlockContainer&>(PaintableBox::layout_box());
return static_cast<Layout::NodeWithStyleAndBoxModelMetrics&>(PaintableBox::layout_node_with_style_and_box_metrics());
}
TraversalDecision PaintableBox::hit_test_scrollbars(CSSPixelPoint position, Function<TraversalDecision(HitTestResult)> const& callback) const
@ -822,7 +849,7 @@ TraversalDecision PaintableBox::hit_test(CSSPixelPoint position, HitTestType typ
if (hit_test_scrollbars(position_adjusted_by_scroll_offset, callback) == TraversalDecision::Break)
return TraversalDecision::Break;
if (layout_box().is_viewport()) {
if (layout_node_with_style_and_box_metrics().is_viewport()) {
auto& viewport_paintable = const_cast<ViewportPaintable&>(static_cast<ViewportPaintable const&>(*this));
viewport_paintable.build_stacking_context_tree_if_needed();
viewport_paintable.document().update_paint_and_hit_testing_properties_if_needed();
@ -874,7 +901,7 @@ TraversalDecision PaintableWithLines::hit_test(CSSPixelPoint position, HitTestTy
auto position_adjusted_by_scroll_offset = position;
position_adjusted_by_scroll_offset.translate_by(-cumulative_offset_of_enclosing_scroll_frame());
if (!layout_box().children_are_inline() || m_fragments.is_empty()) {
if (!layout_node_with_style_and_box_metrics().children_are_inline() || m_fragments.is_empty()) {
return PaintableBox::hit_test(position, type, callback);
}
@ -1102,7 +1129,7 @@ void PaintableBox::resolve_paint_properties()
CSSPixelRect background_rect;
Color background_color = computed_values.background_color();
auto const* background_layers = &computed_values.background_layers();
if (layout_box().is_root_element()) {
if (layout_node_with_style_and_box_metrics().is_root_element()) {
background_rect = navigable()->viewport_rect();
// Section 2.11.2: If the computed value of background-image on the root element is none and its background-color is transparent,
@ -1122,7 +1149,7 @@ void PaintableBox::resolve_paint_properties()
m_resolved_background.layers.clear();
if (background_layers) {
m_resolved_background = resolve_background_layers(*background_layers, layout_box(), background_color, background_rect, normalized_border_radii_data());
m_resolved_background = resolve_background_layers(*background_layers, layout_node_with_style_and_box_metrics(), background_color, background_rect, normalized_border_radii_data());
};
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -26,6 +27,7 @@ class PaintableBox : public Paintable
public:
static JS::NonnullGCPtr<PaintableBox> create(Layout::Box const&);
static JS::NonnullGCPtr<PaintableBox> create(Layout::InlineNode const&);
virtual ~PaintableBox();
virtual void before_paint(PaintContext&, PaintPhase) const override;
@ -37,10 +39,10 @@ public:
virtual Optional<Gfx::Bitmap::MaskKind> get_mask_type() const { return {}; }
virtual RefPtr<Gfx::Bitmap> calculate_mask(PaintContext&, CSSPixelRect const&) const { return {}; }
Layout::Box& layout_box() { return static_cast<Layout::Box&>(Paintable::layout_node()); }
Layout::Box const& layout_box() const { return static_cast<Layout::Box const&>(Paintable::layout_node()); }
Layout::NodeWithStyleAndBoxModelMetrics& layout_node_with_style_and_box_metrics() { return static_cast<Layout::NodeWithStyleAndBoxModelMetrics&>(Paintable::layout_node()); }
Layout::NodeWithStyleAndBoxModelMetrics const& layout_node_with_style_and_box_metrics() const { return static_cast<Layout::NodeWithStyleAndBoxModelMetrics const&>(Paintable::layout_node()); }
auto const& box_model() const { return layout_box().box_model(); }
auto const& box_model() const { return layout_node_with_style_and_box_metrics().box_model(); }
struct OverflowData {
CSSPixelRect scrollable_overflow_rect;
@ -115,7 +117,12 @@ public:
CSSPixels absolute_y() const { return absolute_rect().y(); }
CSSPixelPoint absolute_position() const { return absolute_rect().location(); }
[[nodiscard]] bool has_scrollable_overflow() const { return m_overflow_data->has_scrollable_overflow; }
[[nodiscard]] bool has_scrollable_overflow() const
{
if (!m_overflow_data.has_value())
return false;
return m_overflow_data->has_scrollable_overflow;
}
bool has_css_transform() const { return computed_values().transformations().size() > 0; }
@ -128,8 +135,8 @@ public:
void set_overflow_data(OverflowData data) { m_overflow_data = move(data); }
DOM::Node const* dom_node() const { return layout_box().dom_node(); }
DOM::Node* dom_node() { return layout_box().dom_node(); }
DOM::Node const* dom_node() const { return layout_node_with_style_and_box_metrics().dom_node(); }
DOM::Node* dom_node() { return layout_node_with_style_and_box_metrics().dom_node(); }
virtual void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes) override;
@ -207,7 +214,7 @@ public:
Optional<CSSPixelRect> get_clip_rect() const;
bool is_viewport() const { return layout_box().is_viewport(); }
bool is_viewport() const { return layout_node_with_style_and_box_metrics().is_viewport(); }
virtual bool wants_mouse_events() const override;
@ -238,6 +245,7 @@ public:
protected:
explicit PaintableBox(Layout::Box const&);
explicit PaintableBox(Layout::InlineNode const&);
virtual void paint_border(PaintContext&) const;
virtual void paint_backdrop_filter(PaintContext&) const;
@ -306,10 +314,11 @@ class PaintableWithLines : public PaintableBox {
public:
static JS::NonnullGCPtr<PaintableWithLines> create(Layout::BlockContainer const&);
static JS::NonnullGCPtr<PaintableWithLines> create(Layout::InlineNode const&, size_t line_index);
virtual ~PaintableWithLines() override;
Layout::BlockContainer const& layout_box() const;
Layout::BlockContainer& layout_box();
Layout::NodeWithStyleAndBoxModelMetrics const& layout_node_with_style_and_box_metrics() const;
Layout::NodeWithStyleAndBoxModelMetrics& layout_node_with_style_and_box_metrics();
Vector<PaintableFragment> const& fragments() const { return m_fragments; }
Vector<PaintableFragment>& fragments() { return m_fragments; }
@ -343,13 +352,18 @@ public:
virtual void resolve_paint_properties() override;
size_t line_index() const { return m_line_index; }
protected:
PaintableWithLines(Layout::BlockContainer const&);
PaintableWithLines(Layout::InlineNode const&, size_t line_index);
private:
[[nodiscard]] virtual bool is_paintable_with_lines() const final { return true; }
Vector<PaintableFragment> m_fragments;
size_t m_line_index { 0 };
};
void paint_text_decoration(PaintContext&, TextPaintable const&, PaintableFragment const&);

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -156,15 +157,19 @@ void ViewportPaintable::assign_clip_frames()
for (auto& it : clip_state) {
auto const& paintable_box = *it.key;
auto& clip_frame = *it.value;
for (auto const* block = &paintable_box.layout_box(); !block->is_viewport(); block = block->containing_block()) {
auto const& block_paintable_box = *block->paintable_box();
for (auto const* block = &paintable_box.layout_node_with_style_and_box_metrics(); !block->is_viewport(); block = block->containing_block()) {
auto const& paintable = block->first_paintable();
if (!paintable->is_paintable_box()) {
continue;
}
auto const& block_paintable_box = static_cast<PaintableBox const&>(*paintable);
auto block_overflow_x = block_paintable_box.computed_values().overflow_x();
auto block_overflow_y = block_paintable_box.computed_values().overflow_y();
if (block_overflow_x != CSS::Overflow::Visible && block_overflow_y != CSS::Overflow::Visible) {
auto rect = block_paintable_box.absolute_padding_box_rect();
clip_frame.add_clip_rect(rect, block_paintable_box.normalized_border_radii_data(ShrinkRadiiForBorders::Yes), block_paintable_box.enclosing_scroll_frame());
}
if (auto css_clip_property_rect = block->paintable_box()->get_clip_rect(); css_clip_property_rect.has_value()) {
if (auto css_clip_property_rect = block_paintable_box.get_clip_rect(); css_clip_property_rect.has_value()) {
clip_frame.add_clip_rect(css_clip_property_rect.value(), {}, block_paintable_box.enclosing_scroll_frame());
}
if (block->has_css_transform()) {

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/