This implementation also fixes an issue where the individual components
of the `border-radius` shorthand were always assumed to be of type
`BorderRadiusStyleValue`, which could lead to a crash when CSS-wide
keywords were used.
Instead of trying to manually determine which parts of a bitmap fall
within the box of the `<img>` element, just draw the whole bitmap and
let Skia clip the draw-area to the correct rectangle.
This fixes a bug where the entire bitmap was squashed into the rectangle
of the image box instead of being clipped.
With this change, image rendering is now correct enough to import some
of the WPT tests for object-fit and object-position. To get some good
coverage I have imported all tests for the `<img>` tag. I also wanted to
import a subset of the tests for the `<object>` tag, since those are
passing as well now. Unfortunately, they are flaky for unknown reasons.
This is the second attempt at this bugfix. The prior one was e055927ead
and broke image rendering whenever the page was scrolled. It has
subsequently been reverted in 16b14273d1. Hopefully this time it is not
horribly broken.
Instead of trying to manually determine which parts of a bitmap fall
within the box of the `<img>` element, just draw the whole bitmap and
let Skia clip the draw-area to the correct rectangle.
This fixes a bug where the entire bitmap was squashed into the rectangle
of the image box instead of being clipped.
With this change, image rendering is now correct enough to import some
of the WPT tests for object-fit and object-position. To get some good
coverage I have imported all tests for the `<img>` tag. I also wanted to
import a subset of the tests for the `<object>` tag, since those are
passing as well now. Unfortunately, they are flaky for unknown reasons.
A cursor is an image, with an optional x,y hotspot.
We know that a CursorStyleValue's bitmap never needs to change size, so
we create the ShareableBitmap once and then cache it, so that we don't
have to repeatedly create an FD for it or do the work of painting.
To avoid repainting that bitmap, we cache the values that were used to
create it - what currentColor is and its length resolution context -
and only repaint when those change.
None of the code here actually needs a NodeWithStyleAndBoxModelMetrics,
and we'll need to be able to resolve images from inside
NodeWithStyle::apply_style().
We previously only invalidated the cached color-stop data when the
painted area's size changed. However, multiple elements can use the
same gradient and be the same size, but have different parameters that
affect the gradient stop positions, for example if a stop has an em
position. This can also change for the same element over time.
The new cache instead uses these parameters as the cache key. So we
recompute the cache if lengths would resolve differently, or the area's
size is different.
The included test fails without this change.
The main users were the `dump()` functions, which now dump their
children instead, which is more correct anyway.
The others are for serializing numeric values, so
NumericCalculationNode's to_string() is renamed to value_to_string
() and used for those for convenience.
This gets us 37 new subtest passes in css/css-values, and 13 passes in
our other in-tree tests (and probably some random other ones!)
As noted in comments, a few parts of this algorithm have ad-hoc
behaviour to handle some issues in the spec.
Having multiple kinds of node that hold numeric values made things more
complicated than they needed to be, and we were already converting
ConstantCalculationNodes to NumericCalculationNodes in the first
simplification pass that happens at parse-time, so they didn't exist
after that.
As noted, the spec allows for other contexts to introduce their own
numeric keywords, which might be resolved later than parse-time. We'll
need a different mechanism to support those, but
ConstantCalculationNode could not have done so anyway.
Before this change, we only parsed fit-content as a standalone keyword,
but CSS-SIZING-3 added it as a function as well. I don't know of
anything else in CSS that is overloaded like this, so it ends up looking
a little awkward in the implementation.
Note that a lot of code had already been prepped for fit-content values
to have an argument, we just weren't parsing it.
This reduces the number of `.cpp` files that need to be recompiled when
one of the below header files changes as follows:
Painting/Command.h: 1030 -> 61
Painting/DisplayList.h: 1030 -> 60
Painting/DisplayListRecorder.h: 557 -> 59
We've long claimed to support this, but then silently ignored string
values, until 4cb2063577 which would
not-so-silently crash instead. (Oops)
So, actually pass the string value along and use it in the list marker.
As part of this, rename our `list-style-type` enum to
`counter-style-name-keyword`. This is an awkward name, attempting to be
spec-based. (The spec says `<counter-style>`, which is either a
`<counter-style-name>` or a function, and the `<counter-style-name>` is
a `<custom-ident>` that also has a few predefined values. So this is the
best I could come up with.)
Unfortunately only one WPT test for this passes - the others fail
because we produce a different layout when text is in `::before` than
when it's in `::marker`, and similar issues.
The Web::CSS::Parser's GradientParsing ignores color-stops if
it is only a single one. This change allows to have color-stops
with double positions against a single color.
Further, also allows for `linear-gradient(black)` and similar
other gradient functions
If a calculation was simplified down to a single numeric node, then most
of the time we can instead return a regular StyleValue, for example
`calc(2px + 3px)` would be simplified down to a `5px` LengthStyleValue.
This means that parse_calculated_value() can't return a
CalculatedStyleValue directly, and its callers all have to handle
non-calculated values as well as calculated ones.
This simplification is reflected in the new test results. Serialization
is not yet correct in all cases but we're closer than we were. :^)
Calc simplification eventually produces a single style-value as its
output. This extra context data will let us know whether a calculated
number should be treated as a `<number>` or an `<integer>`, so that for
example, `z-index: 12` and `z-index: calc(12)` both produce an
`IntegerStyleValue` containing 12.
The goal of this VERIFY was to ensure that we didn't mess up the logic
for calculating the correct type. However, it's now unable to do so
because it doesn't have access to the CalculationContext, which
determines what type percentages are. This makes it crash when running
the simplification algorithm. The benefits of this check are small, and
it meant doing extra work, so let's just remove it.
Calc simplification (which I'm working towards) involves repeatedly
deriving a new calculation tree from an existing one, and in many
cases, either the whole result or a portion of it will be identical to
that of the original. Using RefPtr lets us avoid making unnecessary
copies. As a bonus it will also make it easier to return either `this`
or a new node.
In future we could also cache commonly-used nodes, similar to how we do
so for 1px and 0px LengthStyleValues and various keywords.
To be properly compatible with calc(), the resolved() methods all need:
- A length resolution context
- To return an Optional, as the calculation might not be resolvable
A bonus of this is that we can get rid of the overloads of `resolved()`
as they now all behave the same way.
A downside is a scattering of `value_or()` wherever these are used. It
might be the case that all unresolvable calculations have been rejected
before this point, but I'm not confident, and so I'll leave it like
this for now.
Initially I added this to the existing CalculationContext, but in
reality, we have some data at parse-time and different data at
resolve-time, so it made more sense to keep those separate.
Instead of needing a variety of methods for resolving a Foo, depending
on whether we have a Layout::Node available, or a percentage basis, or
a length resolution context... put those in a
CalculationResolutionContext, and just pass that one thing to these
methods. This also removes the need for separate resolve_*_percentage()
methods, because we can just pass the percentage basis in to the regular
resolve_foo() method.
This also corrects the issue that *any* calculation may need to resolve
lengths, but we previously only passed a length resolution context to
specific types in some situations. Now, they can all have one available,
though it's up to the caller to provide it.
Same again, although rotation is more complicated: `rotate`
is "equivalent to" multiple different transform function depending on
its arguments. So we can parse as one of those instead of the full
`rotate3d()`, but then need to handle this when serializing.
The only ways this varies from the `scale()` function is with parsing
and serialization. Parsing stays separate, and serialization is done by
telling `TransformationStyleValue` which property it is, and overriding
its normal `to_string()` code for properties other than `transform`.
Various places in the spec allow for `<number> | <percentage>`, but this
is either/or, and they are not allowed to be combined like dimensions
and percentages are. (For example, `calc(12 + 50%)` is never valid.)
User code generally doesn't need to care about this distinction, but it
does now need to check if a calculation resolves to a number, or to a
percentage, instead of a single call.
The existing parse_number_percentage[_value]() methods have been kept
for simplicity, but updated to check for number/percentage separately.