Commit Graph

92 Commits

Author SHA1 Message Date
Andreas Kling
1f69e9cddf LibWeb: Remove Layout::Node::m_visible and compute it on the fly
This fixes an issue where the value would be out of sync with reality
in anonymous wrapper block boxes, since we forgot to compute m_visible
after assigning the computed values to them.

Fixes #21106
2023-09-18 14:45:20 +02:00
Aliaksandr Kalenik
dd7bba66ed LibWeb: Change viewport ownership from BrowsingContext to Navigable 2023-09-16 16:53:32 +02:00
Aliaksandr Kalenik
7eee3f6952 LibWeb: Add mutable_computed_values() for NodeWithStyle
This fixes the issue that we previously had to use a gross static_cast
whenever we wanted to mutate computed values outside of the Node
methods.
2023-09-12 17:26:30 +02:00
Aliaksandr Kalenik
b4064320bd LibWeb: Add m_is_grid_item in Layout::Node
This information is going to be needed during painting to treat grid
items as stacking contexts.
2023-08-22 11:33:24 +02:00
Andreas Kling
429b2e5860 LibWeb: Make FontCache per-StyleComputer
This effectively makes it per-Document, but we hang it off of
StyleComputer since that's what it's used for.

The purpose of this is to prevent downloaded fonts from escaping the
context that loaded them. There's probably a more elegant solution where
we still share caching of system fonts, but let's start here.
2023-08-17 20:32:21 +02:00
Andi Gallo
89305f1481 LibWeb: Copy button style properties for generated table and cell 2023-08-12 13:36:37 +02:00
Andi Gallo
b34b80104f LibWeb: Fix buttons with TextNode label
Fixes #20472.
2023-08-11 10:02:27 +02:00
Aliaksandr Kalenik
b6ea4b002b LibWeb: Add info about pseudo element type in Layout::Node 2023-08-07 05:23:31 +02:00
MacDue
21ace4f90b LibWeb: Add Node::scaled_font(float scale_factor)
This will allow fetching fonts scaled by a transform.
2023-07-21 11:42:30 +02:00
Andi Gallo
55f1a70577 LibWeb: Fix style updates for table box nodes
On style update, we have to preserve the invariant established when we
built the layout tree - some properties are applied to the table wrapper
and the table box values are reset to their initial values.

This also ensures that the containing block of a table box is always a
table wrapper, which isn't the case if we set absolute position on the
box instead of the wrapper.

Fixes #19452.
2023-06-23 16:40:19 +02:00
Andreas Kling
b6f3369b66 LibWeb: Fix spelling of non_anonymous_containing_block() 2023-06-14 17:08:15 +02:00
Aliaksandr Kalenik
258f3ea952 LibWeb: Remove Layout::TableBox
Solves conflict in layout tree "type system" when elements <label> (or
<button>) can't have `display: table` because Box can't be
Layout::Label (or Layout::ButtonBox) and Layout::TableBox at the same
time.
2023-05-29 14:12:29 +02:00
Andi Gallo
5cec517153 LibWeb: Get reference height from closest non-anonymous ancestor
Ignore anonymous block boxes when resolving percentage weights that
would refer to them, per the CSS 2 visual formatting model
specification. This fixes the case when we create an anonymous block
between an image which uses a percentage height relative to a parent
which specifies a definite height.

Fixes #19052.
2023-05-26 14:53:53 +02:00
Andreas Kling
e2c72922f6 LibWeb: Make LayoutState use HashMap instead of potentially huge Vector
Before this change, LayoutState essentially had a Vector<UsedValues*>
resized to the exact number of layout nodes in the current document.

When a nested layout is performed (to calculate the intrinsic size of
something), we make a new LayoutState with its own Vector. If an entry
is missing in a nested LayoutState, we check the parent chain all the
way up to the root.

Because each nested LayoutState had to allocate a new Vector with space
for all layout nodes, this could get really nasty on very large pages
(such as the ECMA262 specification).

This patch replaces the Vector with a HashMap. There's now a small cost
to lookups, but what we get in return is the ability to handle huge
layout trees without spending eternity in page faults.
2023-05-23 09:24:08 +02:00
Timothy Flynn
8f0b7fa370 LibWeb: Verify that a node has styled properties in its styled accessors
For example, it's possible to access Node::computed_values() on a node
that neither has style nor a parent with style. This ultimately results
in a null pointer dereference when we return parent()->computed_values()
as a fallback. This can be a little tricky to track down due to these
functions being inlined, so add an explicit verification.
2023-04-27 18:28:43 +02:00
MacDue
7061a3d8e6 LibWeb: Add .scaled_font() helper to Layout::Node
This returns the font scaled for the current zoom level.
2023-04-01 22:39:47 +01:00
Andreas Kling
1cf5737e9e LibWeb: Add fast_is<T>() for various types stood out in a profile 2023-03-11 10:46:26 +01:00
Andreas Kling
7e76a51cb0 LibWeb: Rename Layout::InitialContainingBlock to Layout::Viewport
The name "initial containing block" was wrong for this, as it doesn't
correspond to the HTML element, and that's specifically what it's
supposed to do! :^)
2023-02-28 12:21:56 +01:00
Andreas Kling
f11899f885 LibWeb+LibIDL: Fix (or paper over) various const-correctness issues
There's definitely stuff to iterate on here, but this takes care of
making the libraries compile with stricter RP and NNRP.
2023-02-21 00:54:04 +01:00
Timothy Flynn
1c1b902a6a LibJS+LibWeb: Move headers around to allow including Value from Cell
The goal here is to allow Cell::initialize to return a ThrowCompletion,
to handle OOM for example. Cell.h will then need to include Completion.h
which must include Value.h. This currently can't happen because Value.h
includes BigInt.h, which in turn includes Cell.h. So we would have an
include cycle.

This removes BigInt.h from Value.h, as it is forward-declarable (it is
only referred to with a reference or pointer). Then the Value overload
for Cell::Visitor::visit is moved to Cell.h, and missing BigInt.h
includes as peppered as needed.
2023-01-29 00:02:45 +00:00
Andreas Kling
aa19c4a340 LibWeb: Add Layout::Node::is_table() and make is<TableBox>() fast 2023-01-24 11:44:03 +01:00
Andreas Kling
51555dea7c LibWeb: Make Layout::Node::containing_block() return a Layout::Box
Containing blocks can be formed by boxes that aren't block containers,
so let's make this return a Box and work towards type correctness here.
2023-01-24 11:44:03 +01:00
Aliaksandr Kalenik
45e85d20b6 LibWeb: Output display type inline-table in layout dump 2023-01-17 10:18:33 +01:00
Aliaksandr Kalenik
709fe01f52 LibWeb: Override width calculation for table wrappers
Introduce `TableWrapper` type so table wrappers could be
distinguished from block containers and override width
calculation for table wrappers (CSS 2.2 spec, section 17.5.2)
 inside BFCs in the way that their width should be equal to
width of table box they wrap.
2023-01-14 19:22:08 +01:00
Andreas Kling
4d401bf796 LibWeb: Make the paint tree GC-allocated
This simplifies the ownership model between DOM/layout/paint nodes
immensely by deferring to the garbage collector for figuring out what's
live and what's not.
2023-01-11 12:55:00 +01:00
Aliaksandr Kalenik
57940f4370 LibWeb: Wrap table roots in anonymous block boxes
According to table fixup algorithm:
https://www.w3.org/TR/css-tables-3/#fixup-algorithm
around every table-root should be generated anonymous
box wrapper.

Also this patch implements important part of CSS 2.2
spec that is currently not present in CSS Tables 3
spec draft: https://www.w3.org/TR/CSS22/tables.html#model
that portion of computed properties should be moved
from table-root to table wrapper box. Without having
this part implemented height of absolutely positioned
table with `height: auto` won't be computed correctly.
2023-01-09 11:47:31 +01:00
Sam Atkins
5d8e3f5122 LibWeb: Convert Layout::Node to new pixel units 2023-01-05 17:42:31 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Andreas Kling
6d830e6335 LibWeb: Tie layout tree to a specific browsing context
Now that both the layout tree and browsing context are GC-allocated,
we can formalize their relationship a bit better by having layout
nodes keep a NonnullGCPtr to the browsing context.

This makes the previously-indirect link direct, removing an unpleasant
"how do we know the browsing context is alive" question when accessing
it from the layout tree.
2022-10-20 19:36:59 +02:00
Andreas Kling
268b9c5d90 LibWeb: Make the layout tree GC-allocated
This removes a set of complex reference cycles between DOM, layout tree
and browsing context.

It also makes lifetimes much easier to reason about, as the DOM and
layout trees are now free to keep each other alive.
2022-10-20 15:16:23 +02:00
Andreas Kling
be5a39657e LibWeb: Only store one DOM pointer per Layout::Node
Instead of storing two JS::Handles into the DOM, we can combine them
into a single one.

If the layout node is anonymous, m_dom_node points to the DOM::Document.
Otherwise, m_dom_node points to the associated DOM node.

The anonymous state is moved to an m_anonymous boolean member.

This cuts the number of JS::Handles created by the layout tree in half
(and shrinks Layout::Node by 8 bytes).
2022-10-20 15:16:23 +02:00
Andreas Kling
49eb324535 LibWeb: Add Layout::Node::display()
This will return something sensible for style-less nodes as well.
2022-10-06 16:25:26 +02:00
Andreas Kling
a0e6882d99 LibWeb: Remove Layout::Node::set_inline()
Now that this flag is no longer used, we can stop setting it.
2022-10-06 15:29:38 +02:00
Andreas Kling
5989a3ee77 LibWeb: Honor CSS display value in is_inline() and is_inline_block()
These were totally ad-hoc before, is_inline() was based on a boolean
flag on Layout::Node that we set in various situations.

Meanwhile, is_inline_block() was a combination on is_inline() plus a
type check to see if the layout node inherited from BlockContainer.

This patch replaces the above mess with simple lookups of the CSS
display value. Note that layout nodes without their own style (i.e text
nodes) are automatically assumed to be inline and non-blocks. This has
to be special-cased since layout nodes without style will consult the
style of their parent, so without short-circuiting this would break.
2022-10-06 15:29:38 +02:00
Andreas Kling
9e4226f353 LibWeb: Create flex items for empty generated boxes
I couldn't find anything in the specs about this, but GMail uses
empty generated boxes (`::before` and `::after` with `content: ""`)
inside a flexbox container in order to vertically center things.

The flexbox spec tells us to not generate flex items for empty
*anonymous* boxes, so we continue not doing that, but generated boxes
(any pseudo-element box) now always produce a flex item. This probably
isn't perfect either, and we'll have to revisit it for stuff like
`::first-letter`.
2022-09-29 20:09:49 +02:00
Andreas Kling
e36750d591 LibWeb: Remove unused Layout::Node::did_insert_into_layout_tree() 2022-09-20 10:32:12 +02:00
Ben Wiederhake
fe48fed4fa LibWeb: Break inclusion cycle by removing unnecessary include 2022-09-17 04:00:54 +00:00
Andreas Kling
6f433c8656 LibWeb+LibJS: Make the EventTarget hierarchy (incl. DOM) GC-allocated
This is a monster patch that turns all EventTargets into GC-allocated
PlatformObjects. Their C++ wrapper classes are removed, and the LibJS
garbage collector is now responsible for their lifetimes.

There's a fair amount of hacks and band-aids in this patch, and we'll
have a lot of cleanup to do after this.
2022-09-06 00:27:09 +02:00
MacDue
6a6475673f LibWeb: Convert images to common AbstractImageStyleValue base
This commit moves both the ImageStyleValue and LinearGradientStyleValue
to a common base class of AbstractImageStyleValue. This abstracts
getting the natural_width/height, loading/resolving, and painting
the image.

Now for 'free' you get:

 - Linear gradients working with the various background sizing/repeat
   properties.
 - Linear gradients working as list-markers :^) -- best feature ever!

P.s. This commit is a little large as it's tricky to make this change
incrementally without breaking things.
2022-08-08 22:39:06 +02:00
Andreas Kling
3ede8dbffb LibWeb: Rename IntrinsicSizeDetermination to IntrinsicSizing
This matches the exact terminology used in CSS-SIZING-3:
https://drafts.csswg.org/css-sizing-3/#intrinsic-sizing
2022-07-26 01:53:41 +02:00
Andreas Kling
71a707480c LibWeb: Move "has-definite-width/height" flags to UsedValues
This state is less static than we originally assumed, and there are
special formatting context-specific rules that say certain sizes are
definite in special circumstances.

To be able to support this, we move the has-definite-size flags from
the layout node to the UsedValues struct instead.
2022-07-26 01:53:41 +02:00
Andreas Kling
9b46091f38 LibWeb: Rename LayoutState::NodeState => LayoutState::UsedValues
This object contains all the CSS "used values" as seen during the layout
process, so calling it "used values" seems appropriate. :^)
2022-07-17 14:11:37 +02:00
Andreas Kling
52862c72d0 LibWeb: Rename FormattingState to LayoutState
This seems a bit more descriptive (and also a bit shorter).
2022-07-17 14:11:36 +02:00
Andreas Kling
0cacaf025d LibWeb: Stop putting the FormattingState nodes in a slow hash map
Instead, put them in a Vector<OwnPtr<NodeState>>. Each layout node
has a unique index into the vector. It's a simple serial ID assigned
during layout tree construction. Every new layout restarts the sequence
at 0 for the next ICB.

This is a huge layout speed improvement on all content.
2022-07-11 18:57:45 +02:00
Andreas Kling
64959a8504 LibWeb: Express intrinsic size layout via size constraints
Previously, we had three layout modes:

- Normal:
    - Everything uses the computed values from CSS.

- MinContent:
    - Containing blocks act as if they have 0 width.
    - All line breaking opportunities are taken.

- MaxContent:
    - Containing blocks act as if they have infinite width.
    - Only forced line breaks are accepted.

The above was based on a set of misunderstandings of CSS sizing.
A major problem with the above was that *all* containing blocks
behaved differently during intrinsic size layout, not just the
relevant one.

With this patch there are only two layout modes:

- Normal:
    - Everything uses the computed values from CSS.

- IntrinsicSizeDetermination:
    - One or more boxes have size constraints applied.

There are two size constraints per layout box, set here:

- FormattingState::NodeState::width_constraint
- FormattingState::NodeState::height_constraint

They are of type SizeConstraint and can be one of None, MinContent,
or MaxContent. The default is None.

When performing an IntrinsicSizeDetermination layout, we now assign
a size constraint to the box we're trying to determine the intrinsic
size of, which is then honored by using two new helpers to query
the dimensions of containing blocks:

- FormattingContext::containing_block_width_for(Box)
- FormattingContext::containing_block_height_for(Box)

If there's a relevant constraint in effect on the Box, the size of
its containing block is adjusted accordingly.

This is essentially an implementation of the "available space"
constraints from CSS-SIZING-3. I'm sure some things will break from
this, and we'll have to deal with that separately.

Spec: https://drafts.csswg.org/css-sizing-3/#available
2022-07-11 18:57:45 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Andreas Kling
329f06d59a LibWeb: Add Layout::Node::line_height()
This allows you to call line_height() on any layout node, even if it's a
text node (in which case we'll ask the parent node for its line-height.)
2022-03-24 18:14:01 +01:00
Andreas Kling
74927fd218 LibWeb: Move Layout::Box::is_out_of_flow() to Layout::Node
I want to use this function in inline layout, where we're not just
dealing with boxes.
2022-03-22 19:26:51 +01:00
Andreas Kling
c1f0d21bbe LibWeb: Rename the LayoutMode enum values and explain them
The old mode names, while mechanically accurate, didn't really reflect
their relationship to the CSS specifications.

This patch renames them as follows:

    Default => Normal
    AllPossibleLineBreaks => MinContent
    OnlyRequiredLineBreaks => MaxContent

There's also now an explainer comment with the LayoutMode enum about the
specific implications of layout in each mode.
2022-03-19 15:46:15 +01:00
Lenny Maiorani
c37820b898 Libraries: Use default constructors/destructors in LibWeb
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-03-17 17:23:49 +00:00