Based very scientifically on what's listed here:
https://harfbuzz.github.io/what-does-harfbuzz-do.html
I've moved the code into LibGfx because including a HarfBuzz header
directly from LibWeb is a little unpleasant. But the Gfx::FontTech enum
follows the CSS definitions for font features for simplicity.
TrueType collections are supported. SVG and Embedded OpenType are not,
but they're not widely supported by other browsers so that's fine.
Most of the features are completely supported by HarfBuzz, so we can
just return true. Graphite support is optional (and it appears we use a
build of HarfBuzz without it) but there's a define we can check.
Incremental Font Transfer is a whole separate thing that we definitely
don't support yet.
For getComputedStyle(), we must return an absolute URL for image style
values. We currently return the raw parsed URL.
This fixes loading the marker icons on https://usermap.serenityos.org.
When serializing CSS declarations we now support combining multiple
properties into a single shorthand property in some cases.
This comes with a healthy dose of FIXMEs, including work to be done
around supporting:
- Nested shorthands (e.g. background, border, etc)
- Shorthands which aren't represented by the ShorthandStyleValue type
- Subproperties pending substitution
This gains us a bunch of new test passes, both for WPT and in-tree
This exposed a few bugs which caused the following tests to behave
incorrectly:
- `tab-size-text-wrap.html`: This previously relied on a bug where we
incorrectly treated `white-space: pre` as allowing text wrapping. The
fix here is to implement the text-wrap CSS shorthand property.
- `execCommand-preserveWhitespace.html`: We don't correctly serialize
shorthand properties. This is covered by an existing FIXME in
`CSSStyleProperties::serialized()`
- `white-space-shorthand.html`: The last 5 subtests here fail as we
don't correctly handle shorthand properties in
`CSSStyleProperties::remove_property()`. This is covered by an
existing FIXME in said function.
If a property is uses discrete interpolation and TransitionBehavior is
not set to `AllowDiscrete` that property should be non-transitionable.
This is now true for properties whose animation type is not discrete,
but the animation type falls back to discrete.
This function attempts to resolve `lighter` and `bolder`, which we don't
want to do when serializing - that should happen in style computation.
This has the unexpected bonus of 37 more WPT passes!
To be vendor-prefixed, an ident has to start with a '-', then have
another '-' later. If the ident simply starts with a '-' then that's
perfectly fine.
Fixes 62 in-tree WPT subtests. :^)
We don't want to reset the values of `font-variant-*` here, as that will
override whatever our parsed font-variant-css2 was, so stop doing that.
Also, font-stretch is mentioned in the spec, but it's a legacy name
alias for font-width, so we don't need to do anything for it.
Gets us 319 WPT passes!
"format(woff-variations)" and pals are supposed to expand like so:
"format(woff) tech(variations)".
However, since we don't support tech() yet, this patch just adds a small
hack where we still treat "woff-variations" as "woff" so that fonts
load and get used, even if we don't make use of the variations yet.
The spec has a general rule for this, which is roughly that "If it's not
a falsey value, it's true". However, a couple of media-features are
always false, apparently breaking this rule. To handle that, we have an
array of false keywords in the JSON, instead of a single keyword. For
those always-false media-features, we can enter all their values into
this array.
Gets us 2 more WPT subtest passes.
Despite what the spec suggests, modern displays are not progressive, and
WPT expects `@media (scan: progressive)` to fail. So, return `none`
here to accurately represent that.
I've left a FIXME in case we can detect the display type from the OS
somehow in the future.
Gets us 4 WPT subtest passes.
Previously, for `foo < 30px` ranges, we'd flip them and store them as
`30px > foo` instead. That worked fine, but means the serialization is
wrong. So instead, keep them in their original form.
I experimented with giving Range two optional sub-structs instead of 4
optional members, thinking it would be smaller - but it's actually
larger, because the two Optional<Comparison>s fit snugly together. So,
the slightly-goofy all-Optionals remains.
This gets us 2 WPT passes that I'm aware of.
Instead of rejecting invalid media-feature values at parse time, we are
expected to parse them, and then treat them as Unknown when evaluating
their media query. To implement this, we first try to parse a valid
value as before. If that fails, or we have any trailing tokens that
could be part of a value, we then scoop up all the possible
ComponentValues and treat that as an "unknown"-type MediaFeatureValue.
This gets us 66 WPT passes.
The current spec defines this simply as `<ident>`, but does apparently
serialize as lowercase.
Because of this change, we no longer need to care about the deprecated
media types, as they all behave the same as unknown ones.
We still keep an enum around for KnownMediaType, to avoid repeated
string comparisons when evaluating it.
Gets us 2 WPT passes.
When position changes, we may need to make larger structural updates
to the layout tree. A simple relayout is not sufficient.
This was a source of flakiness in the engine, and gives us at least
+28 new WPT subtest passes.
This fixes an issue where we'd serialize some floating point numbers
with excessive precision, resulting in unpleasant-looking numbers like
0.49999999999999999 and such.
At least 90 new subtests passing on WPT, possibly more. :^)
This gives us a more human-looking serialization of numbers by default,
and in case a fixed number of decimal digits is actually wanted, we
still have the 'f' specifier.
There's discussion in the linked spec issue, but the short version is,
this algorithm will see "foo,bar," as a list of two groups, with "foo"
in the first group and "bar" in the second. However, users of this want
to get a list of three groups, with the last one being empty. So, do
that!
Some dimensions would always serialize in a canonical unit, others never
did, and others we manually would do so in their StyleValue. This
commit moves all of that into the dimension types, which means for
example that Length can apply its special rounding.
Our local serialization test now produces the same output as other
browsers. :^)
Selector::serialize() is used for both normal and relative selectors.
For the latter, we need to serialize their initial combinator, and for
the former, we always set the initial combinator as None anyway, so
this would be a no-op there.
Gets us 3 WPT passes.
The spec requires us to accept any ident here, not just ltr/rtl, and
also serialize it back out. That means we need to keep the original
string around.
In order to not call keyword_from_string() every time we want to match
a :dir() selector, we still attempt to parse the keyword and keep it
around.
A small behaviour change is that now we'll serialize the ident with its
original casing, instead of always lowercase. Chrome and Firefox
disagree on this, so I think either is fine until that can be
officially decided.
Gets us 2 WPT passes (including 1 from the as-yet-unmerged :dir() test).
The spec gives us a hard-coded list of functional pseudo-classes and how
to serialize them - but this list is incomplete and likely to always be
outdated compared to the list of pseudo-classes that exist. So instead,
use the generated metadata we already have to serialize their arguments
based on their type.
This fixes :dir() and :has(), which previously did not serialize their
arguments.
Gets us 26 passes (including 6 from that as-yet-unmerged :dir() test).
Previously we only matched against the first attribute with a given
local name. What we actually want to do is look at each attribute with
that local name in turn and only return false if none of them match.
Also remove a hack for HTML elements in HTML documents, where we would
refuse to match any namespaced attributes. This doesn't seem to be
based on the spec, but we had regressions without it, until now. :^)
Gets us 21 more WPT subtest passes.
The HTML spec gives us a list of HTML attributes that must have their
values compared case-insensitively by default (when the attribute
selector does not specify a case-sensitiveness). However, ifwe have a
namespace, then we are not looking for an HTML attribute, so this
should not apply.
Gets us 8 more WPT subtest passes.