Instead of doing internal child layout incrementally as we go, save it
for the end of flex layout. The code will become simpler if we can focus
on simply computing the dimensions of each flex item while we're doing
the main FFC algorithm.
We don't need to perform inside layout here. The only information we
need in this step is whether an anonymous block container has nothing
but empty-or-whitespace text children.
This information is already accurate after the initial layout tree
construction. Performing a layout does not change the answer. It does
however have many other side effects, so let's defer those.
This implements at least some of the specification. inter-character is
not yet handled. However as our current algorithm only considers
whitespace as word breaks, inter-word could technically be considered to
be handled. :^)
All the justification-related code is now in
InlineFormattingContext::apply_justification_to_fragments and is
performed after all the line boxes have been added.
Text justification now only happens on the last line if the excess space
including whitespace is below a certain threshold. 10% seemed reasonable
since it prevents the "over-justification" of text. Note that fragments
in line boxes before the last one are always justified.
Everything related to hit testing is better off using the painting tree.
The thing being mousemoved over is a paintable, so let's hand that out
directly instead of the corresponding layout node.
Input events have nothing to do with layout, so let's not send them to
layout nodes.
The job of Paintable starts to become clear. It represents a paintable
item that can be rendered into the viewport, which means it can also
be targeted by the mouse cursor.
This patch adds a bunch of Paintable subclasses, each corresponding to
the Layout::Node subclasses that had a paint() override. All painting
logic is moved from layout nodes into their corresponding paintables.
Paintables are now created by asking a Layout::Box to produce one:
static NonnullOwnPtr<Paintable> Layout::Box::create_paintable()
Note that inline nodes still have their painting logic. Since they
are not boxes, and all paintables have a corresponding box, we'll need
to come up with some other solution for them.
BlockContainer paint boxes are the only ones that have line boxes
associated, so let's not waste memory on line boxes in all the other
types of boxes.
This also adds Layout::Box::paint_box() and the more tightly typed
Layout::BlockContainer::paint_box() to get at the paint box from the
corresponding layout box.
The "paintable" state in Layout::Box was actually not safe to access
until after layout had been performed.
As a first step towards making this harder to mess up accidentally,
this patch moves painting information from Layout::Box to a new class:
Painting::Box. Every layout can have a corresponding paint box, and
it holds the final used metrics determined by layout.
The paint box is created and populated by FormattingState::commit().
I've also added DOM::Node::paint_box() as a convenient way to access
the paint box (if available) of a given DOM node.
Going forward, I believe this will allow us to better separate data
that belongs to layout vs painting, and also open up opportunities
for naturally invalidating caches in the paint box (since it's
reconstituted by every layout.)
Note that we don't put absolutely positioned items on a line! This is
just so that IFC can discover boxes and pass them along to BFC.
This fixes an issue where only direct children of the IFC containing
block were considered for absolute positioning. Now we pick up
absolutely positioned children of nested inline nodes as well.
This patch adds support for "crisp-edges", "high-quality" and "smooth"
for the CSS image-rendering property.
"crisp-edges" maps to nearest-neighbor scaling for <canvas> and <img>
elements, while "high-quality" and "smooth" both use bilinear blending.
Previously, the decoration was painted behind the text. This probably
wasn't noticed before, as we didn't compute `text-decoration-color`
values yet and the decoration had the same color anyway.
Previosly, we used only the text color as a line decoration color.
The FIXME comment has been directly copy-pasted from the border color
note a few lines below.
If the content wants to be pixelated, we should honor that and paint
with nearest-neighbor scaling. The fact that it's faster is a nice bonus
as well. :^)
When calculating the intrinsic width of a block-level box, we were
previously measuring the content boxes of children. This meant that
shrink-to-fit sized blocks didn't gain enough width to contain children
with horizontal padding and/or border.
Until now, we've been treating the bottom of every line box fragment as
its baseline, and just aligning all the bottoms to the bottom of the
line box. That gave decent results in many cases, but was not correct.
This patch starts moving towards actual baseline calculations as
specified by CSS2.
Note that once layout is finished with a line box, we also store the
baseline of the line box in LineBox::m_baseline. This allows us to align
the real baseline of display:inline-block elements with other inline
content on the same line.
I was wrong in 56df05ae44, there are
situations where floating children should not affect the auto height of
their parent.
It turns out we were using the "height:auto for BFC roots" algorithm for
all height:auto blocks. This patch fixes that by splitting it into two
separate functions, and implementing most of the two different variants.
Note that we don't support vertical margin collapsing here yet.
Thanks to Tim for noticing the error! :^)
If an element with height:auto has any floating descendants whose bottom
margin edge is below the element's bottom content edge, then the height
is increased to include those edges.
Before this patch, we were stopping at the bottom *content* edge of
floating descendants.
This patch begins the support for the 'view-box' attribute that can be
attached to <svg>'s.
The FormattingContext determines the size of the Element according to
the specified 'width' and 'height' or if they are not given by the
'viewbox' or by the bounding box of the path if nothing is specified.
When we try to paint a SVG Path that belongs to a <svg> that has the
'view-box' and a specified 'height'/'width', all the parts of the path
get scaled/moved accordingly.
There probably are many edge cases and bugs still to be found, but this
is a nice start. :^)
Previously we used a native ui button to draw the buttons.
These buttons can however not be styled with css.
To allow these to be styled with css, we create a button with
the UA stylesheet that resembles the system ui button.
Instead of making a full copy of every NodeState when cloning a
FormattingState, we make NodeState ref-counted and implement a basic
copy-on-write mechanism.
FormattingState::get_mutable() now makes a deep copy of the NodeState
when first accessed *if* it is shared with other FormattingStates.
We now consider a layout box as having definite size in these cases:
- The size is a <length>.
- The size is a <percentage> and the containing block has definite size.
This is not complete, but a bit more accurate than what we had before.