Instead of trying to be clever and detaching the paint tree lazily,
just detach all paintables from both DOM and layout tree when building
and committing respectively.
Rather than resolving the text-shadow each time painting commands are
recorded, we can resolve it once during the layout commit and save the
resolved values in paintable fragments. This is also step towards
getting rid of layout node pointer in paintable fragment.
This is a part of refactoring towards making the paintable tree
independent of the layout tree. Now, instead of transferring text
fragments from the layout tree to the paintable tree during the layout
commit phase, we allocate separate PaintableFragments that contain only
the information necessary for painting. Doing this also allows us to
get rid LineBoxes, as they are used only during layout.
This patch makes a few changes to the way we calculate line-height:
- `line-height: normal` is now resolved using metrics from the used
font (specifically, round(A + D + lineGap)).
- `line-height: calc(...)` is now resolved at style compute time.
- `line-height` values are now absolutized at style compute time.
As a consequence of the above, we no longer need to walk the DOM
ancestor chain looking for line-heights during style computation.
Instead, values are inherited, resolved and absolutized locally.
This is not only much faster, but also makes our line-height metrics
match those of other engines like Gecko and Blink.
Until now, we had implemented flex container sizing by awkwardly doing
exactly what the spec said (basically having FFC size the container)
despite that not really making sense in the big picture. (Parent
formatting contexts should be responsible for sizing and placing their
children)
This patch moves us away from the Flexbox spec text a little bit, by
removing the logic for sizing the flex container in FFC, and instead
making sure that all formatting contexts can set both width and height
of flex container children.
This required changes in BFC and IFC, but it's actually quite simple!
Width was already not a problem, and it turns out height isn't either,
since the automatic height of a flex container is max-content.
With this in mind, we can simply determine the height of flex containers
before transferring control to FFC, and everything flows nicely.
With this change, we can remove all the virtuals and FFC logic for
negotiating container size with the parent formatting context.
We also don't need the "available space for flex container" stuff
anymore either, so that's gone as well.
There are some minor diffs in layout test results from this, but the
new results actually match other browsers more closely, so that's fine.
This should make flex layout, and indeed layout in general, easier to
understand, since this was the main weird special case outside of
BFC/IFC where a formatting context delegates work to its parent instead
of the other way around. :^)
Before this change, we used the wrong insertion point for flex items
in reverse layouts with `justify-content: normal`. This caused flex
items to overflow the flex containers "backwards" from the start edge.
This moves us a bit toward correctly representing two separate concepts
from the spec: lines and tracks. Lines divide the grid into tracks, so
there should always be a line concluding the last track.
- We now propagate changes in font and line-height to anonymous wrappers
when doing a partial style update after invalidation.
- We no longer (incorrectly) propagate style from table wrapper boxes
to the table root, since inheritance works in the other direction.
Fixes#22395
This change fixes the function that calculates the number of auto-fill
tracks, ensuring it uses height when applied to rows, instead of
assuming that it always operates on columns.
Fixes the mistake that gaps are counted as if they exist after each
track, when actually gaps are present only between tracks.
Visual progression on https://kde.org/products/
Similar to calculate_inner_width(), let's make the caller responsible
for handling "auto" instead of returning the input height as is when
when it cannot be resolved.
Initially, this function was made to return CSS::Length because some of
its callers were expecting it to ignore "auto" width on input and
return it as is. Instead, let's just forbid using "auto" for input
width and always return CSSPixels.
Percentage vertical margin and padding values are relative to the
containing block *width*, not *height*. This has to be one of the most
commonly recurring mistakes we make :^)
Fragments contained by the inline node should be painted in the
foreground phase for this node, instead of being painted as a part of
the containing PaintableWithLines. This change implements that by
marking all fragments contained by inline nodes so they can be skipped
while painting the content of PaintableWithLines. This is an ugly way,
and instead, we should make InlinePaintables own all fragments
contained by them.
Before this change, parsed grid-template-columns/grid-template-rows
were represented as two lists: line names and track sizes. The problem
with this approach is that it erases the relationship between tracks
and their names, which results in unnecessarily complicated code that
restores this data (incorrectly if repeat() is involved) during layout.
This change solves that by representing line definitions as a list of
sizes and names in the order they were defined.
Visual progression https://genius.com/
Before this change, we would only cache and reuse Gfx::ScaledFont
instances for downloaded CSS fonts.
By moving it into Gfx::VectorFont, we get caching for all vector fonts,
including local system TTFs etc.
This avoids a *lot* of style invalidations in LibWeb, since we now vend
the same Gfx::Font pointer for the same font when used repeatedly.
With this change "display: contents" ancestors are not considered as
insertion point for inline nodes similar to how we already ignore them
for non-inline nodes.
Fixes https://github.com/SerenityOS/serenity/issues/22396
In a bunch of cases, this actually ends up simplifying the code as
to_number will handle something such as:
```
Optional<I> opt;
if constexpr (IsSigned<I>)
opt = view.to_int<I>();
else
opt = view.to_uint<I>();
```
For us.
The main goal here however is to have a single generic number conversion
API between all of the String classes.
This patch adds basic support for the SVG `<textPath>`, so it supports
placing text along a path, but none of the extra attributes for
controlling the layout of the text. This is enough to correctly display
the MDN example.
The styling of elements using the `use_pseudo_element()` was only
applied on layout. When an element style was recomputed later that
styling was not overruled with the pseudo element selector styles.
This moves the styling override from `TreeBuilder.cpp` to
`StyleComputer.cpp`. Now the styles are always correctly applied.
I also removed the method `property_id_by_index()` because it was
not needed anymore.
Als some calls to `invalidate_layout()` in the Meter, Progress and
Select elements where not needed anymore because the style values
are update on the changing of the style attribute.
This fixes issue #22278.
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).
This commit is auto-generated:
$ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
Meta Ports Ladybird Tests Kernel)
$ perl -pie 's/\bDeprecatedString\b/ByteString/g;
s/deprecated_string/byte_string/g' $xs
$ clang-format --style=file -i \
$(git diff --name-only | grep \.cpp\|\.h)
$ gn format $(git ls-files '*.gn' '*.gni')
No functional impact intended. This is just a more complicated way of
writing what we have now.
The goal of this commit is so that we are able to store the 'name' of a
pseudo element for use in serializing 'unknown -webkit-
pseudo-elements', see:
https://www.w3.org/TR/selectors-4/#compat
This is quite awkward, as in pretty much all cases just the selector
type enum is enough, but we will need to cache the name for serializing
these unknown selectors. I can't figure out any reason why we would need
this name anywhere else in the engine, so pretty much everywhere is
still just passing around this raw enum. But this change will allow us
to easily store the name inside of this new struct for when it is needed
for serialization, once those webkit unknown elements are supported by
our engine.
Out-of-flow boxes (floating and absolutely-positioned elements) were
previously collected and put in the anonymous block wrapper as well, but
this actually made hit testing not able to find them, since they were
breaking expectations about tree structure that hit testing relies on.
After this change, we simply let out-of-flow boxes stay in their
original parent, preserving the author's intended box tree structure.
According to the CSS font matching algorithm specification, it is
supposed to be executed for each glyph instead of each text run, as is
currently done. This change partially implements this by having the
font matching algorithm produce a list of fonts against which each
glyph will be tested to find its suitable font.
Now, it becomes possible to have per-glyph fallback fonts: if the
needed glyph is not present in a font, we can check the subsequent
fonts in the list.
Sizing already worked correctly, but before this change, we were too
aggressive with inserting line breaks when negative margins would
still an atomic inline to fit on the line.
This change fixes a problem that we should not call `to_px()` to
resolve any length or percentage values during paintables traversal
because that is supposed to happen while performing layout.
Also it improves performance because before we were resolving border
radii during each painting phase but now it happens only once during
layout.