It is only PaintableBox that can have scrollable overflow so it doesn't
make sense to have handle_mousewheel() implementation in Paintable.
Also new implementation of handle_mousewheel() takes in account overflow
limits from scrollable_overflow_rect().
The volume control's slider is drawn in a rectangle shrunken by its
slider handle's size, so the handle did not move 1:1 with the user's
mouse movement.
To fix this, it will now check for a mousedown in the volume control
with a rectangle sized to fit any possible position of the handle, but
the volume value result will be calculated based on the center of the
handle instead. This allows it to move 1:1 with the mouse cursor.
Co-authored-by: trflynn89 <trflynn89@serenityos.org>
...along with `outline-color`, `outline-style`, and `outline-width`.
This re-uses the existing border-painting code, which seems to work well
enough!
This replaces the previous code for drawing focus-outlines, with generic
outline painting for any elements that want it. Focus outlines are now
instead supported by this code in Default.css:
```css
:focus-visible {
outline: auto;
}
```
This patch adds handling of the 'object-fit' CSS property to the
painting of HTML Image Elements.
This is achieved by first calculating the rect which the image would
need if it were to fully expand into open space and then adequately
cropping it to fit into the image's box.
scale-down is not supported for now.
Otherwise, in a simple page such as:
<video src=...>
<audio src=...>
The video's clip rect would "leak" to the AudioPaintable, preventing the
audio controls from rendering at all.
Not a huge deal because the base MediaPaintable class goes very out of
its way to paint within the confines of its own box, but just to be
safe, this was missed when adding the AudioPaintable class.
The `clip_shrink` optimization in `paint_background()` now also
correctly uses DevicePixels, instead of reducing a DevicePixel rect by
a CSSPixels amount.
When joined border width is zero width, then the midpoint
of the joined corner is no longer need to be computed
anymore. Just set the mid point to be the endpoint of the
corner.
Fixes broken border-radius painting because of lost precision while
converting back and forth between double and CSSPixels.
Fixed example:
```html
<style>
div {
border-radius: 9999px;
background: orange;
padding: 10px;
}
</style><div>huh</div>
```
Using fixed-point saturated arithmetics for CSSPixels allows to avoid
accumulating floating-point errors.
This implementation is not complete yet: currently saturated
arithmetics implemented only for addition. But it is enough to not
regress any of layout tests we have :)
See https://github.com/SerenityOS/serenity/issues/18566
The refactor of the border painting mainly to handle:
1. Single border with minor border radius.
2. Different border widths and border colors joined situations.
This refactor only apply to solid border.
The main differece is to use Path.fill to paint each border,
not fill_rect anymore. There's a special case need to consider.
The Path.fill will leave shared edge blank between two borders.
To handle this, we decide to combine the borders with same color
to paint together.
There are two parts to this fix:
- First, StyleProperties::transformations() would previously omit calc()
values entirely when returning the list of transformations. This was
very confusing to StackingContext which then tried to index into the
list based on faulty assumptions. Fix this by emitting calc values.
- Second, StackingContext::get_transformation_matrix() now always calls
resolve() on length-percentages. This takes care of actually resolving
calc() values. If no reference value for percentages is provided, we
default to 0px.
This stops LibWeb from asserting on websites with calc() in transform
values, such as https://qt.io/ :^)
Since we deliberately skip positioned elements in paint_descendants(),
we have to make sure we actually paint them in the subsequent
paint_internal() pass.
Before this change, we were only painting positioned elements whose
paintable was a PaintableBox, neglecting inline-level relpos elements.
Defer conversion to device pixels until we need to paint. This
helps borders of cells with different spans align, since rounding early
makes addition non-associative.
This finally fixes the issue where stacking contexts that have either a
transform or opacity != 1 would clip their descendants to the root of
the stacking context.
Importantly, we now only consider overflow from descendants with
explicltly visible overflow, and only from descendants that have the
measured box as their containing block.
Also, we now measure scrollable overflow for all boxes, not just scroll
containers. This will allow us to fix a long-standing paint problem in
the next commit.
Follow the specification in making the borders centered on the grid
lines. This avoids visual bugs due to double-rendering of borders on
either side of an edge and paves the way for a full implementation of
the harmonization algorithm for collapsed borders.
Currently, this still lacks complete handling of row and column spans.
Also, the box model for cells still considers the full width of the
internal borders instead of just half, as the specification requires.
Some additional handling of rounding issues will be needed to avoid very
subtle visual bugs.
Despite these limitations, this improves the appearance of all the
tables with collapsed borders I've tried while limiting the amount of
change to something reasonable.
Move painting of cell borders to a separated function since doing it
correctly has to consider the entire grid as a whole for the collapsed
borders case.
Feels nicer to click anywhere on the control box to toggle playback,
rather than needing to accurately click the playback button. Note this
does not affect other behavior-specific buttons; i.e. if the mute button
is pressed, we won't reach the playback toggle..
The SVGContext is a leftover from when SVG properties were more ad-hoc.
All properties are now (for better or worse) treated as CSS properties
(or handled elsewhere). This makes the SVGContext's fill/stroke
inheritance handling unnecessary.
Before this change, we only blurred the shadows which would've been
generated without blur. This meant that we didn't generate a shadow when
the offset was zero, even with blur. However, other browsers generate a
shadow when blur is set.
Instead, always generate a rectangular contour of sufficient thickness,
blur it if needed and blit it into the right position at the very end.
Thanks to the blur radius, we'll have a shadow even when the offset is
zero.
It's a little bit of a battle to fit all of the media controls in the
available width of the media element. We currently cram everything on
one horizontal line. We've made adjustments to be able to fit it all,
but the controls (in particular the media timeline) are rather squished.
This paints the timeline above the other media controls now. This
provides much more granular control over the playback position when
scrubbing, and makes it much more likely for the timeline to render at
all.