1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 02:37:42 +00:00
Commit graph

1828 commits

Author SHA1 Message Date
Andreas Kling
c4d75ac11a LibGfx/GIF: Avoid a silly loop in GIF logical screen parsing 2024-01-05 13:20:00 +01:00
Andreas Kling
182a2b0c3a LibGfx/GIF: Only parse global color table if header flag is set
This fixes an issue where GIF images without a global color table would
have the first segment incorrectly interpreted as color table data.

Makes many more screenshots appear on https://virtuallyfun.com/ :^)
2024-01-05 13:20:00 +01:00
Lucas CHOLLET
b8cbc282f3 LibGfx/TIFF: Don't stop decoding when failing to decode a tag
TIFF files are made in a way that make them easily extendable and over
the years people have made sure to exploit that. In other words, it's
easy to find images with non-standard tags. Instead of returning an
error for that, let's skip them.

Note that we need to make sure to realign the reading head in the file.

The test case was originally a 10x10 checkerboard image with required
tags, and also the `DocumentName` tag. Then, I modified this tag in a
hexadecimal editor and replaced its id with 30 000 (0x3075 as a LE u16)
and the type with the same value as well. This is AFAIK, never used as
a custom TIFF tag, so this should remain an invalid tag id and type.
2024-01-04 14:27:16 +01:00
Nico Weber
fa24fbf120 LibGfx/OpenType: Survive simple glyphs with 0 contours
These are valid per spec, and do sometimes occur in practice, e.g.
in embedded fonts in 0000550.pdf and 0000246.pdf in 0000.zip in the
PDFA test set.
2024-01-04 03:32:46 +01:00
MacDue
b4eb66d9fe LibGfx: Simplify condition
This is just an XOR. No behaviour change.
2024-01-03 12:56:01 +01:00
MacDue
db51e80d50 LibGfx: Fix typo 2024-01-03 12:56:01 +01:00
MacDue
a9502396ee LibGfx: Remove somewhat outdated comment
Most of these optimizations have been tried now, so this comment is a
bit misleading.
2024-01-03 12:56:01 +01:00
MacDue
096bdb142b LibGfx: Speed up filling solid colors in path rasterizer
For solid color fills (with alpha = 255), the rasterizer now tracks
spans of solid colors within a scanline and fills the entire span with
a single call to fast_u32_fill().

This gave up to a 1.5x speedup drawing the Ghostscript Tiger within
SerenityOS.
2024-01-03 12:56:01 +01:00
MacDue
2fa488cfa9 LibGfx: Skip horizontal edges in path rasterizer
Only the vertical parts of edges are plotted (then accumulated
horizontally). Fully horizontal edges won't be plotted (and just result
in NaNs).
2024-01-03 12:56:01 +01:00
Lucas CHOLLET
4e09ee1f2f LibGfx/TIFF: Reject images that declare a sample with abnormal bit depth
Anything with a bit depth of zero or greater than 32 is outside our
working range, so let's reject them.
2024-01-02 06:52:50 -07:00
Lucas CHOLLET
ba84af7c22 LibGfx/TIFF: Move check on tag values in its own function
There is only one check for now, but the fuzzer has already found more
checks to add :^)
2024-01-02 06:52:50 -07:00
Nico Weber
bcb1e548f1 LibGfx/ICC: Improve XYZ coordinates of gray colors
In XYZ space, gray doesn't have three equal values. Instead, it is
a line through the whitepoint.

(Multiplying by the whitepoint has the same effect as multiplying
the sRGB matrix with a (g, g, g) vector, since the numbers on
the matrix's rows add up to the whitepoint.)

Fixes the very slight red tint on all the figures in chapter 4
of the PDF 1.7 spec.
2023-12-31 13:20:37 +01:00
Lucas CHOLLET
31b5f17f79 LibGfx/TIFF: Reject images with invalid StripByteCounts or StripOffsets
These two arrays should have the exact same size, files not respecting
this condition should be considered as invalid.
2023-12-30 23:24:05 +01:00
Lucas CHOLLET
82d40aab18 LibGfx/TIFF: Don't try to check non-existent values
We were previously only checking the first value, this is wrong for tags
that accept multiple values (e.g. ExtraSamples) and can lead to crashes
on malformed images containing tags with a count of 0.
2023-12-30 23:24:05 +01:00
Lucas CHOLLET
d66a421757 LibGfx/TIFF: Enforce a length of one for more tags
The TIFF spec is constructed in a way that many tags are defined in
multiple places but some of these definitions are partial. If we look
into "Section 8: Baseline Field Reference Guide", we can see that these
tags indeed have an enforced length of 1.
2023-12-30 23:24:05 +01:00
Aliaksandr Kalenik
ac6b3c989d LibWeb: Apply scroll boxes offsets after painting commands recording
With this change, instead of applying scroll offsets during the
recording of the painting command list, we do the following:
1. Collect all boxes with scrollable overflow into a PaintContext,
   each with an id and the total amount of scrolling offset accumulated
   from ancestor scrollable boxes.
2. During the recording phase assign a corresponding scroll_frame_id to
   each command that paints content within a scrollable box.
3. Before executing the recorded commands, translate each command that
   has a scroll_frame_id by the accumulated scroll offset.

This approach has following advantages:
- Implementing nested scrollables becomes much simpler, as the
  recording phase only requires the correct assignment of the nearest
  scrollable's scroll_frame_id, while the accumulated offset from
  ancestors is applied subsequently.
- The recording of painting commands is not tied to a specific offset
  within scrollable boxes, which means in the future, it will be
  possible to update the scrolling offset and repaint without the need
  to re-record painting commands.
2023-12-30 11:10:24 +01:00
Lucas CHOLLET
73c8b4865e LibGfx/TIFF: Add AdobeDeflate compression support
This new compression is quite popular and uses a basic Zlib compression
to compress strips. Note that this is not part of the original TIFF
specification but in the Technical Notes from 2002:
https://web.archive.org/web/20160305055905/http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf

The test case was generated with GIMP.
2023-12-29 20:12:07 +01:00
Nico Weber
9c5a75067f LibGfx/JPEG: Reject ycck or cmyk jpegs with k subsampled for now
The decoder assumes that k's sampling factor matches y's at the moment.
Better to error out than to silently render something broken.

For ycck, covered by ycck-2111.jpg in the tests.
2023-12-29 18:55:57 +01:00
Nico Weber
a2bd19fdac LibGfx/JPEG: Make ycck jpegs with just cc subsampled decode correctly
We currently assume that the K (black) channel uses the same sampling
as the Y channel already, so this already works as long as we don't
error out on it.
2023-12-29 09:45:31 -05:00
Lucas CHOLLET
f389c1cdba LibGfx+LibPDF: Use LibCompress' implementation of the PackBits decoder
No need to have these three copies :^)
2023-12-27 17:40:11 +01:00
Nico Weber
3c39c18440 LibGfx/JPEG: Add spec comment to read_start_of_frame() 2023-12-27 13:38:25 +00:00
Andreas Kling
a30d263522 LibGfx: Don't clone fonts in FontCascadeList::extend()
This was create a completely avoidable explosion of BitmapFont clones
when running on SerenityOS.
2023-12-27 11:42:05 +01:00
Andreas Kling
f900957d26 LibGfx+LibWeb: Move Gfx::ScaledFont caching from LibWeb into LibGfx
Before this change, we would only cache and reuse Gfx::ScaledFont
instances for downloaded CSS fonts.

By moving it into Gfx::VectorFont, we get caching for all vector fonts,
including local system TTFs etc.

This avoids a *lot* of style invalidations in LibWeb, since we now vend
the same Gfx::Font pointer for the same font when used repeatedly.
2023-12-26 18:15:55 +01:00
MacDue
64411127cb LibGfx: Clip edges above or below the visible area in the rasterizer
This avoids doing pointless plotting for scanlines that will never be
seen.

Note: This currently can only clip edges vertically. Horizontal clipping
is more tricky, since edges that are not visible can still change how
things accumulate across the scanline.

Fixes #22382

Sadly, this causes a bunch of LibWeb test churn as this change
imperceptibly changes the final rasterized output.
2023-12-24 13:25:40 +01:00
Lucas CHOLLET
a31b988473 LibGfx/TIFF: Ensure baseline tags presence before decoding
This allows us to reject invalid images before trying to decode them.
The spec requires more tag to be present[1] but as we don't use them for
decoding I don't see the point.

[1] - XResolution, YResolution and ResolutionUnit
2023-12-23 20:54:07 +01:00
Lucas CHOLLET
67522fab2e LibGfx/TIFF: Add support for RGBPalette images
TIFF images with the PhotometricInterpretation tag set to RGBPalette are
based on indexed colors instead of explicitly describing the color for
each pixel. Let's add support for them.

The test case was generated with GIMP using the Indexed image mode after
adding an alpha layer. Not all decoders are able to open this image, but
GIMP can.
2023-12-23 20:41:48 +01:00
Shannon Booth
e2e7c4d574 Everywhere: Use to_number<T> instead of to_{int,uint,float,double}
In a bunch of cases, this actually ends up simplifying the code as
to_number will handle something such as:

```
Optional<I> opt;
if constexpr (IsSigned<I>)
    opt = view.to_int<I>();
else
    opt = view.to_uint<I>();
```

For us.

The main goal here however is to have a single generic number conversion
API between all of the String classes.
2023-12-23 20:41:07 +01:00
Nico Weber
80359517bd LibGfx: Do not use double negation in TIFFGenerator.py
No behavior change.
2023-12-23 12:25:08 -05:00
Lucas CHOLLET
2cfca633ca LibGfx/TIFF: Add support for images with UnassociatedAlpha
UnassociatedAlpha is the one used by GIMP when generating TIFF images
with transparency. Support is added for Grayscale and RGB images as it's
the two that we support right now but managing transparency should be
really straightforward for other types as well.
2023-12-22 08:08:47 +00:00
Lucas CHOLLET
796ece7b35 LibGfx/TIFF: Read the ExtraSamples tag 2023-12-22 08:08:47 +00:00
Nicolas Ramz
6ccdb1dc72 LibGfx/ILBMLoader: Add support for 24bit files 2023-12-21 09:19:30 +00:00
Nicolas Ramz
caa13d3960 LibGfx/ILBMLoader: Stop the decoding loop when plane buffer is full
This allows decoding files (eg. 24bit) that may have been badly encoded.
2023-12-21 09:19:30 +00:00
Lucas CHOLLET
b0e5aadf1a LibGfx/TIFF: Remove an unneeded parameter
This should have been done in f00e9540.
2023-12-20 12:19:30 +01:00
Lucas CHOLLET
caf9f00456 LibGfx/TIFF: Skip channels that we are unable to interpret
As per the specification, TIFF readers should gracefully skip samples
that they are not able to interpret.

This patch allow us to read `strike.tif` from the libtiff test suite as
an RGB image.
2023-12-20 12:19:30 +01:00
Lucas CHOLLET
a443d2955a LibGfx/TIFF: Don't use SamplesPerPixel to infer the "type" of image
The number of samples is not a good measure to deduce the type of image
we are decoding. As per the TIFF spec, the PhotometricInterpretation tag
is required and we should use that instead.
2023-12-20 12:19:30 +01:00
MacDue
d327104910 LibGfx: Add Path::place_text_along(text, font)
This method returns a new path with the input text placed along the edge
of the original path.
2023-12-19 21:29:03 +01:00
MacDue
8713968165 LibGfx: Preserve path order while splitting cubic/quadratic beziers
This changes the splitting to use a stack, which ensures the resulting
line segments follow the path in order. This will be important for SVG
`<textPath>`s which place text along a path.
2023-12-19 21:29:03 +01:00
Lucas CHOLLET
64912d4d02 LibGfx/TIFF: Add support for images with CCITT3 1D compression
This compression (tag Compression=2) is not very popular on its own, but
a base to implement CCITT3 2D and CCITT4 compressions.

As the format has no real benefits, it is quite hard to find an app that
accepts tho encode that for you. So I used the following program that
calls `libtiff` directly:
```cpp
#include <vector>
#include <cstdlib>
#include <iostream>

#include <tiffio.h>

// An array containing 0 and 1 of length width * height.
extern std::vector<uint8_t> array;
int main() {
    // From: https://stackoverflow.com/a/34257789

    TIFF *image = TIFFOpen("input.tif", "w");
    int const width = 400;
    int const height = 300;
    TIFFSetField(image, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(image, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 0);
    TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_CCITTRLE);

    TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 1);
    TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1);

    std::vector<uint8_t> scan_line(width / 8 + 8, 0);
    int count = 0;
    for (int i = 0; i < height; i++) {
        std::fill(scan_line.begin(), scan_line.end(), 0);
        for (int x = 0; x < width; ++x) {
            uint8_t eight_pixels = scan_line.at(x / 8);
            eight_pixels = eight_pixels << 1;
            eight_pixels |= !array.at(i * width + x);
            scan_line.at(x / 8) = eight_pixels;
        }
        int bytes = int(width / 8.0 + 0.5);
        if (TIFFWriteScanline(image, scan_line.data(), i, bytes) != 1)
            std::cerr << "Something went wrong\n";
    }

    TIFFClose(image);
}
```
2023-12-19 21:01:24 +01:00
Lucas CHOLLET
7266d8c35d LibGfx/TIFF: Correctly upscale samples with a resolution lower than 8
As pointed out by @nico, while doing a right-shift to downscale is fine,
a left-shift to upscale gives wrong results. As an example, imagine a 2-
bits value containing 3, left-shifting it would give 192 instead of 255.
2023-12-19 21:01:24 +01:00
Lucas CHOLLET
5b62d877f2 LibGfx/TIFF: Parse more common tags
These tags are either part of the baseline specification or included by
default by GIMP when exporting TIFF files. Note that we don't add
support for them in the decoder yet. This commit only allows us to parse
the metadata and display it gracefully.
2023-12-18 07:14:11 +01:00
Ali Mohammad Pur
5e1499d104 Everywhere: Rename {Deprecated => Byte}String
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).

This commit is auto-generated:
  $ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
    Meta Ports Ladybird Tests Kernel)
  $ perl -pie 's/\bDeprecatedString\b/ByteString/g;
    s/deprecated_string/byte_string/g' $xs
  $ clang-format --style=file -i \
    $(git diff --name-only | grep \.cpp\|\.h)
  $ gn format $(git ls-files '*.gn' '*.gni')
2023-12-17 18:25:10 +03:30
Nicolas Ramz
cd6c7f3fc4 LibGfx/ILBMLoader: Add support for PC DeluxePaint files 2023-12-13 10:39:13 +00:00
Aliaksandr Kalenik
df57d7ca68 LibGfx+LibWeb: Update for_each_glyph_position to use font cascade list
This change updates function that builds list of glyphs to use font
cascade list to find font for each code point.
2023-12-10 17:32:04 +01:00
Aliaksandr Kalenik
2cb0039a13 LibGfx+LibWeb: Produce font cascade list in CSS font matching algorithm
According to the CSS font matching algorithm specification, it is
supposed to be executed for each glyph instead of each text run, as is
currently done. This change partially implements this by having the
font matching algorithm produce a list of fonts against which each
glyph will be tested to find its suitable font.

Now, it becomes possible to have per-glyph fallback fonts: if the
needed glyph is not present in a font, we can check the subsequent
fonts in the list.
2023-12-10 17:32:04 +01:00
Aliaksandr Kalenik
f50bf00814 LibWeb+LibGfx: Move UnicodeRange from LibWeb to LibGfx
In upcoming changes UnicodeRange is going to be used in LibGfx in
a class that represents font cascade list.
2023-12-10 17:32:04 +01:00
Aliaksandr Kalenik
0d03257e69 LibGfx+LibAccelGfx+LibWeb: Use RefPtr for font in DrawGlyphOrEmoji 2023-12-10 17:32:04 +01:00
Kyle Pereira
649f1df771 LibGfx: Add RepeatingBitmapPaintStyle and OffsetPaintStyle
RepeatingBitmapPaintStyle tiles a bitmap passed on passed in parameters
and paints according to that.

OffsetPaintStyle offsets an existing paint style and paints with that.

These two will be useful in the PDF renderer.
2023-12-10 16:44:24 +01:00
Lucas CHOLLET
3ae29fdeec LibGfx/TIFF: Support WhiteIsZero parameter for grayscale images
PhotometricInterpretation::WhiteIsZero is used to inverse black and
white on bilevel and grayscale images.
2023-12-10 09:45:30 +01:00
Lucas CHOLLET
64d7e386d2 LibGfx/TIFF: Parse the PhotometricInterpretation tag 2023-12-10 09:45:30 +01:00
Lucas CHOLLET
234d084876 LibGfx/TIFF: Add support for bit-depth up to 32 bits per sample
This makes us support every "minisblack" and "rgb-contig" images from
the depth folder of libtiff's test suite:
https://libtiff.gitlab.io/libtiff/images.html
2023-12-09 21:47:33 +01:00