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 :^)
We were mistakenly creating stacking contexts for all elements with
non-static CSS position.
For `absolute` and `relative`, we should only create stacking contexts
if the `z-index` value is something other than `auto`.
This makes it possible to click the cookie on Cookie Clicker. :^)
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.
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.
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).
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.
Let's not assume the containing block has a paintable box just because
someone is calling set_needs_display(). It can just be a no-op in that
case, and nobody gets hurt.
This patch changes the *computed* representation of the following CSS
properties to use CSS::Size:
- width, min-width, max-width
- height, min-height, max-height
A few things had to change in order for things to keep working,
but I tried to keep the diff to a minimum.
The main trouble was that `min-width` and `max-width` can't actually be
`auto`, but they *can* be `none`. We previously treated `auto` as a
valid value (and it behaved mostly like `none`).
Instead of asking Gfx::FontDatabase for the "default font" and the
"default fixed-width font", we now proxy those requests out via
the Platform::FontPlugin. This will allow Ladybird to use other default
fonts as fallback.
We didn't set their display at all before, and since CSS display is not
inherited, anonymous block wrappers were actually "display: inline", but
it kinda worked anyway because we positioned blocks based on their C++
class (BlockContainer) rather than their CSS display value.
Now that we position based on CSS display value, this broke positioning
of anonymous wrapper blocks, and this fixes that.
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.
Add functionality to begin parsing grid-template-columns and
grid-template-rows. There are still things to be added, like parsing
functions, but I would say a couple of the major points are already
adressed like length, percentage, and flexible-length.
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.
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.
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
This commit moves the length calculations out to be directly on the
StringView users. This is an important step towards the goal of removing
StringView(char const*), as it moves the responsibility of calculating
the size of the string to the user of the StringView (which will prevent
naive uses causing OOB access).
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.
The spec grammar for `text-decoration-line` is:
`none | [ underline || overline || line-through || blink ]`
Which means that it's either `none`, or any combination of the other
values. This patch makes that parse for `text-decoration-line` and
`text-decoration`, stores the results as a Vector, and adjusts
`paint_text_decoration()` to run as a loop over all the values that are
provided.
As noted, storing a Vector of values is a bit wasteful, as they could be
stored as flags in a single `u8`. But I was getting too confused trying
to do that in a nice way.
By the time that property() gets called, we've already given every
single property a value, so we can just return it. This simplifies a
lot of places that were manually handling a lack of value
unnecessarily.
This function was written as if it returned `Optional<CSS::BoxSizing>`
but actually returned a plain `CSS::BoxSizing`, meaning if the property
was not set or was invalid, it would return whichever enum value was
first. This wasn't visible because we don't yet pay any attention to
the `box-sizing` property.
For things like "line-height: 2" to work, the font size must be assigned
before resolving the line height. Previously, the line-height was
resolved first, which meant that numeric and other relative units were
resolved against the default font-size instead.
1. Make this decision *after* we've inserted the layout node into the
layout tree. Otherwise, we can't reach its containing block!
2. Per css-sizing-3, consider auto-sized blocks whose sizes resolve
solely against other definite sizes as definite themselves.
In particular, (2) makes us consider width:auto block children of a
definite-size containing block as having definite size. This becomes
very important in flex layout.