This fixes the issue where max margin is used to find offset of
floating box although horizonal margins do not collapse so they need
to be summed instead.
This fixes a plethora of rounding problems on many websites.
In the future, we may want to replace this with fixed-point arithmetic
(bug #18566) for performance (and consistency with other engines),
but in the meantime this makes the web look a bit better. :^)
There's a lot more things that could be converted to doubles, which
would reduce the amount of casting necessary in this patch.
We can do that incrementally, however.
Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.
This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.
All users of `Gfx::Rect` have been updated accordingly.
Before this change, LayoutState essentially had a Vector<UsedValues*>
resized to the exact number of layout nodes in the current document.
When a nested layout is performed (to calculate the intrinsic size of
something), we make a new LayoutState with its own Vector. If an entry
is missing in a nested LayoutState, we check the parent chain all the
way up to the root.
Because each nested LayoutState had to allocate a new Vector with space
for all layout nodes, this could get really nasty on very large pages
(such as the ECMA262 specification).
This patch replaces the Vector with a HashMap. There's now a small cost
to lookups, but what we get in return is the ability to handle huge
layout trees without spending eternity in page faults.
This fixes a crash in box_baseline, due to cells created for
display: table expecting a box child and getting the inline node wrapper
instead.
Fixes#18972.
Using HashTable of grid positions to represent OccupationGrid allows to
simplify positioning code. For example maybe_add_row() and
maybe_add_column() calls are not needed anymore because there is no
Vector<Vector<bool>> that need to be resized.
No observable changes in grid layout are expected :)
Since the specifications indicate that the algorithm for sizing tracks
without any spanning items is a simplified version of the more general
algorithm used for sizing tracks with spanning items, we can reuse the
code to size both cases.
Implements more parts of sizing algorithm for tracks with spanning
items to archive parity with implementation for sizing of tracks
with non-spanning items.
We have to special-case these, otherwise our normal CSS layout algorithm
will see that some SVG roots have width/height assigned, and make those
the used width/height.
When used in an SVG-as-image context, the outermost viewport must be the
authoritative root size.
This allows the painting subsystem to request a bitmap with the exact
size needed for painting, instead of being limited to "just give me a
bitmap" (which was perfectly enough for raster images, but not for
vector graphics).
This implements the stop-opacity, fill-opacity, and stroke-opacity
properties (in CSS). This replaces the existing more ad-hoc
fill-opacity attribute handling.
There are a couple of things that went into this:
- We now calculate the intrinsic width/height and aspect ratio of <svg>
elements based on the spec algorithm instead of our previous ad-hoc
guesswork solution.
- Replaced elements with automatic size and intrinsic aspect ratio but
no intrinsic dimensions are now sized with the stretch-fit width
formula.
- We take care to assign both used width and used height to <svg>
elements before running their SVG formatting contexts. This ensures
that the inside SVG content is laid out with knowledge of its
viewport geometry.
- We avoid infinite recursion in tentative_height_for_replaced_element()
by using the already-calculated used width instead of calling the
function that calculates the used width (since that may call us right
back again).
In order to fix this, I also had to reorganize the code so that we
create an independent formatting context even for block-level boxes
that don't have any children. This accidentally improves a table
layout test as well (for empty tables).
Adds support for grid items with fixed size paddings. Supporting
percentage paddings will probably require to do second pass of tracks
layout: second pass is needed to recalculate tracks sizes when final
items sizes are known when percentage paddings are already resolved.
This change addresses the incorrect assumption that the available width
inside a grid item is equal to the width of the track it belongs to.
For instance, if a grid item has a width of 200px, the available width
inside that item is also 200px regardless of its column(s) base size.
To solve this issue, it was necessary to move the final resolution of
grid items to occur immediately after the final column track sizes are
determined. By doing so, it becomes possible to obtain correct
available width inside grid items while resolving the row track sizes.
This change makes grid items be responsible for their borders instead
of grid tracks which can not have borders itself.
There are changes in layout tests but those are improvements :)
1. Propagate calc() values from StyleProperties to ComputedValues.
2. Actually resolve calc() values when determining the used flex basis.
This makes the "support" section on https://shopify.com/ show up
correctly as a 2x2 grid (instead of 1x4). :^)
While inline content between floating elements was broken correctly,
text justification was still using the original amount of available
space (without accounting for floats) when justifying fragments.
This code now works in terms of *intrusion* by left and right side
floats into a given box whose insides we're trying to layout.
Previously, it worked in terms of space occupied by floats in the root
box of the BFC they participated in. That created a bunch of edge cases
since the code asking about the information wasn't operating in root
coordinate space, but in the coordinate space of some arbitrarily nested
block descendant of the root.
This finally allows horizontal margins in the containing block chain to
affect floats and nested content correctly, and it also allows us to
remove a bogus workaround in InlineFormattingContext.
item_incurred_increase should be reset before every next distirbution
because otherwise it will accumulate increases from previous
distributions which is not supposed to happen.
Note that this simple form of text-indent only affects the first line
of formatted content in each block.
Percentages are resolved against the width of the block.
Fixes the issue when if there are enough rows/column to force
m_row_gap_tracks or m_column_gap_tracks be resized during gaps
initialization then pointers stored in m_grid_columns_and_gaps or
m_grid_rows_and_gaps become invalid.
After finishing layout, iframe layout boxes (FrameBox) get notified
about their new size by LayoutState::commit(). This information is
forwarded to the nested browsing context, where it can be used for
layout of the nested document.
The problem here was that we notified the FrameBox twice. Once when
assigning the used offset to its paintable, and once when assigning its
size. Because the offset was assigned first, we ended up telling the
FrameBox "btw, your size is 0x0". This caused us to throw away all
the layout information we had for the nested document.
We'd then say "actually, your size is 300x200" (or something) but by
then it was already too late, and we had to do a full relayout.
This caused iframes to flicker as every time their containing document
was laid out, we'd nuke the iframe layout and redo it (on a zero timer).
The fix is pleasantly simple: we didn't need to inform the nested
document of its offset in the containing document's layout anyway. Only
its size is relevant. So we can simply remove the first call, which
removes the bogus 0x0 temporary size.
Note that iframes may still flicker if they change size in the
containing document. That's a separate issue that will require more
finesse to solve. However, this fixes a very noticeable common case.
This change is supposed to solve the problem that currenty when grid
tracks are interleaved with gaps it is impossible to iterate tracks
spanned by a specific grid item. There is a pair of functions:
gap_adjusted_row() and gap_adjusted_column() but they won't work
when it comes to items spanning > 1 track.
Separating gaps from tracks is going to make it possible to iterate
just tracks or both tracks and gaps when it is required. And now tracks
spanned by an item can be accessed by just index without doing any
additional math.