We were saving to source declarations for *every* property, even though
we only ever looked it up for animation-name.
This patch gets rid of the per-property source pointer and we now keep
a single pointer to the animation-name source only.
This shrinks StyleProperties from 6512 bytes to 4368 bytes per instance.
Pseudo-elements' style is only computed while building the layout tree.
This meant that previously, they would not have their style recomputed
in some cases. (Such as when :hover is applied to an ancestor.)
Now, when recomputing an element's style, we also return a full
invalidation if one or more pseudo-elements would exist either before or
after style recomputation.
This heuristic produces some false positives, but no false negatives.
Because pseudo-elements' style is computed during layout building, any
computation done here is then thrown away. So this approach minimises
the amount of wasted style computation. Plus it's simple, until we have
data on what approach would be faster.
This fixes the Acid2 nose becoming blue when the .nose div is hovered.
These have a few rules that we didn't follow in most cases:
- CSS-wide keywords are not allowed. (inherit, initial, etc)
- `default` is not allowed.
- The above and any other disallowed identifiers must be tested
case-insensitively.
This introduces a `parse_custom_ident_value()` method, which takes a
list of disallowed identifier names, and handles the above rules.
This removes some ambiguity about what the return value should be if
the index is out of range.
Previously, we would sometimes return a JS null, and other times a JS
undefined.
It will also let us fold together the checks for whether an index is a
supported property index, followed by getting the value just afterwards.
This is `counter(name, style?)` or `counters(name, link, style?)`. The
difference being, `counter()` matches only the nearest level (eg, "1"),
and `counters()` combines all the levels in the tree (eg, "3.4.1").
These control the state of CSS counters.
Parsing code for `reversed(counter-name)` is implemented, but disabled
for now until we are able to resolve values for those.
The new method is Parser::parse_all_as_single_none_value(), which has a
few advantages:
1. There's no need for user code to manually create a StyleValue.
2. It consumes tokens so that doesn't have to be done manually.
3. Whitespace before or after the `none` is consumed correctly.
It does mean we create and then discard a `none` StyleValue in a couple
of places, namely parsing for `grid-*` properties. We may or may not
want to migrate those to returning the IdentifierStyleValue instead.
This represents each element's set of CSS counters.
https://drafts.csswg.org/css-lists-3/#css-counters-set
Counters are resolved while building the tree. Most elements will not
have any counters to keep track of, so as an optimization, we don't
create a CountersSet object until the element actually needs one.
In order to properly support counters on pseudo-elements, the
CountersSet needs to go somewhere else. However, my experiments with
placing it on the Layout::Node kept hitting a wall. For now, this is
fairly simple at least.
Before this change, "background-clip: text" was implemented by saving a
Vector<Gfx::Path> of all glyphs needed to paint a mask for the
background. The issue with this approach was that once glyphs were
extracted into vector paths, the glyph rasterization cache could no
longer be utilized.
With this change, all text required for mask painting is saved in a
nested display list and rasterized as a regular text.
With this change, instead of recording a display list item for each
instance of a repeated background, a new DrawRepeatedImmutableBitmap
type is used. This allows the painter to use optimized repeated image
painting and, when the GPU backend is used, avoid re-uploading the image
texture for each repetition.
Some screenshot tests are affected, but there are no visible
regressions.
https://null.com/games/chainstaff works a lof faster with this change.
The :host family of pseudo class selectors select the shadow host
element when matching against a rule from within the element's shadow
tree.
This is a bit convoluted due to the fact that the document-level
StyleComputer keeps track of *all* style rules, and not just the
document-level ones.
In the future, we should refactor style storage so that shadow roots
have their own style scope, and we can simplify a lot of this.
This fixes an issue where :host(foo) would parse as if "foo" was the
on the right side of a descendant combinator.
Not testable yet, but will be in the next commit.
This change removes wrappers inherited from Gfx::Typeface for WOFF and
WOFF2 fonts. The only purpose they served is owning of ttf ByteBuffer
produced by decoding a WOFF/WOFF2 font. Now new FontData class is
responsible for holding ByteBuffer when a font is constructed from
non-externally owned memory.
When loading a canned version of reddit.com, we end up parsing many many
shadow tree style sheets of roughly ~170 KiB text each.
None of them have '\r' or '\f', yet we spend 2-3 ms for each sheet just
looping over and reconstructing the text to see if we need to normalize
any newlines.
This patch makes the common case faster in two ways:
- We use TextCodec::Decoder::to_utf8() instead of process()
This way, we do a one-shot fast validation and conversion to UTF-8,
instead of using the generic code-point-at-a-time callback API.
- We scan for '\r' and '\f' before filtering, and if neither is present,
we simply use the unfiltered string.
With these changes, we now spend 0 ms in the filtering function for the
vast majority of style sheets I've seen so far.
This is the expected behavior per the HTML spec. Fixes an issue where
styling these elements wouldn't have the expected effect unless you also
set the display property.
We already have a FlyString of its value from parsing, and most users
also want a FlyString from it, so let's use that instead of converting
backwards and forwards.
The two users that did want a String are:
- Quotes, which make sense as FlyString instead, so I've converted that.
- Animation names, which should probably be FlyString too, but the code
currently also allows for other kinds of StyleValue, and I don't want
to dive into this right now to figure out if that's needed or not.
Previously the entire slider track was colored.
Now only the lower part of the slider track (left side of the thumb) is
colored.
Chrome and Firefox do the same.