The verified pixel output in this test just reflects currently observed
behavior, I have not verified that all cases output the correct data wrt
what the spec expects.
The `Bitmap` type was referring to to its internal pixel format by a
name that represents the order of the color components as they are layed
out in memory. Contrary, the `Color` type was using a naming that where
the name represents the order of the components from most to least
significant byte when viewed as a unsigned 32bit integer. This is
confusing as you have to keep remembering which mental model to use
depending on which code you work with.
To unify the two, the naming of RGBA-like colors in the `Color` type has
been adjusted to match the one from the Bitmap type. This seems to be
generally in line with how web APIs think about these types:
* `ImageData.pixelFormat` can be `rgba-8unorm` backed by a
`Uint8ClamedArray`, but there is no pixel format backed by a 32bit
unsigned type.
* WebGL can use format `RGBA` with type `UNSIGNED_BYTE`, but there is no
such format with type `UNSIGNED_INT`.
Additionally, it appears that other browsers and browser-adjacent
libraries also think similarly about these types:
* Firefox:
https://github.com/mozilla-firefox/firefox/blob/main/gfx/2d/Types.h
* WebKit:
https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/graphics/PixelFormat.h
* Skia:
https://chromium.googlesource.com/skia/+/refs/heads/main/include/core/SkColorType.h
This has the not so nice side effect that APIs that interact with these
types through 32bit unsigned integers now have the component order
inverted due to little-endian byte order. E.g. specifying a color as hex
constant needs to be done as `0xAABBGGRR` if it is to be treated as
RGBA8888.
We could alleviate this by providing endian-independent APIs to callers.
But I suspect long-term we might want to think differently about bitmap
data anyway, e.g. to better support HDR in the future. However, such
changes would be more involved than just unifying the naming as done
here. So I considered that out of scope for now.
When decoding a BitmapSequence received over IPC, we were creating an
AnonymousBuffer for each bitmap and then making a Gfx::Bitmap wrapper
around it.
This was unnecessarily using up one file descriptor per bitmap, and also
wasting a lot of memory for small bitmaps since we always allocated at
least one VM page.
This patch changes the BitmapSequence decoder to use malloc memory
instead, saving file descriptors and using less memory overall.
This produces more granural information on the actual pixel errors
present between two bitmaps. It now also asserts that both bitmaps are
the same size, since we should never compare two differently sized
bitmaps anyway.
When decoding data into bitmaps, we end up with different alpha types
(premultiplied vs. unpremultiplied color data). Unfortunately, Skia only
seems to handle premultiplied color data well when scaling bitmaps with
an alpha channel. This might be due to Skia historically only supporting
premultiplied color blending, with unpremultiplied support having been
added more recently.
When using Skia to blend bitmaps, we need the color data to be
premultiplied. ImmutableBitmap gains a new method to enforce the alpha
type to be used, which is now used by SharedResourceRequest and
CanvasRenderingContext2D to enforce the right alpha type.
Our LibWeb tests actually had a couple of screenshot tests that exposed
the graphical glitches caused by Skia; see the big smiley faces in the
CSS backgrounds tests for example. The failing tests are now updated to
accommodate the new behavior.
Chromium and Firefox both seem to apply the same behavior; e.g. they
actively decode PNGs (which are unpremultiplied in nature) to a
premultiplied bitmap.
Fixes#3691.
This brings mmap more in line with other operating systems. Prior to
this, it was impossible to request memory that was definitely committed,
instead MAP_PURGEABLE would provide a region that was not actually
purgeable, but also not fully committed, which meant that using such memory
still could cause crashes when the underlying pages could no longer be
allocated.
This fixes some random crashes in low-memory situations where non-volatile
memory is mapped (e.g. malloc, tls, Gfx::Bitmap, etc) but when a page in
these regions is first accessed, there is insufficient physical memory
available to commit a new page.
Problem:
- `(void)` simply casts the expression to void. This is understood to
indicate that it is ignored, but this is really a compiler trick to
get the compiler to not generate a warning.
Solution:
- Use the `[[maybe_unused]]` attribute to indicate the value is unused.
Note:
- Functions taking a `(void)` argument list have also been changed to
`()` because this is not needed and shows up in the same grep
command.
When create_with_shared_buffer() is called in the next line, the
RefPtr::operator* asserts that the RefPtr is not null. That can happen when
we're low-ish on memory, and the image is huge.
Bitmap::is_path_a_supported_image_format() and Bitmap::load_from_file()
now check the file extension with CaseSensitivity::CaseInsensitive.
This fixes a couple of inconsistencies, for example would
FileSystemModel::icon_for() recognize image files uppercase extensions
but couldn't create thumbnails for them (any attempt to create a bitmap
from such files would fail).
If we're sharing buffers, we only want to share trivial structures
as anything else could potentially share internal pointers, which
most likely is going to cause problems due to different address
spaces.
Fix the GUI::SystemTheme structure, which was not trivial, which
is now caught at compile time.
Fixes#3650
Moves Bitmap backing store creation to the static create() methods.
This backing store is then passed into the Bitmap constructor. This
allows us correctly return nullptr from create() in the event that
memory allocation fails.
Errors like this became more likely due to the 'optimized' memory usage.
Also, this prevents the WindowServer from being killed by a goofy program
sharing an incomplete bitmap, and likely some other scenarios.
Indexed bitmaps used to allocate four times the required amount of memory.
Also, we should acknowledge that the underlying data is not always RGBA32,
and instead cast it only when the true type is known.
The new ImageDecoder service (available for members of "image" via
/tmp/portal/image) allows you to decode images in a separate process.
This will allow programs to confidently load untrusted images, since
the bulk of the security concerns are sandboxed to a separate process.
The only API right now is a synchronous IPC DecodeImage() call that
takes a shbuf with encoded image data and returns a shared buffer and
metadata for the decoded image.
It also comes with a very simple library for interfacing with the
ImageDecoder service: LibImageDecoderClient. The name is a bit of a
mouthful but I guess we can rename it later if we think of something
nicer to call it.
There's obviously a bit of overhead to spawning a separate process
for every image decode, so this is mostly only appropriate for
untrusted images (e.g stuff downloaded from the web) and not necessary
for trusted local images (e.g stuff in /res)
This adds support for loading the first image from ICO format images only if they are PNG encoded.
This is useful for loading favicons, which are sometimes PNGs with an ICO extension and sometimes actual ICO files.
In particular we can now load the favicon from new.ycombinator.com
Adds an *almost fully featured BMP loader to process .bmp files.
Features:
- All header formats are supported
- Full RLE4/8/24 support
- Color scaling (e.g. distributing a 5-bit color throughout the 8-bit
color spectrum, so 5-bit white is still 0xffffff)
- Full BITMASK/ALPHABITMASK support
*Not included:
- 1D Huffman compression. Good luck actually finding a bmp in the wild
that uses this
- Use of any field in the V4/V5 header. Color spaces? Endpoints? No
thanks :)
This loader was tested with the images at
https://entropymine.com/jason/bmpsuite/bmpsuite/html/bmpsuite.html. This
loader correctly displays 81 out of the 90 total images (for reference,
firefox displays 64 correctly). Note that not rendering the images at
the bottom is counted as displaying correctly.
If the area or size_in_bytes calculation for a Gfx::Bitmap would
overflow, we now refuse to create such a bitmap and return nullptr.
Thanks to @itamar8910 for finding this! :^)
With this patch, it's now possible to pass a Gfx::ShareableBitmap in an
IPC message. As long as the message itself is synchronous, the bitmap
will be adopted by the receiving end, and disowned by the sender nicely
without any accounting effort like we've had to do in the past.
Use this in NotificationServer to allow sending arbitrary bitmaps as
icons instead of paths-to-icons.
This feels a lot more consistent and Unixy:
create_shared_buffer() => shbuf_create()
share_buffer_with() => shbuf_allow_pid()
share_buffer_globally() => shbuf_allow_all()
get_shared_buffer() => shbuf_get()
release_shared_buffer() => shbuf_release()
seal_shared_buffer() => shbuf_seal()
get_shared_buffer_size() => shbuf_get_size()
Also, "shared_buffer_id" is shortened to "shbuf_id" all around.