This avoids looking at every single installed typeface to see if there's
a family name match.
Fixes a large performance regression introduced when making
StyleComputer consider system fonts in CSS font fallback.
Regressed with 69a81243f5.
User styles are applied after the UserAgent's built-in styles, and
before the Author styles that are part of the web page.
Because they're neither part of the page, but can still be modified
while the page is open, caching is a little tricky. The approach here
is to piggy-back on the StyleComputer's rule caches, which already get
rebuilt whenever the styles change. This is not the smartest approach,
since it means re-parsing the style sheet more often than is necessary,
but it's simple and works. :^)
This is all of them currently, except Length, because we lack the needed
information to be able to expand font-relative lengths.
The whole way `expand_unresolved_values()` works is awkward, but at some
point we'll be able to run the simplification algorithm on the
calculation, which will either return a single value, or a new
calculation that's simplified as much as possible.
Mostly I just wanted that FIXME log message to go away, because it's
overwhelming on certain sites.
This effectively makes it per-Document, but we hang it off of
StyleComputer since that's what it's used for.
The purpose of this is to prevent downloaded fonts from escaping the
context that loaded them. There's probably a more elegant solution where
we still share caching of system fonts, but let's start here.
We had `parse_calculated_value()` which parsed the contents of `calc()`,
and `parse_dynamic_value()` which parsed any math function, both of
which produce a CalculatedStyleValue, but return a plain StyleValue.
This was confusing, so let's combine them together, and return a
CalculatedStyleValue.
This also makes the other math functions work in
`StyleComputer::expand_unresolved_values()`.
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.
Instead, perform the filtering for each rule as we go. This avoids
creating a separate list of rules, which was ~5% of runtime when
mousing around on the Discord web interface.
CSSStyleSheet now caches the CSSNamespaceRule for the default namespace,
which is the only one we currently care about. This saves us from
iterating over its list of rules every time we want to know what that
default namespace is.
The spec dictates that `@namespace` rules are only valid near the start
of a stylesheet, so we also take advantage of that to quit searching
for namespaces as soon as we see a non-import rule.
Also renamed `namespace_filter()` to `default_namespace()` since that's
what it actually returns.
This makes github.com/serenityos/serenity snappy again. :^)
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.
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.
Now that we have a way to resolve calc() lengths without a layout node,
we can finally support calc() values in font-size.
This wasn't possible before because font-related properties have to be
resolved eagerly in StyleComputer due to font-relative CSS length units
depending on the computed font being known.
Unlike DOM mutations, CSS animations don't affect the style of the
entire subtree of the element being animated. This means we only have to
recompute style for the animating element, which is significantly
faster than doing the whole subtree.
This takes idle CPU usage on https://shopify.com/ from 100% to 30% on my
(not massively powerful) laptop. :^)
This commit makes the StyleComputer avoid restarting finished animations
(e.g. animations with finite iteration counts that have run to
completion).
As a bonus, it also disables the animation timer when all animations
have finished running.
This partially implements CSS-Animations-1 (though there are references
to CSS-Animations-2).
Current limitations:
- Multi-selector keyframes are not supported.
- Most animation properties are ignored.
- Timing functions are not applied.
- Non-absolute values are not interpolated unless the target is also of
the same non-absolute type (e.g. 10% -> 25%, but not 10% -> 20px).
- The JavaScript interface is left as an exercise for the next poor soul
looking at this code.
With those said, this commit implements:
- Interpolation for most common types
- Proper keyframe resolution (including the synthetic from-keyframe
containing the initial state)
- Properly driven animations, and proper style invalidation
Co-Authored-By: Andreas Kling <kling@serenityos.org>
This allows us to figure out where a specific CSS property comes from,
which is going to be used in a future commit to uniquely identify
running animations.
Specifically, stop letting NumericStyleValues holding `0` from
pretending to hold a Length. The parser is now smart enough that we
don't have to do this. :^)