This makes use of the new Gfx::Path::text() to handle SVG text elements,
with this text is just a regular path, and can be manipulated like any
other graphics element.
This removes the SVGTextPaintable and makes both <text> and geometry
elements use a new (shared) SVGPathPaintable. This is identical to the
old SVGGeometryPaintable. This simplifies painting as once something is
resolved to a Gfx::Path, the painting logic is the same.
When calculating the width of text using a bitmap font, a glyph spacing
is added at the end of each fragment, including the last one. This meant
that everything was 1 pixel too long. This bug did not affect vector
fonts.
Before this change, we were doing it after every layout, which meant
that already-propagated overflow could be propagated again, which led to
incorrect scrolling behavior.
Previously, all SVG <text> elements were zero-sized boxes, that were
only actually positioned and sized during painting. This led to a number
of problems, the most visible of which being that text could not be
scaled based on the viewBox.
Which this patch, <text> elements get a correctly sized layout box,
that can be hit-tested and respects the SVG viewBox.
To share code with SVGGeometryElement's the PathData (from the prior
commit) has been split into a computed path and computed transforms.
The computed path is specific to geometry elements, but the computed
transforms are shared between all SVG graphics elements.
Changing `try_compute_width()` to return width and margins, instead of
mutating them in the box's state makes it works in cases when box has
min-width or max-width and this function needs to be called multiple
times.
Fixes https://github.com/SerenityOS/serenity/issues/21598
As spec comment in the code says we should use item’s max-content
contribution to calculate flex fraction.
Likely, it was calculate_max_content_size() because we didn't have
calculate_max_content_contribution() when this function was implemented
initially.
Rewrites the grid area building to accurately identify areas that span
multiple rows. Also now we can recognize invalid areas but do not
handle them yet.
Grid items should respect alignment properties if top/right/bottom/left
are not specified.
This change adds a separate implementation of
layout_absolutely_positioned_element that is extended with support for
alignment.
If the first pass of rows sizing results in the container's automatic
height being less than the specified min-height, we need to run a
second pass using the updated available space.
493dd5d93c caused the `::before`
pseudo-element node to be inserted before the element's content, which
caused issues with how we determine where to insert inline nodes into
the layout tree. At the time, I noticed the issue with contents of flex
containers, and prevented them from merging into a `::before` box.
However, a similar situation happens when we're not in a flex container,
but the pseudo-element has `display: block`. This commit fixes that
situation by using the same logic in both places, so a similar mistake
can't be made again.
This fixes the tab text being invisible on GitHub project pages. :^)
We were incorrectly offsetting the static position of abspos children of
flex containers by the padding twice. This was a misguided attempt to
adjust to the abspos containing block being the padding box, not the
content box.
Fixes#21344.
This makes multiple levels of quote actually use different quotation
marks, instead of always the first available pair of them.
Each Layout::Node remembers what the quote-nesting level was before its
content was evaluated, so that we can re-use this number in
`apply_style()`. This is a bit hacky, since we end up converting the
`content` value into a string twice.
`StyleProperties::content()` now takes an initial quote-nesting level,
and returns the final level after that content.
For now, part of this is commented-out. Our current implementations of
`<mask>` and `<symbol>` rely on creating layout nodes, so they can't be
`display: none`.
Before, we only ensured that boxes establishing BFC did not overlap
with floats because that is what CSS 2.2 specification says. However,
we should also apply the same for boxes establishing FFC or GFC as this
aligns with the behavior of other browsers.
Fixes https://github.com/SerenityOS/serenity/issues/21095
This allows SVG mask elements to have layout computed, but not connected
to the main paint tree. They should only be reachable if (and painted)
if referenced by the "mask" attribute of another element.
This is controlled by the forms_unconnected_subtree() function on the
paintable, which (if it returns true) prevents the paintable from being
added as a child to what would be its parent.
We shouldn't be putting generated pseudo elements inside elements that
can't have children in the first place.
This patch fixes two issues:
- We stop generating pseudo elements for layout nodes that can't have
children anyway.
- We mark Layout::BreakNode as not being able to have children.
The spec requires that details elements be assigned a shadow tree with
two slots. The first slot is assigned the first summary child element of
the details element. The second slot is assigned all other children.
When calculating the edge offset of the next floating item based on the
offset of the preceding floating item, we need to ensure that the
preceding offset is always > 0. This isn't explicitly written in the
spec, but all other popular engines do that.
Fixes https://github.com/SerenityOS/serenity/issues/21023
Before, we completely ignored clearance for block-level boxes if they
were floated. This was incorrect because it is valid for a block-level
box to be floated and still have clearance. However, unlike clearance
on normal flow boxes, clearance on floating boxes does not affect the
y-position of subsequent normal flow boxes. Instead, it pushes the
box's position to the very beginning of an edge.
Work towards https://github.com/SerenityOS/serenity/issues/21023
This is a simple mapping of some code-points to others.
I was going to use a ref test for this, but without knowing that the
font contains the code-points (which SerenitySans does not) we'd be
comparing a series of replacement characters to a series of replacement
characters, which doesn't tell you if they're the right code-points
underneath.
This one is a bit fun because it can be `add(<integer>)` or `auto-add`,
but children have to inherit the computed value not the specified one.
We also have to compute it before computing the font-size, because of
`font-size: math` which will be implemented later.
Previously we were overly generous in what we accepted for `display`.
For example, we accepted:
- Multiple outside or inside identifiers
- Unrecognized identifiers
- Non-identifier tokens
Now, we reject all these cases. This makes us stop accepting the
`display: block math;` declaration in `MathML/Default.css`, and so the
one layout test we have containing MathML elements has changed to
reflect that.
When a button should use flex for alignment and also has ::before
and/or ::after, we previously did the following:
1. Prepended/appended the button's children with boxes for
pseudo-elements.
2. Replaced the button's direct children with a flex container that
contains its children.
As a result, the generated boxes for ::before/::after ended up as
children of the generated flex item, instead of being direct children
of the button layout box as they were supposed to be.
This change reverses these steps, ensuring that boxes for
pseudo-elements are generated only after modifications inside the
button layout are completed.
When modifying the button layout during tree building to use flex for
vertical alignment, let's explicitly set the button box's children to
be non-inline. It doesn't make sense to layout the button as an IFC
when its only child is a flex container.
Before, we were using the line height from NodeWithStyle::line_height()
to calculate the y offset for floats inside the IFC. However, this
value doesn't always correspond to the actual height of a line box. For
instance, adding a fragment for an inline-block might change the height
of the line box. With this change, we recalculate the height of the
line box after adding a new fragment and use this recalculated height
value to determine the y position for floats.
Fixes https://github.com/SerenityOS/serenity/issues/20982
If an element is created from JS, it might have its contents modified
before it is inserted into the document. In this case, we don't have a
shadow tree yet and so trying to set m_text_node's text content would
cause a null dereference. So let's not do that. :^)
That case also means that by the time we do create the shadow tree, we
have the text content already, so we can set it there.
Added a test to verify that we don't crash, and that the text content
appears in the textarea whether it was inserted by JS or by the HTML
parser.
Previously, the code assumed that in dividing up the space in the
affected tracks there would never be an overshoot. Instead, we can
check for each track how much extra space is left and never consume any
extra.
In the same way, we can ensure that all extra space is consumed by
distributing all remaining extra space starting from the first track.
Thus, if there is no growth limit, the space distribution should always
consume all the extra space.
The spec says that the sum of affected size + item-incurred increase
should reach the limit, rather than just the item-incurred increase.
This seems to improve layout on the testcase `row-span-2-with-gaps`.
The extra line of space at the bottom of the left div
(`div.grid-item.item-span-two`) is not present anymore, matching other
browsers' layout much more closely.
The final used values for these properties is stored in the layout node,
so we need to make sure they are propagated there as well when doing
table box fixup.
Some replaced elements can have intrinsic aspect ratios but no
intrinsic size. In these cases, the tentative sizes are undefined, and
can therefore sometimes be zero. However, when resolving the size
constraints, we are already guaranteed to have an intrinsic aspect
ratio, so let's use that instead to calculate the resolved sizes.
This allows us to retain perfect precision for aspect ratios derived
from either the intrinsic sizes of replaced elements, or the
`aspect-ratio` CSS property.
There's a particularly awkward case where the static position of an
abspos child of a flex container is dependent on its height. This can
happen when `align-items: center` is in effect, as we have to adjust
the abspos child's Y position by half of its height.
This patch solves the issue by reordering operations in the abspos
height resolution algorithm, to make sure that height is resolved
before the static position is calculated.
Using flex layout inside button solves the issue with wrongly calculated
height when it has: pseudo element and whitespaces inside.
Also using flex instead of a table layout allows for the same vertical
alignment but with fewer layout nodes: a flex container and anonymous
wrapper for content instead of a table wrapper, table, row, and cell.
Before this change, we were creating a new anonymous flex item for every
inline-level child of a flex container, even when we had a sequence of
inline-level children.
The fix here is to simply keep putting things in the last child of the
flex container, if that child is already an anonymous flex item.
Previously we always set the height of the HTML element equal to the
viewport height but now this will only happen in quirks mode as it is
intended. Otherwise the html element height will be computed as auto.
Since we always pass the px value as an argument to resolved(), we can
pass it directly as CSSPixels instead of wrapping it in Length. This
approach allows us to avoid converting to a double, resulting in fewer
precision issues.
When text paintables shift around in the tree due to line wrapping,
we may end up in a situation where some text node does not generate
a paintable (due to being all whitespace, for example), even though
in the previous layout pass, it *did* generate a paintable.
To prevent holding on to old paintables in such cases, we now do a
pass in LayoutState::commit() where we explicitly detach all old
paintables from the layout tree.
We need to start looking from the beginning of current row if adding
new implicit column track made enough space to accomodate spanning item
This fixes placement for spanning grid items when `grid-auto-flow` is
specified to `column`.
If the table used width has to be adjusted because of a cell with
percentage width, add back the undistributable space due to border
spacing. This is consistent with the width distribution algorithm, which
sets aside the undistributable space and the behavior of other browsers.
When the grid layout gets to
`resolve_items_box_metrics(GridDimension::Column)`, we've already
determined the width of each column. However, the widths of the
individual grid items themselves haven't been set. Rather than using
`get_available_space_for_item()`, which returns an indefinite size if
an item's width/height hasn't been set, we should use the already
known track width as the available size to calculate the fit-content
width.
In general it is not safe to convert any arbitrary floating-point value
to CSSPixels. CSSPixels has a resolution of 0.015625, which for small
values (e.g. scale factors between 0 and 1), can produce bad results
if converted to CSSPixels then scaled back up. In the worst case values
can underflow to zero and produce incorrect results.
- Ambiguous `raw_value()` method is replaced with `line_number()` and
`span()`.
- `line_name()` that before returned either line name or area name is
replaced with `line_name()` and `area_name()`.
- `Position` type is replaced with `Line` and `Area` type so we don't
have to guess while doing layout.
Affected test expectations:
- `template-lines-and-areas` - improvement over what we had before.
- `named-tracks` - rebaseline a giant test. will have to split it into
smaller tests in the future.
The resolution is simply 1dppx * device pixel ratio.
This makes high resolution images show up on https://apple.com/
when running on a high-DPI display. :^)
`DeprecatedString::to_int` calls `StringUtils::convert_to_int`
internally. However, the integer parsing is not done in an HTML
spec-compliant way. For example, `colspan="2;"` is valid according to
the spec. But, with the current implementation, we will fail to parse
"2;", and instead fall back to using 1 as the colspan value.
This patch changes the `HTMLTableCellElement::col_span` and
`HTMLTableCellElement::row_span` methods to use the
`Web::HTML::parse_non_negative_integer` function that will parse the
attribute value in an HTML spec-compliant way.
This giant grid test has been a source of problems while iterating on
GFC for a long time. Let's split it into smaller tests to make it
easier to identify issues without needing further reductions on the
test.
We were relying on the table fixup algorithm to insert the missing table
row, which fails to do so when we only have an image in the button.
While that might be a problem with the table fixup algorithm, we should
build a correct layout tree explicitly anyway.
Fixes crashes on GitHub.
Check the width of the next token after white space to decide line
breaks. The next width can also be the total width of multiple tokens.
This better follows the CSS Text specification and matches behavior of
other browsers.
Fixes#20388.
And treat them as "auto" for now, per CSS-SIZING-3, with a FIXME about
supporting more layout directions.
This fixes an issue on MDN where `height: max-content` was not
overriding height from non-CSS presentational hints.
CSS-ALIGN-3 tells us that `normal` behavior inside flex containers is
simply to behave as `stretch` so this patch makes them behave the same
inside FFC.
Furthermore, we change the `align-items` initial value to `normal`,
matching other engines.
I'm about to make StackingContext traverse the paintable tree instead of
actually traversing the layout tree, and it turns out we were not
creating paintables for these SVG elements.
Also switch them to Layout::Box instead of the default InlineNode to
make the trees look a bit less weird. Ultimately, we should do something
specialized for these subtrees, but for now this'll do.
This patch just adds the new root paintable and updates the tests
expectations. The next patch will move painting logic from the layout
viewport to the paint viewport.
When a box is sized under max-content constraint, any percentage value
set for max-width should be considered as if it were infinite. In other
words, it should have no effect on restricting the box's width.
This doesn't seem to actually have fixed any bugs, as having
FillOpacity instead of StrokeOpacity in the call to parse_css_value
doesn't seem to have actually been causing bugs. But, I still think it's
worthwhile correcting.
The reason that it wasn't causing bugs is that having FillOpacity
instead of StrokeOpacity in the call to parse_css_value means that when
parsing the value is compared to the acceptable values for that property
(for example the value can only be a percentage, or a number, etc.). In
this case both FillOpacity and StrokeOpacity seem to accept the same
values.
The SVG G container should have the same size as its children. This
fixes a bug when there was an opacity value on the G element, as in
StackingContext it would try and get a bitmap of the element which would
be empty due to it having no size.
Instead of applying relative offsets (like position:relative insets)
during painting and hit testing, we now do a pass at the end of layout
and assign the final resolved offsets to paintables.
This makes painting and hit testing easier since they don't have to
think about relative offsets, and it also fixes a bug where offsets were
not applied to text fragments inside inline-flow elements that were
themselves position:relative.
Changing `calculate_min_content_heigh()` and
`calculate_min_content_heigh()` to accept width as `CSSPixels`, instead
of `AvailableSize` that might be indefinite, makes it more explicit
that width is supposed to be known by the time height is measured.
This change has a bit of collateral damage which is rows height
calculation regression in `table/inline-table-width` that worked before
by accident.
We now apply MathML's default user agent style sheet along with other
default styles. This sheet is not mixed in with the other styles in
CSS/Default.css because it is a namespaced stylesheet and so has to
be its own sheet.
Using avilable space directly while resolving table container width
allows to avoid assigning it to table wrapper box content width which
sometimes involves infinite (saturated) values.
Also this allows to get rid of set_max_content_width() which is a hack
that allows to bypass set_content_width() to assign infinite
(saturated) width to a box.
Closes https://github.com/SerenityOS/serenity/issues/19521
Replicate the more conservative way it's done for other nodes, for
which we verify whether they have a paintable before doing
painting-related operations with it.
Fixes crash on https://www.haiku-os.org/.
Returning greatest_child_width() from automatic_content_width() in BFC
if root box children are inline and there are min/max-width that caused
width to be changed after IFC layout while content_width should be
always set to correct value by layout_inline_children() regardless of
layout mode.
- Out-of-flow items should not affect grid layout
- "The static position of an absolutely-positioned child of a grid
container is determined as if it were the sole grid item in a grid
area whose edges coincide with the content edges of the grid
container."
We were already parsing non-function-syntax :host, so let's also do
the :host(...) variant. Note that we don't have matching for these yet.
This fixes many issues on sites generated by Wix, as they often have
selector lists that include some :host() selector, and we'd reject the
entire rule after failing to parse it.
This stuff is pretty hairy since the specifications don't give any
guidance on which widths to use when calculating the intrinsic height of
flex items in a column layout.
However, our old behavior of "treat anything indefinite as fit-content"
was definitely not good enough, so this patch improves the situation by
considering values like `min-content`, `max-content` and `fit-content`
separately from `auto`, and making the whole flex layout pipeline aware
of them (in the cross axis context).
Use the max-width of percentage cells instead of min-width as the
reference to be used to compute the total table width. The specification
only suggests that the UA should try to satisfy percentage constraints
and this behavior is more consistent with other browsers.
Fixes infinite spinning in the cases when CSSPixels does not have
enough precision to represent increase per track which happens when
very small extra_space got divided by affected tracks number.
Change associativity in computing of replaced element size to improve
precision of division.
Fixes vertically squashed image from Mozilla splash page MDN example.
This patch implements "Overflow Viewport Propagation" from CSS-OVERFLOW.
It fixes an issue where many websites were not scrollable because they
had `overflow: scroll` on the body element and we didn't propagate it.
Pseudo-elements like ::before and ::after were discarded when their
content property was an empty string (ignoring whitespace), because they
are anonymous containers with no lines.
Our previous way around it was to add an empty line box (see b062a0fb7c)
however it didn't actually work for cases described in the previous
commit.
This makes avatars and cover arts square on last.fm and "fixes" the test
css-pseudo-element-should-not-be-affected-by-presentational-hints.html.
Unfortunately, this also regresses on block-and-inline/clearfix.html,
but that hopefully will be handled in subsequent commit.
Properties like min-width, max-width, etc, should be ignored while we're
trying to determine the intrinsic size of a flex container.
This fixes an infinite recursion when using an intrinsic size keyword as
the max-width of a flex column container.
Note that this behavior is marked as AD-HOC in code comments because
specs don't tell us how to achieve intrinsic sizing.
We can now load product pages on the Twinings site, such as
https://twinings.co.uk/products/earl-grey-100-tea-bags :^)
Fixes the issue that before "automatic minimum size" were used to size
flexible tracks even though specification says is should be "minimum
contribution"
Previously, we always rounded border-widths up when converting them to
device pixels. However, the spec asks us to follow a specific algorithm
to "snap" these values, so that the computed value is snapped.
The difference from before, is that widths of between 0 and 1 device
pixels are rounded up to 1, and and values larger than 1 are rounded
down.
If a math function resolves to `<length>` or `<percentage>`, then it
will by definition also resolve to `<length-percentage>`. (Same for any
other basic types.) Since we were checking `<length-percentage>` first
and then bailing if no given properties could accept that, math
functions would always fail to match a property that just accepts a non
`-percentage` type.
This is a universal value like `initial` and `inherit` and works by
reverting the current value to whatever we had at the start of the
current cascade origin.
The implementation is somewhat inefficient as we make a copy of all
current values at the start of each origin. I'm sure we can come up with
a way to make this faster eventually.
Allow the left margin of a box which creates a block formatting context
to overlap with left floating boxes which are siblings in the document
tree.
Fixes#20233 and the comment layout on https://lobste.rs.
This change makes tree builder omit elements with "display: contents"
from the layout tree during construction. Their child elements are
instead directly appended to the parent element in layout tree.
For malformed tables which only have cells with span greater than 1, the
content sizes for row and column aren't initialized to non-zero values.
Avoid undefined behavior in such cases, which sometimes show up on
Wikipedia.
Auto margins used together with justify-content would previously
result in children being positioned outside their parent. This was
solved by letting auto margins take precedence when they are used,
which was already implemented to some extent before, but not
fully.
Containers with both flex reverse and justify content would
sometimes place children outside the container. This happened
because it assumed any reversed container would have items
aligned to the right, which isn't true when using eg. `flex-end`.
Both `justify-content: start` and `justify-content: end` are now
also independent of the reverseness.
After switching to fixed-point arithmetic in CSSPixels, it no longer
supports representing infinite values, which was previously the case
for remaining_free_space in FFC. Using Optional that is not empty only
when value is finite to store remaining_free_space ensures that
infinity is avoided in layout calculations.
Before this change, we always derived a box's baseline from its last
child, even if the last child didn't have any line boxes inside.
This caused baselines to slip further down vertically than expected.
There are more baseline alignment issues to fix, but this one was
responsible for a fair chunk of trouble. :^)
Using fixed-point saturated arithmetics for CSSPixels allows to avoid
accumulating floating-point errors.
This implementation is not complete yet: currently saturated
arithmetics implemented only for addition. But it is enough to not
regress any of layout tests we have :)
See https://github.com/SerenityOS/serenity/issues/18566
Follow the computing column measures section of the specification, which
gives an algorithm for setting intrinsic percentage widths when spanning
columns are involved.
Change how we store type of columns. It was used where the specification
only distinguishes between percent and everything else, so it makes more
sense to store and use it as a boolean.
The specification says we should distribute excess width proportionally
to the width of the cell, not to the preferred increment. Doing the
latter leads to distributing all excess width to just the cells which
demand some increment, even if it's very modest. Moreover, there's code
which partially implements the correct criteria just below the one we
remove here.
Once we've resolved the used flex item width & height, we should allow
percentage flex item sizes to resolve against them instead of forcing
flex items to always treat percentages as auto while doing intrinsic
sizing layout.
Regressed in 8dd489da61.
We do this by piggybacking on FormattingContext helpers instead of
reinventing the wheel in FlexFormattingContext.
This fixes an issue where `min-width: fit-content` (and other
layout-dependent values) were treated as 0 on flex items.
This makes the cookie banners look okay on https://microsoft.com/ :^)
If an inline-block has a percentage height that relies on the auto
height of the containing block, it should always resolve to the
automatic height of the box, regardless of the percentage value. This
change may seem confusing, but it aligns with the behavior of other
engines.
Unlike all other primitives elliptical arcs are non-trivial to
manipulate, it's tricky to correctly apply a Gfx::AffineTransform to
them. Prior to this change, Path::copy_transformed() was still
incorrectly applying transforms such as flips and skews to arcs.
This patch very closely approximates arcs with cubic beziers (I can not
visually spot any differences), which can then be easily and correctly
transformed in all cases.
Most of the maths here was taken from:
https://mortoray.com/rendering-an-svg-elliptical-arc-as-bezier-curves/
(which came from https://www.joecridge.me/content/pdf/bezier-arcs.pdf,
now a dead link).
There are two parts to this fix:
- First, StyleProperties::transformations() would previously omit calc()
values entirely when returning the list of transformations. This was
very confusing to StackingContext which then tried to index into the
list based on faulty assumptions. Fix this by emitting calc values.
- Second, StackingContext::get_transformation_matrix() now always calls
resolve() on length-percentages. This takes care of actually resolving
calc() values. If no reference value for percentages is provided, we
default to 0px.
This stops LibWeb from asserting on websites with calc() in transform
values, such as https://qt.io/ :^)
This change implements following paragraph from placement algorithm in
the spec:
"If the largest column span among all the items without a definite
column position is larger than the width of the implicit grid, add
columns to the end of the implicit grid to accommodate that column
span."
There were places in the grid implementation code with copies of this
text, but those were completely unrelated to the code where they were
being pasted so I removed them.
Max width shouldn't be tied to min width, commit d33b99d went too far
and made them the same when the table-root had a specified percentage
width.
Fixes#19940.
Make sure the insets and margins calculated according to the spec are
not later ignored and ad-hoc recomputed in
layout_absolutely_positioned_element.
Use the static position calculation in a couple of places where the
spec (and comment) was indicating it should be used.
Fixes#19362
The tests still pass, but opening the files in Ladybird and Safari or
Firefox shows clearly where the layouting in Ladybird is incorrect
for some absolute positioned elements. The previous 1px border was
subtly hiding some issues.
When the containing block has an indefinite width, any descendants with
a percentage size should resolve that against 0, not infinity.
Fixes an assertion failure when loading https://www.gnu.org/
When sizing under a max-content constraint, we allow flex lines to have
an infinite amount of "remaining space", but we shouldn't let infinity
leak into the geometry of items. So treat it as zero in arithmetic.
This fixes an issue where inline SVGs with natural aspect ratio (from
viewBox) but no natural width or height could get an infinite size as
flex items.
All of the following properties in the font shorthand can be `normal`:
- font-style
- font-variant
- font-weight
- font-stretch
This means that we must allow up to four consecutive `normal` at the
start of a font shorthand value.
Anonymous wrapper boxes inherit style from their layout tree parent,
and since style data is per-layout-node, we have to manually sync them
from parent to anonymous children when something changes.
This is not very elegant or efficient, so I've left a FIXME about
solving it in a nicer way.
This fixes horizontal dog alignment on https://waffles.dog/ :^)
As it turns out, Layout::TreeBuilder never managed to wrap text within
table boxes in anonymous wrapper boxes, since it relied on checking
text_for_rendering(), and that was never initialized during that early
stage of tree building.
This patch fixes the issue by making text_for_rendering() compute the
(potentially collapsed) text lazily when called.
Note that the test included with this patch is still totally wrong,
but that is now a TFC problem rather than a TreeBuilder problem. :^)
Computing the table width algorithm bifurcates based on whether
table-root width is auto. We only adjust the used table width based on
cell percentage widths on the auto branch, thus the same check is needed
when we initialize cell widths.
Cell percentage widths are relative to table width, not containing
block width. If the table width is auto, there isn't a normative
specification, only a brief mention that the user agent should try to
meet it.
As a starting point, we increase the width of the table such that it's
sufficient to cover min-width of cells with a percentage width. This
matches the behavior of other browsers, at least for simple cases.
This ensures that min-content contributions from cells with no content
are computed using their calculated values, which are never considered
for min-content before then. The specification diverges from column
measures algorithm, which doesn't use specified width of cells anywhere.
The used width is already a content width, which doesn't include
borders. Border widths should be subtracted from the specified width
instead, since that initially specifies the total width including
borders, for consistent comparison. Also handle table box padding as an
additional fix.
On style update, we have to preserve the invariant established when we
built the layout tree - some properties are applied to the table wrapper
and the table box values are reset to their initial values.
This also ensures that the containing block of a table box is always a
table wrapper, which isn't the case if we set absolute position on the
box instead of the wrapper.
Fixes#19452.
This fixes the issue when size of abspos items is considered to be
resolvable without performing layout which is not correct in the
scenarious when top/right/bottom/left properties are not auto.
Return error when input svg is not valid and SVGSVGElement is not
present in the tree instead of doing svg_root nullptr dereference.
Fixes crash on https://apps.kde.org/en-gb/
Adding undistributable space right before setting the content width is
incorrect when it's a percentage. Follow the specification and add it to
GRIDMIN and GRIDMAX instead.
In particular, in BFC:
- Non-floating, non-replaced elements
- Floating, non-replaced elements
- Floating, replaced elements
The first two regressed in 1d76126abe
The third one seems to have been introduced by this regression, as it
was seemingly copied from compute_width_for_floating_box in
7f9ede07bc
The fix here has two parts:
1. Don't use the fallback viewBox at all if we're not in SVG-as-image.
2. Don't make a fallback viewBox with zero width and/or height.
This fixes a crash on Bandcamp pages. Thanks Tim Flynn for reporting!
The shortcut we put in place didn't resolve percentage widths and
ignored border spacing. We can still return early after we compute the
width per the specifications.
While CSS 2.2 does tell us to use the "auto height for BFC roots"
calculation when resolving auto heights for abspos elements, that
doesn't make sense for other formatting context roots, e.g flex.
In lieu of implementing the entire new absolute positioning model from
CSS-POSITION-3, this patch borrows one small nugget from it: using
fit-content height as the auto height for non-BFC-root abspos elements.
When embedding an SVG in an img element, if the external SVG's root
element has both width and height attributes, but no viewBox attribute,
we now create a fallback viewBox with "0 0 width height".
This appears to match the behavior of other browsers. Inspired by
discussion on Mozilla's bug tracker:
https://bugzilla.mozilla.org/show_bug.cgi?id=614649
If we don't paint, SVG-as-image documents don't get laid out, and so
have 0x0 size throughout.
This change is also generally nice, as it makes the painting code run
on all the layout tests, increasing coverage. :^)
Compute the contributions to a spanning cell width from each cell in the
span. This better handles uneven column widths, since each cell
contribution is proportional with its own width as opposed to the own
width of the first cell in the span.
This better matches the behavior of other browsers and further aligns
with the specification.
The part in FFC where we ask the parent formatting context to size the
flex container midway through layout is really weird, but let's at least
be consistently weird for BFC and IFC. Since IFC always works within its
parent BFC, it can simply forward these requests to the BFC.
This fixes an issue where inline-flex containers incorrectly had main
axis margins subtracted from their content size.
With multi-line text cells, we don't reliably know the height would stay
the same as the one set by the independent format context run. In such
situations, we can end up with a table box which is sized inconsistently
with the grid boxes of the table due to differences in line breaks.
In compute_table_box_width_inside_table_wrapper, we should only consider
available_width when it's valid. Values which come from {min,
max}-content constraints aren't meaningful and shouldn't be considered
for the cap.
Absolutely positioned elements should have their percentage sizes
resolved against the padding box of the containing block, not the
content box.
From CSS-POSITION-3 <https://www.w3.org/TR/css-position-3/#def-cb>
"..the containing block is formed by the padding edge of the ancestor.."
When resolving a percentage min-width or min-height size against a
containing block currently under a min-content constraint, we should act
as if the containing block has zero size in that axis.
"display: max-content" is not a thing. The test was actually not working
correctly, it just looked like it did. Now it has correct metrics for
the body element.
This is technically "undefined behavior" per CSS 2.2, but it seems
sensible to mirror the behavior of max-height in the same situation.
It also appears to match how other engines behave.
Fixes#19242
The margin from the containing blocks shouldn't be included in the
amount by which we increment x after a float was places. That coordinate
should be relative to the containing block.
Fixes the comments layout on https://lobste.rs.
The spec says the result of this algorithm is undefined in such cases,
and it appears that other engines yield a zero size.
More importantly, this prevents us from leaking a non-finite value into
the layout tree.
Although DistinctNumeric, which is supposed to abstract the underlying
type, was used to represent CSSPixels, we have a whole bunch of places
in the layout code that assume CSSPixels::value() returns a
floating-point type. This assumption makes it difficult to replace the
underlying type in CSSPixels with a non-floating type.
To make it easier to transition CSSPixels to fixed-point math, one step
we can take is to prevent access to the underlying type using value()
and instead use explicit conversions with the to_float(), to_double(),
and to_int() methods.
Instead of hard-coding a check for "calc", we now call out to
parse_dynamic_value() which allows use of other functions like min(),
max(), clamp(), etc.
Add logic to compute {min, max}-height and use min-height when
calculating table height, per specifications.
Fixes some issues with phylogenetic tree visualizations on Wikipedia.