This isn't entirely symmetrical with on_load_start as it will also fire
on reloads and back/forward navigations. However, it's good enough for
some basic use cases, and we can do more sophisticated notifications
later on when we need them.
The width of a line box is the distance from the left edge of the first
fragment to the right edge of the last fragment. We don't have to loop
over all the fragments to figure this out. :^)
Instead of invoking the CSS parser every time we compute the style for
an element that has a "style" attribute, we now cache the result of
parsing the inline style whenever the "style" attribute is set.
This is a nice boost to relayout performance since we no longer hit the
CSS parser at all.
This patch removes a bunch of the less generally useful information
from layout tree dumps and puts it behind some optional bool params.
We also show layout units as integers instead of floats for now,
since fractional layout almost never happen anyway (yet) and this makes
it much easier to read.
I didn't generalize this into a helper since the HTML spec doesn't
seem to use this particular algorithm for anything else.
This makes the ACID1 test title show up correctly. :^)
Once we've generated enough lines to make it past all the floating
boxes on either side, just forget those boxes. This simplifies the
available space computation since we don't have to consider boxes
that can't vertically intersect the current line anyway.
After we've cleared past some floating elements, we should not keep
stacking new floats horizontally.
Instead, new floats after the clear should once again start at the
left or right edge of their containing block.
Within the same stacking context, positioned elements must be painted
after non-positioned ones.
I added a Layout::Node::for_each_child_in_paint_order() to help with
this since it's also needed for hit testing.
The BFC "context box" is now the outer box of the block formatting
context. Previously the context box was always the current target box,
which made it hard to reason about who was really the containing block
of whom in various places.
Note that IFC still has the containing block as its context box, this
change only affects BFC. However, to clarify the situation in IFC,
I've added a containing_block() getter than returns the context_box().
Instead of plowing through all the floating boxes within a BFC and
doing all the layout up front, do the children of each block as we go.
This will allow us to know the vertical position of the containing
block when placing floats.
I realized that we're supposed to float the boxes sideways, but not
always to y=0, so that makes it logical to share the placement logic
with other normal non-replaced blocks.
This is still pretty buggy but we're getting closer. :^)
This is definitely not fully-featured, but basically we now handle
the clear property by forcing the cleared box below the bottom-most
floated box on the relevant side.
I don't know why basing the available space between floats on the y
coordinate in the middle of each line seemed like a good idea. It just
creates situations with a few pixels of floats overlapping text!
I'm not sure what this was trying to achieve, but it was moving all
line fragments upwards and a lot of things look a lot better if we
just stop doing that.
I had guessed that floating boxes should somehow be hoisted up to the
nearest block ancestor that creates a block formatting context, but
that's just wrong. They move up to the nearest block ancestor like any
other box that's not absolutely (or fixed) positioned. :^)
Boxes can now be floated left or right, which makes text within the
same block formatting context flow around them.
We were creating way too many block formatting contexts. As it turns
out, we don't need one for every new block, but rather there's a set
of rules that determines whether a given block creates a new block
formatting context.
Each BFC keeps track of the floating boxes within it, and IFC's can
then query it to find the available space for line boxes.
There's a huge hack in here where we assume all lines are the exact
line-height. Making this work with vertically non-uniform lines will
require some architectural changes.
We were not accounting for space occupied by borders when computing
the vertical (y) position of blocks. This meant that blocks with wide
top/bottom borders could bleed into each other incorrectly.
Fix this by using the combined padding+border geometry instead of just
the padding when placing blocks on the y axis.
We were incorrectly resolving relative length units (ex, em, etc.)
against the containing block in many cases. Fix this to resolve them
against the descendant box we're currently processing.
Instead of doing a CSS property lookup for the line style of each
border edge during paint, we now cache the final CSS::LineStyle to use
in the Layout::BorderData.
In order for inline elements (e.g <span>) to contribute padding etc.
to line boxes, we now create special "leading" and "trailing" fragments
for Layout::InlineNode and size them according to the horizontal
padding values.
The height of these fragments is taken from the tallest fragment on the
line. (Perhaps we should stop having per-fragment heights and just keep
a single height per line box, but that's a separate issue.)
In order to make things look nice, we now also adjust the height of all
fragments on a line so that nobody is shorter than the CSS line-height.
Fragment painting was very limited by only being called during the
foreground paint phase. We now paint fragments as part of every phase
(and the phase is passed to paint_fragment() of course!)
We were rejecting perfectly valid z-index values like '1000' since we
were passing all CSS values through the length parser and unit-less
lengths are not valid in this context.
It's yet another hack for the ad-hoc CSS parser (its days are numbered)
but this makes the top header links on google.com actually work. :^)
Calling Frame::set_size() already triggered a relayout, so calling
layout() again right after meant we did all the work one more time.
Not being dumb like this makes resizing significantly smoother. :^)