getComputedStyle(element) now returns a ComputedCSSStyleDeclaration
object, which is a live view of the computed style of a given element.
This works by ComputedCSSStyleDeclaration being a wrapper around an
element pointer. When you ask it for a CSS property, it gets the latest
computed style values from the element and returns them as a
CSS::StyleProperty object.
This first cut adds support for computed 'color' and 'display'.
In case the element doesn't have a corresponding node in the layout
tree, we fall back to using specified style instead. This is achieved by
performing an on-the-fly style resolution for the individual element and
then grabbing the requested property from that resolved style.
This patch moves the CSS property+value storage down to a new subclass
of CSSStyleDeclaration called PropertyOwningCSSStyleDeclaration.
The JavaScript wrapper for CSSStyleDeclaration now calls virtual
functions on the C++ object.
This is preparation for supporting computed style CSSStyleDeclaration
objects which won't have internal property storage, but rather an
internal element pointer. :^)
The StyleProperties code for opacity existed before NumericStyleValue
was a thing, and was affected by over-enthusiastic unitless-length
parsing, so it assumed everything was a length. Now it matches the
Color4 spec instead, accepting either a number, or a percentage.
We also get to remove the hack! :^)
Previously, we applied the unitless length quirk to all numbers in
quirks mode. Now, we correctly only do so for the set of properties
listed in the quirks-mode spec:
https://quirks.spec.whatwg.org/#quirky-length-value
However, we do not yet prevent this quirk inside CSS expressions (like
`calc()`) as the spec directs.
After `parse_css_value(PropertyID, TokenStream)`, we only need to know
the current PropertyID when checking for property-specific quirks, which
will take place in only 2 places, which happen deep down. Making the
current PropertyID part of the context means that those places can check
it easily, without us having to pass it to every one of the parsing
functions, which otherwise do not care.
Two CSS quirks are specced to only apply to specific properties:
- The hashless hex color quirk
https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
- The unitless length quirk
https://quirks.spec.whatwg.org/#the-unitless-length-quirk
These are now represented in `Properties.json` like so:
```json
"property-name-here": {
"quirks": [
"hashless-hex-color",
"unitless-length"
]
}
```
Every property that either of those two quirks applies to is included in
`Properties.json` and now has their quirks listed. :^)
This fixes#9978.
When a TokenStream is empty, reading its `current_token()` still returns
a token (for EOF) so it makes sense to allow users to
`reconsume_current_input_token()` that token, so they do not have to
handle that themselves. Instead of VERIFY()ing, we can just no-op when
reconsuming token 0.
And also try_create<T> => try_make_ref_counted<T>.
A global "create" was a bit much. The new name matches make<T> better,
which we've used for making single-owner objects since forever.
Previously it was returning an "auto" length. This caused all the new
"initial" values to effectively turn into auto values long before layout
had a chance to resolve them.
This broke replaced elements with intrinsic size but no specified width
or height, and is the reason that Mr. ACID2 temporarily lost his eyes.
This isn't 100% spec complaint, as it should use glyph_height()
depending on what the value of the writing-mode is, but we haven't
implemented it yet, so I think it'll be good enough for now.
This can be tested in https://wpt.live/css/css-values/ch-unit-008.html
Other css-unit tests fail as:
- 001 shows an issue related to a renderer (looks to me like you can't
pass a width and height property to a span -- adding `display: block`
to it passes the test),
- 002-004 and 009-012 use mentioned writing-mode,
- 016-017 loads custom fonts, which we also don't support (yet).
When property() previously would have returned an InitialStyleValue, we
now look up what the initial value would be, and return that instead.
We also intercep 'inherit', but inheritance is not implemented yet so we
just return nothing.
This does cause a regression on Acid2: The eyes no longer appear, and I
am not sure why. :^(
With the new parser, we started interpreting the `opacity` property as a
string value, which made it turn into `auto` and so anything with
opacity ended up not visible (e.g the header on google.com)
This patch restores our old behavior for `opacity` by interpreting it
as a numeric value with optional decimals.
This is primarily to be able to remove the GenericLexer include out of
Format.h as well. A subsequent commit will add AK::Result to
GenericLexer, which will cause naming conflicts with other structures
named Result. This can be avoided (for now) by preventing nearly every
file in the system from implicitly including GenericLexer.
Other changes in this commit are to add the GenericLexer include to
files where it is missing.
If the font-family property is set to a StyleValueList, we now iterate
through it, looking up each font in turn until one is found.
StyleResolver no longer needs to handle FontFamily specifically, which
is a nice bonus.
Serenity's current dependence on bitmap fonts leads to some weirdness
here - for example, the `if (!found_font)` path can trigger even if a
generic font family like "sans-serif" is used, since our default
sans-serif font might not be available in the desired size or weight.
The `monospace` variable only exists for that reason.
This is not a complete solution, by a long way! Serenity's font support
is still quite basic, so more work needs to be done there before we can
start implementing the spec's font-matching algorithm. But this is still
an improvement. :^)
The code was assuming the font-weight would be a Length, apparently
since NumericStyleValue didn't exist at the time. Now, it's always a
numeric value, so treat it as such.
We also replace the hardcoded numbers with references to the FontWeight
enum.
Also, it was always setting the weight to 900, so that has been fixed.
The previous code assumed all font sizes were in px, but now we perform
the conversion. There is an existing bug with em sizes returning 0,
which seems to affect other places too - see
`NodeWithStyle::apply_style()`.
This also implements 'larger', 'smaller' and calc() font-sizes.
We already include the inheritance for each property in Properties.json,
so made sense to use that instead of a list in StyleResolver.
Added `inherited: true` to a couple of properties to match the previous
code's behavior. One of those had a FIXME which I've moved to the JSON
file, which is hacky, but it works.
This commit changes inline CSS loaded from style attributes of HTML
elements to be loaded as CSS::ElementInlineCSSStyleDeclaration instead
of CSS::CSSStyleDeclaration, fixing a crash when the style of that
element is changed from JavaScript.
Some properties, such as `margin`, take multiple values but are not
complicated enough to require special-case handling. These no longer
parsed after my previous StyleValue changes, so this fixes that.
In the future we may want to configure whether to allow this for each
property.
Apart from now gathering comma-separated font-family names into a
StyleValueList, this also corrects the logic for parsing a single
font-family. Previously, we did not handle unquoted font names at all,
and now they are handled including when they are several words separated
by whitespace.
Modified the logic for `font` to use `parse_font_family_value()`.
`FontStyleValue.font_families()` is now a StyleValueList instead of a
vector, so that it can be better handled in StyleResolver.
We also finally remove the CSS::ParsingContext in
set_property_expanding_shorthands(). :^)
This wraps an x and y background-repeat value. Potentially, we could use
this in place of the background-repeat-x and background-repeat-y
pseudo-properties, but for now StyleResolver splits it into those
properties, like it did before.
This parses the elliptical border-radius values, though currently we
only support circular ones. So, to_length() is overloaded to return the
horizontal-radius. This means the code in Layout/Node.cpp does not need
to change for now.
This is not just moving the code from StyleResolver to Parser. The logic
has changed to allow for the `flex-basis` to come before or after the
`flex-grow/shrink` values, as well as handle the special one-value
cases.
Also added test cases to flex.html to check the parsing. It does parse
correctly, but elements with `flex-basis: auto` do not calculate their
width correctly.
Modified text-decoration.html to better test that the values can be in
any order, and that it adopts the color from the `color` property if no
decoration color is specified. Right now, it always does because we do
not support a different decoration color. Later, we need to support the
`currentcolor` special CSS value for this purpose.
Yes, the name is silly, but it's a StyleValue for list-style, so...
yeah. :^)
Since `list-style-type` and `list-style-image` can both have `none` as a
value, and can appear in any order, we have to handle it separately, and
then assign either or both of those to `none` depending on how many
`none`s there are, and whether those sub-properties already have values.
Added some extra test cases to lists.html to cover list-style-image and
list-style-position parts of the list-style shorthand, and the `none`
values.
This one represents one secton of a `background` property, since it can
have multiple background values separated by commas. Eventually, we will
represent that as a List of BackgroundStyleValues.
Also modified some background-foo properties in StyleResolver so that
the is_background_x() functions could be removed.
I realized that our handling of var() in shorthand properties is wrong,
so have been removing the is_builtin_or_dynamic() calls from the parsing
code for shorthands. This broke our var() test page, so I have replaced
the use of 'background' with 'background-color' there.