Since more DOM nodes are going to want to load images (<object>, ...)
this patch splits out the image loading logic into an ImageLoader class
and then HTMLImageElement simply has an ImageLoader.
LayoutImage is then given a const ImageLoader& at construction and can
then provide layout and rendering for many kinds of DOM nodes.
This kind of HTML now produces a single piece of whitespace:
<span> </span> <span> </span> <span> </span>
We achieve this by checking if the last fragment on the last line ends
in whitespace. If so, we either don't add a fragment at all (for the
current chunk) or we simply skip over all whitespace at the head of
the current chunk (instead of collapsing it to a single ' '.)
To get the expected behavior for <center>, we needed a special text
alignment mode that centers block-level elements (and not just line
box fragments.)
Table row layout is now split into two phases:
1. Compute all the column widths (even taking colspan into account!)
2. Place all cells at the correct x,y offsets based on column widths.
Both phases visit all rows and all cells.
Get rid of the weird old signature:
- int StringType::to_int(bool& ok) const
And replace it with sensible new signature:
- Optional<int> StringType::to_int() const
Skip over absolutely positioned children when laying out the inline
children of a block. This takes them out of the flow and allows them
to be positioned correctly relative to the (absolute) containing block.
Absolutely positioned elements are placed by their containing block.
Instead of trying to compute its own position, LayoutReplaced will
now simply add itself as an absolutely positioned descendant of its
containing block.
Fixed position elements have the ICB as their containing block.
The magic of fixed positioning is implemented at the rendering stage,
where we temporarily translate painting by the current scroll offset.
Note that "absolutely positioned" includes both position:absolute
and position:fixed.
Absolutely positioned blocks now register themselves with their
containing block (and note that the containing block of an absolutely
positioned box is the nearest non-statically positioned block ancestor
or the ICB as fallback.)
Containing blocks then drive the layout of their tracked absolutely
positioned descendants as a separate layout pass.
This is very far from perfect but the general direction seems good.
The box tree and line boxes now all store a relative offset from their
containing block, instead of an absolute (document-relative) position.
This removes a huge pain point from the layout system which was having
to adjust offsets recursively when something moved. It also makes some
layout logic significantly simpler.
Every box can still find its absolute position by walking its chain
of containing blocks and accumulating the translation from the root.
This is currently what we do both for rendering and hit testing.
* A PageView is a view onto a Page object.
* A Page always has a main Frame (root of Frame tree.)
* Page has a PageClient. PageView is a PageClient.
The goal here is to allow building another kind of view onto
a Page while keeping the rest of LibWeb intact.
This patch introduces support for more than just "absolute px" units in
our Length class. It now also supports "em" and "rem", which are units
relative to the font-size of the current layout node and the <html>
element's layout node respectively.
We don't support incremental relayout of subtrees (only single nodes)
but let's not crash the browser just because this happens. We can keep
the browser up and just complain in the debug log instead.
This patch introduces a bunch of things:
- Subframes (Web::Frame::create_subframe())
- HTMLIFrameElement (loads and owns the hosted Web::Frame)
- LayoutFrame (layout and rendering of the hosted frame)
There's still a huge number of things missing, like scrolling, overflow
handling, event handling, scripting, etc. But we can make a little
iframe in a document and it actually renders another document there.
I think that's pretty cool! :^)
LayoutReplaced now has intrinsic width, height and ratio. Only some of
the values may be present. The layout algorithm takes the various
configurations into account per the CSS specification.
This is still pretty immature but at least we're moving forward. :^)
This patch adds ImageResource as a subclass of Resource. This new class
also keeps a Gfx::ImageDecoder so that we can share decoded bitmaps
between all clients of an image resource inside LibWeb.
With this, we now share both encoded and decoded data for images. :^)
I had to change how the purgeable-volatile flag is updated to keep the
volatile-images-outside-the-visible-viewport optimization working.
HTMLImageElement now inherits from ImageResourceClient (a subclass of
ResourceClient with additional image-specific stuff) and informs its
ImageResource about whether it's inside the viewport or outside.
This is pretty awesome! :^)
There's more to life than inline-vs-block, so we have to take all the
non-block non-inline display types into account when computing whether
a block should say children_are_inline() == true.
.. and make travis run it.
I renamed check-license-headers.sh to check-style.sh and expanded it so
that it now also checks for the presence of "#pragma once" in .h files.
It also checks the presence of a (single) blank line above and below the
"#pragma once" line.
I also added "#pragma once" to all the files that need it: even the ones
we are not check.
I also added/removed blank lines in order to make the script not fail.
I also ran clang-format on the files I modified.
We now implement the somewhat fuzzy shrink-to-fit algorithm when laying
out inline-block elements with both block and inline children.
Shrink-to-fit works by doing two speculative layouts of the entire
subtree inside the current block, to compute two things:
1. Preferred minimum width: If we made a line break at every chance we
had, how wide would the widest line be?
2. Preferred width: We break only when explicitly told to (e.g "<br>")
How wide would the widest line be?
We then shrink the width of the inline-block element to an appropriate
value based on the above, taking the available width in the containing
block into consideration (sans all the box model fluff.)
To make the speculative layouts possible, plumb a LayoutMode enum
throughout the layout system since it needs to be respected in various
places.
Note that this is quite hackish and I'm sure there are smarter ways to
do a lot of this. But it does kinda work! :^)
Add reasonable support for all values of white-space CSS property.
Values of the property are translated into a 3-tuple of rules:
do_collapse: whether whitespace is to be collapsed
do_wrap_lines: whether to wrap on word boundaries when
lines get too long
do_wrap_breaks: whether to wrap on linebreaks
The previously separate handling of per-line splitting and per-word
splitting have been unified. The Word structure is now a more
general Chunk, which represents different amounts of text depending
on splitting rules.
When hit testing encountered a block with inline children, we assumed
that the inline children are nothing but text boxes. An inline-block
box is actually a block child of a block with inline children, so we
have to handle that scenario as well. :^)
Fixes#2353.
Many properties can now have percentage values that get resolved in
layout. The reference value (what is this a percentage *of*?) differs
per property, so I've added a helper where you provide a reference
value as an added parameter to the existing length_or_fallback().
Previously we would only check if the border width property is empty and
skip drawing in that case, and enforcing a minimum width of 1px
otherwise - but "border: 0;" should not paint a border :^)
This is a workaround for the silly issue where some content would move
one pixel upward on every layout. The block layout code was finding
the list item marker and doing regular inline layout on it. We were not
prepared to handle this, which caused it to move in a silly way.
For now, just regenerate markers on every layout to work around the
issue. In the future we should figure out a nice way to layout markers.