There is a problem with current approach where overflow clip rectange is
calculated by aggregating intersection of absolute padding boxes of
boxes in containing block chain that resulting rectangle doesn't
respect transform properties.
To solve this problem `PaintableBox` is changed to store clip rectangle
saved from painter because it does respect transform properties of all
previously applied clip rectangles.
This simplifies the ownership model between DOM/layout/paint nodes
immensely by deferring to the garbage collector for figuring out what's
live and what's not.
This moves the CSS gradient painting to the painter creating:
- Painter::fill_rect_with_linear_gradient()
- Painter::fill_rect_with_conic_gradient()
- Painter::fill_rect_with_radial_gradient()
This has a few benefits:
- The gradients can now easily respect the painter scale
- The Painter::fill_pixels() escape hatch can be removed
- We can remove the old fixed color stop gradient code
- The old functions are now just a shim
- Anywhere can now easily use this gradient painting code!
This only leaves the color stop resolution in LibWeb (which is fine).
Just means in LibGfx you have to actually specify color stop positions.
(Also while here add a small optimization to avoid generating
excessively long gradient lines)
Previously gradient painting was dominated by the clipping checks in
Painter::set_pixel(). This commit changes gradient painting to use the
new Painter::fill_pixels() function (which does all these checks outside
the hot loop).
With this change gradient painting drops from 96% of the profile to 51%
when scrolling around on gradients.html. A nice 45% reduction :^)
Previously we were doing this at the painting stage, which meant that
layout potentially used the wrong glyphs when measuring text.
This would lead to incorrect layout metrics and was visible on the
HTML5Test score display, for example. :^)
This was wrong twice making it right... But let's fix that.
The center was being passed as a DevicePixelPoint, but was in fact in
CSS pixels, the size was passed as a Gfx::FloatSize but was in
CSS pixels again. Then we were scaling from device pixels to CSS pixels
when painting which does not need to be done if everything is passed
which the correct scale factors already applied.
This fixes a few sizing issues too. The page size is now correct in most
cases! \o/
We get to remove some of the `to_type<>()` shenanigans, though it
reappears in some other places.
Store the ratio between device and CSS pixels on the PaintContext, so
that it can convert between the two.
Co-authored-by: MacDue <macdue@dueutil.tech>
The indexes are into the _node_, not in the fragment, so when a node is
split into multiple fragments, simply taking the length of the fragment
is incorrect. This patch corrects this mistake.
...and also for hit testing, which is involved in most of them.
Much of this is temporary conversions and other awkwardness, which
should resolve itself as the rest of LibWeb is converted to these new
types. Hopefully. :thousandyakstare:
Discord modals/pop-outs are in a "layerContainer" <div> with
`z-index: 1002`, which then has an immediate child <div> called
"positionLayer" with `z-index: 0`. We only ever hit test child stacking
contexts with z-index set to anything but 0 (step 7 and step 1 of the
hit test), but not for exactly 0 (step 6). This made it impossible to
hit any element inside positionLayer, making pop-ups such as the emojis
and GIFs unusable.
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.
One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
This fixes a rendering issue where box-shadows would not appear or
render completely broken if the blur radius was larger than the
border radius (border-radius < 2 * blur-radius to be exact).