With per-paintable display list command caching now in place, the
separate paint-only properties resolution phase is no longer needed.
Resolution now happens inline during painting and its cost is amortized
since it only runs on cache miss.
Move all property resolution to point of consumption:
- is_visible() and visible_for_hit_testing() compute on the fly
- Filter resolution moved to assign_accumulated_visual_contexts()
- Border radii, outlines computed on access
- Box shadows, backdrop filter resolved inline during painting
- Background resolution moved into paint_background()
- Mask resolution moved to StackingContext::paint()
- Text fragment and SVG stroke properties resolved during painting
Rename Document::set_needs_display() to set_needs_repaint() and make it
private. External callers must now go through Node/Paintable which
route the request to the document internally.
Fix one existing misuse in AnimationEffect that was calling
document-level set_needs_display() instead of routing through the
target element's paintable.
This is preparation for per-paintable display list command caching:
repaint requests must go through specific paintables so their cached
command lists can be invalidated.
Add unsafe_layout_node(), unsafe_paintable(), and unsafe_paintable_box()
accessors that skip layout-staleness verification. These are for use in
contexts where accessing layout/paintable data is legitimate despite
layout not being up to date: tree construction, style recalculation,
painting, animation interpolation, DOM mutation, and invalidation
propagation.
Also add wrapper APIs on Node to centralize common patterns:
- set_needs_display() wraps if (unsafe_paintable()) ...set_needs_display
- set_needs_paint_only_properties_update() wraps similar
- set_needs_layout_update() wraps if (unsafe_layout_node()) ...
And add Document::layout_is_up_to_date() which checks whether layout
tree update flags are all clear.
Ensure AccumulatedVisualContext stays synchronized when CSS transform
properties change.
AccumulatedVisualContext copies transform and perspective matrices from
the paintable tree at assignment time. When CSS properties that affect
these matrices change (transform, rotate, scale, translate, perspective,
transform-origin, perspective-origin), we must rebuild the
AccumulatedVisualContext tree to reflect the new values.
This adds a rebuild_accumulated_visual_contexts flag to style
invalidation that triggers a full rebuild during the next paint.
Note: The current invalidation strategy is inefficient - it rebuilds
the entire tree even for single-element transform changes. This could
be improved by patching the AccumulatedVisualContext node in-place with
updated matrices, but only when the transform doesn't transition
from/to none (which would change the tree structure). This optimization
is left for future work.
In level 2 of the web animations spec, times are no longer always
measures in milliseconds, they can also be percents when dealing with
progress-based (i.e. scroll-based) timelines.
We don't actually support percent times yet but this change will make it
easier to implement when we do.
Web Animations Level 2 disallows setting some `AnimationEffect` timing
values (start delay, end delay, iteration duration) directly and instead
allows authors to set the specified values which are then normalized
into the actual used values taking into account the type of the
associated timeline (i.e. progress- vs time-based)
Previously we would either parse these as `StyleValueList<T>` or `T`
depending on whether or not there was more than one value, this meant we
always had to handle both cases anywhere we used these values.
This excludes `step-end` and `step-start` which are expected to be
converted to the equivalent function at parse time.
We are expected to serialize these as the explicit keywords - previously
we would parse as `EasingStyleValue` and serialize equivalent functions
as the keywords. This caused issues as we would incorrectly serialize
even explicit functions as the keyword.
This also allows us to move the magic easing functions to
`EasingFunction` rather than `EasingStyleValue` which is a bit tidier
Before this change, we always updated paint-only properties for every
single paintable after layout or style changes.
This could get very expensive in large documents, so this patch makes
it something we can do partially based on "repaint" invalidations.
This cuts down time spent in paint-only property update when scrolling
https://imdb.com/ from 19% to 5%.
This reverts 0e3487b9ab.
Back when I made that change, I thought we could make our StyleValue
classes match the typed-om definitions directly. However, they have
different requirements. Typed-om types need to be mutable and GCed,
whereas StyleValues are immutable and ideally wouldn't require a JS VM.
While I was already making such a cataclysmic change, I've moved it into
the StyleValues directory, because it *not* being there has bothered me
for a long time. 😅
This fixes an issue where only the last KeyframeEffect applied to an
element would actually have an effect on the computed properties.
It was particularly noticeable when animating a shorthand property like
border-width, since only one of the border edges would have its width
actually animate.
By deferring the invalidation until all animations have been processed,
we also reduce the amount of work that gets done on pages with many
animations/transitions per element. Discord is very fond of this for
example.
Before this change, we were going through the chain of base classes for
each IDL interface object and having them set the prototype to their
prototype.
Instead of doing that, reorder things so that we set the right prototype
immediately in Foo::initialize(), and then don't bother in all the base
class overrides.
This knocks off a ~1% profile item on Speedometer 3.
This is not really a context, but more of a set of parameters for
creating a Parser. So, treat it as such: Rename it to ParsingParams,
and store its values and methods directly in the Parser instead of
keeping the ParsingContext around.
This has a nice side-effect of not including DOM/Document.h everywhere
that needs a Parser.
The function AnimationEffect::phase() contained duplicated condition
checks for the animation phase determination. This refactor eliminates
the redundant checks by simplifying the logic.
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:
* JS::NonnullGCPtr -> GC::Ref
* JS::GCPtr -> GC::Ptr
* JS::HeapFunction -> GC::Function
* JS::CellImpl -> GC::Cell
* JS::Handle -> GC::Root