The DocumentTimeline constructor used the current millisecond time to
initialize its currentTime, but that means that a newly created timeline
would always have a different time value than other timelines that have
been through the update_animations_and_send_events function.
Instead of scanning through the list of seen constants, we now have a
more structured storage of the constants true, false, null, undefined,
and every possible Int32 value.
This fixes an O(n^2) issue found by Kraken/json-stringify-tinderbox.js
This turns expressions like `(2 + 3) * 8 / 2` into a constant (20)
at bytecode compilation time instead of generating instructions
to calculate the value.
This is a new Bytecode::Generator helper that takes an operand and
returns the same operand, or a copy of it, in case a copy is required
to preserve correct evaluation order.
This can be used in a bunch of places where we're worried about
clobbering some value after obtaining it.
Practically, locals are always copied, and temporary registers as well
as constants are returned as-is.
Implements `table.get`, `table.set`, `elem.drop`, `table.size`,
and `table.grow`. Also fixes a few issues when generating ref-related
spectests. Also changes the `TableInstance` type to use
`Vector<Reference>` instead of `Vector<Optional<Reference>>`, because
the ability to be null is already encoded in the `Reference` type.
The benefit of the color indexing transform is to have only one
varying channel after it (the green channel, which after the
transform serves as index into the color table).
If there is only one varying channel before the transform, it's
not beneficial. (...except if there are <= 16 colors, then the
pixel bundling presumably still works.)
Functions that don't have a FunctionEnvironment will get their `this`
value from the ExecutionContext. This patch stops generating
ResolveThisBinding instructions at all for functions like that, and
instead pre-populates the `this` register when entering a new bytecode
executable.
We already have a dedicated register slot for `this`, so instead of
having ResolveThisBinding take a `dst` operand, just write the value
directly into the `this` register every time.
This allows searching for text with case-insensitivity. As this is
probably what most users expect, the default behavior is changes to
perform case-insensitive lookups. Chromes may add UI to change the
behavior as they see fit.
Storing a number n needs floor(log2(n) + 1) bits, not ceil(log2(n)).
(The two expressions are identical except for when n is a power of 2.)
Serendipitously covered by the indexed color transform tests in this PR.
If an image has <= 16 colors, WebP lossless files pack multiple
color table indexes into a single pixel's green channel, further
reducing file size. This adds support for that.
My current test files all have more than 16 colors. For a 16x16
black-and-white bitmap that contains a little smiley face in the
middle, this reduces the output size from 128B to 54B.
If an image has 256 or fewer colors, WebP/Lossless allows storing
the colors in a helper image, and then storing just indexes into that
helper image in the main image's green channel, while setting
r, b, and a of the main image to 0.
Since constant-color channels need to space to store in WebP,
this reduces storage needed to 1/4th (if alpha is used) or 1/3rd
(if alpha is constant across the image).
If an image has <= 16 colors, WebP lossless files pack multiple
color table indexes into a single pixel's green channel, further
reducing file size. This pixel packing is not yet implemented in
this commit.
GIFs can store at most 256 colors per frame, so animated gifs
often have 256 or fewer colors, making this effective when
transcoding gifs.
(WebP also has a "subtract green" transform, which can be used
to need to store just a single channel for grayscale images, without
having to store a color table. That's not yet implemented -- for now,
we'll now store grayscale images using this color indexing transform
instead, which wastes to storage for the color table.)
(If an image has <= 256 colors but all these colors use only a single
channel, then storing a color table for these colors is also wasteful,
at least if the image has > 16 colors too. That's rare in practice,
but maybe we can add code for it later on.)
(WebP also has a "color cache" feature where the last few used colors
can be referenced using very few bits. This is what the webp spec says
is similar to palettes as well. We don't implement color cache writing
support yet either; maybe it's better than using a color indexing
transform for some inputs.)
Some numbers on my test files:
sunset-retro.png: No performance or binary size impact. The input
quickly uses more than 256 colors.
giphy.gif (184k): 4.1M -> 3.9M, 95.5 ms ± 4.9 ms -> 106.4 ms ± 5.3 ms
Most frames use more than 256 colors, but just barely. So fairly
expensive runtime wise, with just a small win.
(See comment on #24454 for the previous 4.9 MiB -> 4.1 MiB drop.)
7z7c.gif (11K): 118K -> 40K
Every frame has less than 256 colors (but more than 16, so no packing),
and so we can cut filesize roughly to 1/3rd: We only need to store an
index per channel. From 10.7x as large as the input to 3.6x as large.
No behavior change, but this makes it easy to correctly set this
flag when adding an indexing transform: Opacity then needs to be
determined based on if colors in the color table have opacity,
not if the indexes into the color table do.
With this struct, only the first time something sets opacity is
honored, giving us those semantics.
In an early version of the huffman writing code, we always used 8 bits
here, and the comments still reflected that. Since we're now always
writing only as many bits as we need (in practice, still almost always
8), the comments are misleading.
This allows the browser to send a query to the WebContent process,
which will search the page for the given string and highlight any
occurrences of that string.
This works for now, but is technically still not spec compliant. Right
now, we're (potentially) missing one bit when reading function indices.
See the relevant issue: #24462.
There was an issue with Clang that causes `consteval` function calls
from default initializers of fields to be made at run-time. This
manifested itself in the case of `ByteString::formatted` as an undefined
reference to `check_format_parameter_consistency` once format string
checking was enabled for Clang builds. The workaround is simple (just
move it to the member initializer list), and unblocks a useful change.
This adds a `--experimental-cpu-transforms` option to Ladybird and
WebContent (which defaults to false/off).
When enabled the AffineCommandExecutorCPU will be used to handle
painting transformed stacking contexts (i.e. stacking contexts where
the transform is something other than a simple translation). The regular
command executor will still handle the non-transformed cases.
This is hidden under a flag as the `AffineCommandExecutorCPU` is very
incomplete now. It missing support for clipping, text, and other basic
commands. Once most common commands have been implemented this flag
will be removed.
This CommandExecutor is intended to provide better support for painting
stacking contexts where the transform is not a simple translation. It
is not intended to replace the CPU command executor (as its methods of
painting will likely be slower for the non-transformed case), instead,
it will function as a companion executor to handle transformations.
This is only intended to properly handle 2D transformations (skews,
rotations, scaling, etc). Full support for 3D transformations would
need further changes in LibGfx.
As it stands this is (very) incomplete and experimental, but hopefully,
this can be fleshed out to the point where it supports most common
painting commands.
This adds two new CommandResults: ContinueWithNestedExecutor and
ContinueWithParentExecutor.
ContinueWithNestedExecutor switches the command executor to the result
of calling `.nested_executor()` on the current CommandExecutor.
ContinueWithParentExecutor returns to the previous command executor
(i.e. what it was before the last ContinueWithNestedExecutor).
Using `draw_scaled_bitmap()` for simple scales is almost always better
than using `draw_scaled_bitmap_with_transform()` which does not respect
the scaling mode.
`Painting::paint_all_borders()` only uses `.draw_line()` for simple
borders and `.fill_path()` for more complex cases. These are both
already supported by the `RecordingPainter` so removing this command
simplifies the painting API.
Two test changes:
css-background-clip-text: Borders are now drawn via the AA painter
(which makes them closer to how they appear in other browsers).
corner-clip-inside-scrollable: Borders removed (does not change test)
due to imperceptible sub-pixel changes.
The check from 0805319d1e is too strict for animated images: It's
possible that an animation has alpha, but a frame doesn't.
(For example, if the animation is 10x10 pixels, but one frame updates
just 1x1 pixels. But even a full-sized frame could just not have alpha.)
If the VP8X header claims that the animation has alpha, we could check
that at least one frame has alpha, but for now we just don't do any
checking for animated images.
...instead of scheduling repaint timer in PageClient.
This change fixes flickering on Discord that happened because:
- Event loop schedules repainting by activating repaint timer
- `Document::tear_down_layout_tree()` destroys paintable tree
- Repaint timer invokes callback and renders an empty frame because
paintable tree was destroyed
Although refreshing is cheap, it was performed before each hit-testing
and was 2-4% in profiles on Discord and Twitter.
Now clip and scroll states are refreshed only if scroll offset has
changed.
Previously, we always cast to a HTMLInputElement when getting the value
of an auto directionality form associated element. This caused
undefined behavior when determining the directionality of an element
that wasn't a HTMLInputElement.
Previously, we assumed that all label control paintables were of type
`LabelablePaintable`. This caused a crash when clicking on a label with
a text input control.
As with all other current audio nodes we still need to wire up the
inputs and outputs so it can be properly used in an audio context - but
this is enough to implement the public IDL interface.