The LZW data for both GIF and TIFF images is sometimes intentionally
missing an end-of-information (EOI) code, which technically is a
decoding error, but in practive is handled gracefully by Firefox, Safari
and Chrome for GIFs and Safari for TIFFs. Let's mirror their behavior.
The included WPT test exposes the fact that trailing garbage bytes can
also result in decoding errors. We handle this in the LZW logic rather
than in the image decoding since our LZW implementation is currently
only used by GIF and TIFF decoding. The error is logged behind the
LZW_DEBUG flag.
Cover image-set() candidate selection by resolution for background
images. The tests cover both source-order-independent selection and
calculated resolution descriptors that require layout context.
Cover image-set() painting through background-image with URL-backed
SVG candidates. The test verifies that an unsupported type() candidate
is skipped and the supported image/svg+xml candidate is loaded and
painted.
When resolving cross-axis auto margins on a flex item, the outer cross
size calculation omitted all cross-axis margins. We now include
non-auto margins as part of the outer cross size treating auto margins
as zero.
The counter style used for an element (in either the `content` or
`list-style-type`) may change despite the computed values of properties
on that element remaining the same (e.g. if a new rule is inserted with
higher cascade precedence).
This was a pretty straightforward change of storing registered counter
styles on the relevant `StyleScope`s and resolving by following the
process to dereference a global tree-scoped name, the only things of
note are:
- We only define predefined counter styles (e.g. decimal) on the
document's scope (since otherwise overrides in outer scopes would
themselves be overriden).
- When registering counter styles we don't have the full list of
extendable styles so we defer fallback to "decimal" for undefined
styles until `CounterStyle::from_counter_style_definition`.
Import position-absolute-006 through position-absolute-011 from
css/css-flexbox/abspos.
These ref tests pass without local skips or special handling,
which makes them a good fit for this branch while leaving
position-absolute-005 out of the imported set.
Import flex percentage-heights 004-010 and 014 (ref tests), grid
percentage-rows-indefinite-height 001-002 (testharness), and the
abspos-auto-sizing-fit-content-percentage 001-008 series (ref tests).
All flex and fit-content tests pass. The grid indefinite-height tests
have pre-existing failures (16/120 and 0/4) unrelated to this change.
Import flex percentage-heights-004 through -010 and -014 (ref tests),
and grid-percentage-rows-indefinite-height-001 and -002 (testharness).
The flex tests all pass. The grid indefinite-height tests have many
failures (16/120 pass and 0/4 pass respectively), reflecting known
gaps in our grid percentage row handling.
Other browsers also respect this and there's nothing in the spec to
suggest this shouldn't happen. I removed the border since it was
inconsistently drawn only on missing images with alt text.
Other browsers do not have this at all.
Parent document paints could still record and paint a nested iframe's
contents even while the child document was render-blocked. That let
unstyled iframe content leak into the parent display list before the
child's blocking stylesheet had loaded, which matched the FOUC seen in
Speedometer's TodoMVC suites.
Skip painting hosted documents from NavigableContainerViewportPaintable
while they are render-blocked. Add a reftest that keeps an iframe child
render-blocked with a delayed stylesheet and forces a parent repaint;
without the fix the child's inline FAIL text becomes visible.
The new reftest passes with this change, and the existing render-
blocking requestAnimationFrame tests still pass.
Import ref and text tests from css/CSS2/floats,
css/CSS2/floats-clear, css/CSS2/margin-padding-clear, and
css/CSS2/visuren.
These cover float placement, clear behavior, clearance calculations,
and margin collapsing with floats.
The previous implementation checked text-overflow and overflow-x
on the text node's direct parent during inline item iteration.
Since these are non-inherited properties, ellipsis only worked
for text directly inside the block container, not when wrapped
in inline elements like <span> or <a>.
Move ellipsis truncation to a post-processing step after line
boxes are constructed, checking the containing block instead.
When an SVG is loaded as image data (e.g. via <img>), the
XMLDocumentBuilder returns early for decoded SVGs without calling
completely_finish_loading(). This meant that <use> elements which
forward-reference elements parsed after them never got their shadow
trees populated, since:
1. During parsing, the referenced element doesn't exist yet, so
clone_element_tree_as_our_shadow_tree() receives null.
2. The document_completely_loaded callback never fires.
3. update_use_elements_that_reference_this() returns early because
is_completely_loaded() is false.
Fix this by calling completely_finish_loading() on the document after
parsing in SVGDecodedImageData::create().
When an absolutely positioned element's display was inline-level
before blockification, and its preceding sibling is an anonymous
wrapper with inline children, the element's static position should
be at the same vertical position as that wrapper. This matches where
the element would have been placed if it were still inline.
Previously, the static position was always set to the current block
offset (after the preceding block), which placed the element below
the inline content instead of beside it. This caused absolutely
positioned ::after pseudo-elements (like dropdown chevrons) to appear
on the line below the text instead of at the same vertical position.
The :host::part() pattern allows a shadow DOM's own stylesheet to
style its internal elements that have been exposed via the part
attribute. Previously, ::part() rules were only collected from
ancestor shadow roots (for external part styling), but never from the
element's own containing shadow root.
Fix this by also collecting ::part() rules from the element's own
shadow root in collect_matching_rules(). Additionally, fix the
selector engine's ::part() compound matching to preserve the
shadow_host when the rule originates from the part element's own
shadow root, allowing :host to match correctly in the same compound
selector.
This fixes 2 previously failing WPT tests:
- css/css-shadow-parts/host-part-002.html
- css/css-shadow-parts/host-part-nesting.html
When computing the minimum contribution of a grid item with a definite
minimum size (e.g. min-height: 3rem), we must convert the CSS value to
content-box size before adding margin-box sizes. With box-sizing:
border-box, the CSS value already includes padding and border, so
passing it directly to add_margin_box_sizes() double-counted them.
Use calculate_inner_width/calculate_inner_height to properly convert
the minimum size to content-box dimensions, consistent with how
preferred and maximum sizes are already handled in the grid track
sizing algorithm.
When an element inside a shadow DOM is itself a shadow host, and a
rule from the parent shadow DOM uses a selector like
`:host([attr]) .child`, the combinator traversal needs to reach the
outer shadow host to match `:host([attr])`.
Previously, when the styled element was a shadow host and the rule
came from outside its own shadow root, we set shadow_host_to_use to
nullptr. This caused traverse_up() to use parent() which cannot
cross the shadow boundary, preventing the selector from reaching the
outer :host.
Fix this by using the rule's shadow root's host as the traversal
boundary instead of nullptr. This allows the descendant combinator
to traverse from the element up through the enclosing shadow DOM to
reach the outer shadow host for :host() matching.
The CSS Scoping spec says ::slotted() represents elements assigned
"after flattening" to a slot. When a slot element is itself slotted
into another slot (nested slots), the flattened tree resolves the
chain so that the inner content appears in the outermost slot.
Previously, we only collected ::slotted() rules from the directly
assigned slot's shadow root. This meant that styles defined in an
outer shadow DOM's ::slotted() rules would not apply to elements
that were transitively slotted through intermediate slots.
Fix this by walking up the slot assignment chain when collecting
and matching ::slotted() rules, so that rules from every shadow
root in the chain are considered.
When trimming trailing whitespace from line boxes, we were only
subtracting the glyph width of each trimmed character. However, during
text shaping, letter-spacing is added to each glyph's advance width.
We must subtract the full advance (glyph width + letter-spacing) to
get an accurate line width after trimming.
This also fixes a pre-existing precision bug where the glyph width
(a float) was truncated to int, leaving fractional phantom width in
the line box.
Together, these issues caused text with letter-spacing and trailing
HTML whitespace to have an underestimated intrinsic width, leading to
unexpected text wrapping in flex layouts.
When matching selectors like `:host ::slotted(div)`, the selector
engine needs to traverse up from the slot element to reach the shadow
host for `:host` matching. Previously, we passed shadow_host_to_use
which was derived from the *slotted element's* DOM position. For
elements in the light DOM (not inside any shadow root), this was null,
causing traverse_up() to use parent() instead of
parent_or_shadow_host_element(). This meant the traversal could never
cross the shadow boundary from inside the shadow tree to reach the
host element.
Fix this by deriving the shadow host from the slot's containing shadow
root, which is the correct scope for combinator traversal within
::slotted() rule matching.
Both Chromium and Gecko delay the document's load event for CSS image
resource requests (background-image, mask-image, etc). We now start
fetching CSS image resources as soon as their stylesheet is associated
with a document, rather than deferring until layout. This is done by
collecting ImageStyleValues during stylesheet parsing and initiating
their fetches when the stylesheet is added to the document.
Fixes#3448
Implement support for the 'round' radii in 'clip-path: inset()'
by resolving and normalizing corner radii and generating a path
with elliptical arcs.
Add a screenshot test.
Per the CSS Backgrounds spec, background-clip:text clips the
background to the geometry of text in the element and its in-flow
and floated descendants only.
Skip subtrees rooted at paintables that are neither in-flow
nor floated when computing the text clip path, so that
absolutely/fixed positioned descendants (including pseudo-elements)
do not contribute to the clip.
Fixes#7498
The parent's viewBox transform includes both scaling and a centering
offset. For nested <svg> elements, this transform was applied once to
position the nested SVG's box, then again to position children inside
it, double-counting the centering offset.
We now apply the parent's transform to the nested SVG box upfront to
ensure the transform is only applied once.
Elements that generate anonymous boxes such as `<button>` and
`<fieldset>` need to propagate paint invalidation to them in order to
properly invalidate the style of their inner contents.
Fixes#8347
When collapsible whitespace is skipped without committing a prior
chunk, the loop would fall through and continue with font information
derived from the last whitespace code point rather than the next
non-whitespace character. Restart the function via recursion so that
these values are reinitialized from the correct code point.
The conversion of sqrt2 into CSSPixels caused the value to change from
1.41... to 1.42... This led to incorrect results. I moved the division
inside the sqrt to prevent this conversion step.
When an image has no intrinsic dimensions but has an intrinsic aspect
ratio, the CSS default sizing algorithm should resolve its size as a
contain constraint against the default object size. Previously, we
returned the default size directly, which caused such images to stretch
to fill the entire background positioning area. The SVG's default
`preserveAspectRatio` would then center the content within that
oversized viewport, making the image appear horizontally mispositioned.
Contenteditable elements that would otherwise have zero height now get a
minimum height equal to their line-height.
This ensures they remain clickable and usable for text editing.
This fixes the WPT test:
contenteditable/synthetic-height.html