An early return was occurring between the emission of
PushStackingContext and PopStackingContext, resulting in a
PushStackingContext without a corresponding PopStackingContext in the
display list, which caused broken painting.
Fixes black screen on Discord login page.
We previously checked the cell's computed values for the border-collapse
property, but a cell is only in separated-borders mode if the table has
border-collapse set to separate. Curiously in some other placed where
this mode is checked we already did the correct thing.
When recording the display list for a stacking context, the following
operations (relevant to this bug) happened:
* push a stacking context
* as part of that push a None-value to the scroll frame id stack
* apply filters
* apply masking
* paint recursively
This meant that mask-images were always recorded without scroll frame
id, causing them to be painted without any scroll offset. As a result
mask-images would break as soon as the website using them was scrolled.
Instead, push to the scroll frame id stack later to solve the problem:
* push a stacking context
* apply filters
* apply masking
* push a None-value to the scroll frame id stack
* paint recursively
This was the only remaining data type used in display lists that wasn't
atomically ref-counted.
Now that it is, we no longer crash when scrolling on https://vercel.com/
The contain-paint-stacking-context-001a.html test has been removed
for now because it has a 1px tall blue line at the top that should
not be there. With paint containment, this line is removed only in
the actual test case, but not in the reference. This is because of
the font that we use in testing and happens in Chromium as well if
the test is run with that font.
We're able to efficiently draw repeated bitmaps through Skia, but for
backgrounds we only did so if the background was `repeat-x` _and_
`repeat-y`, and not if just one was set. This meant that for backgrounds
that were only repeating in one direction, we were taking the slow path.
Turns out that this slow path also produced graphical artifacts when
zooming in and out, so let's not do that :^)
A scrollbar contains a mouse position only if its gutter rect contains
that position. We were incorrectly deciding a position was contained if
it fell to the right of a vertical scrollbar, or below a horizontal
scrollbar.
This `translate_by` function is invoked with the cumulative scroll
offset during display list execution. Applying the offset to the gutter
was missed in 66e422b4f1.
This allows the media paintable to be redrawn when the media element is
paused. We change the color of some components on hover, but if the
media was paused, that would not be rendered. This wasn't an issue while
the media is playing because the update to the timeline would take care
of redrawing the paintable.
Currently, compute_scrollbar_data does not adjust the position of the
scrollbar thumb based on the actual scroll offset. This is because we
perform this offset in most cases inside the display list executor, in
order to allow us to avoid recomputing the display list.
However, there are cases where we do want the thumb rect with an offset
inside PaintableBox. We currently use scroll_thumb_rect to perform that
computation.
In an upcoming patch, we will need both this offset thumb rect and the
scrollbar gutter rect. So this patch moves the computation of the offset
to compute_scrollbar_data, performed behind an optional parameter.
When a scrollbar is not interacting with the mouse, we now draw the
scrollbar slightly slimmer. When the mouse enters the space occupied
by the scrollbar, we enlarge it for easier mouse interactivity.
With this change we save a copy of of scroll state at the time of
recording a display list, instead of actual ScrollState pointer that
could be modifed by the main thread while display list is beings
rasterized on the rendering thread, which leads to a frame painted with
inconsistent scroll state.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/4288
This patch adds a workaround for a Swift issue where boolean bitfields
with getters and setters in SWIFT_UNSAFE_REFERENCE types are improperly
imported, causing an ICE.
`DisplayListPlayer::execute_impl()` can receive null surface if it was
invoked to rasterize nested display lists (we use them for iframes). In
this case we should not call `flush()` by the end of execution and wait
until outer display list execution will do that.
The Skia Ganesh backend we currently use doesn't support painting from
multiple threads, which could happen before this change when the main
thread used Skia to paint on the HTML canvas while the rendering thread
was working on display list rasterization.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/4172
Deleteing set_surface() makes DisplayListPlayer API a bit more intuitive
because now caller doesn't have to think whether it's necessary to
restore previous surface after execution, instead DisplayListPlayer
takes care of it by maintaining a stack of surfaces.
This is a improved version of a73cd88f0c
The old commit was reverted in 552dd18696
The new version only paints an element into a new layer if background
blend modes other than normal are used. The rasterization performance
of most websites should therefore not suffer.
Co-Authored-By: Alexander Kalenik <kalenik.aliaksandr@gmail.com>
The display list is an immutable data structure, so once it's created,
rasterization can be moved to a separate thread. This allows more room
for performing other tasks between processing HTML rendering tasks.
This change makes PaintingSurface, ImmutableBitmap, and GlyphRun atomic
ref-counted, as they are shared between the main and rendering threads
by being included in the display list.
Previously, all `GC::Cell` derived classes were Weakable. Marking only
those classes that require this functionality as Weakable allows us to
reduce the memory footprint of some frequently used classes.