Commit Graph

245 Commits

Author SHA1 Message Date
Timothy Flynn
464d7d5858 LibGfx+LibWeb: Allow inexact size lookups when requesting scaled fonts
For bitmap fonts, we will often not have an exact match for requested
sizes. Return the closest match instead of a nullptr.

LibWeb is currently the only user of this API. If it needs to be
configurable in the future to only allow exact matches, we can add a
parameter or another method at that time.
2024-05-06 23:26:42 +00:00
Timothy Flynn
ec492a1a08 Everywhere: Run clang-format
The following command was used to clang-format these files:

    clang-format-18 -i $(find . \
        -not \( -path "./\.*" -prune \) \
        -not \( -path "./Base/*" -prune \) \
        -not \( -path "./Build/*" -prune \) \
        -not \( -path "./Toolchain/*" -prune \) \
        -not \( -path "./Ports/*" -prune \) \
        -type f -name "*.cpp" -o -name "*.mm" -o -name "*.h")

There are a couple of weird cases where clang-format now thinks that a
pointer access in an initializer list, e.g. `m_member(ptr->foo)`, is a
lambda return statement, and it puts spaces around the `->`.
2024-04-24 16:50:01 -04:00
Matthew Olsson
ff00d21d58 Everywhere: Mark a bunch of function parameters as NOESCAPE
This fixes the relevant warnings when running LibJSGCVerifier. Note that
the analysis is only performed over LibJS-adjacent code, but could be
performed over the entire codebase. That will have to wait for a future
commit.
2024-04-09 09:10:44 +02:00
Timothy Flynn
683c08744a Userland: Avoid some conversions from rvalue strings to StringView
These are all actually fine, there is no UAF here. But once e.g.
`ByteString::view() &&` is deleted, these instances won't compile.
2024-04-04 11:23:21 +02:00
Andreas Kling
f48024c2d1 LibGfx/OpenType: Make glyph_width() only fetch the glyph advance
Instead of fetching a generic set of metrics for each glyph, only fetch
the advance when that's all we need.

This is extremely hot in LibWeb text layout, where it makes a nice dent.
2024-03-25 12:39:23 +01:00
MacDue
8057542dea LibGfx: Simplify path storage and tidy up APIs
Rather than make path segments virtual and refcounted let's store
`Gfx::Path`s as a list of `FloatPoints` and a separate list of commands.

This reduces the size of paths, for example, a `MoveTo` goes from 24
bytes to 9 bytes (one point + a single byte command), and removes a
layer of indirection when accessing segments. A nice little bonus is
transforming a path can now be done by applying the transform to all
points in the path (without looking at the commands).

Alongside this there's been a few minor API changes:

- `path.segments()` has been removed
  * All current uses could be replaced by a new `path.is_empty()` API
  * There's also now an iterator for looping over `Gfx::Path` segments
- `path.add_path(other_path)` has been removed
  * This was a duplicate of `path.append_path(other_path)`
- `path.ensure_subpath(point)` has been removed
  * Had one use and is equivalent to an `is_empty()` check + `move_to()`
- `path.close()` and `path.close_all_subpaths()` assume an implicit
  `moveto 0,0` if there's no `moveto` at the start of a path (for
  consistency with `path.segmentize_path()`).

Only the last point could change behaviour (though in LibWeb/SVGs all
paths start with a `moveto` as per the spec, it's only possible to
construct a path without a starting `moveto` via LibGfx APIs).
2024-03-18 07:09:37 +01:00
Nico Weber
7d9294b9a4 LibGfx: Add ScaledFont::scaled_with_size()
It's like ScaledFont::with_size(), except that it guarantees that the
result is non-null and ScaledFont. (Smart pointers don't allow
covariant return types, else we could just narrow down the return
type of with_size() while still overriding the base method.)

No behavior change.
2024-03-01 17:56:59 +01:00
Nico Weber
41e0a0f0aa LibGfx/OpenType: Add named constants for header tags
...together with spec comments.

No behavior change.
2024-02-28 16:00:07 -05:00
Nico Weber
86203974f5 LibGfx/OpenType: Extract read_tag() function 2024-02-28 16:00:07 -05:00
Nico Weber
93038f6f24 LibGfx/OpenType: Extract for_each_table_record() helper
Separates table record iteration from doing something with the table
records, which is arguably easier to read.

No behavior change.
2024-02-28 16:00:07 -05:00
Nico Weber
75e5ed7aea LibGfx: Survive empty simple glyphs with 0 contours
Some fonts have empty slices for glyphs with 0 contours, even though
the spec requires them to store a 0 for instructionLength as far as
I can tell. But let's not assert on invalid fonts like this, but instead
handle them gracefully.

Supersedes #22570.

Fixes the last two crashes on my 1000-file test set: 0000246.pdf and
0000431.pdf.
2024-02-27 07:01:05 +01:00
Nico Weber
78b3c552c2 LibGfx: Tweak semantics of some SkipTables enum values
It turns out that hmtx and OS/2 table values _are_ used when
rendering OpenType for PDFs: hmtx is used for the left-side bearing
value (which is read in `Painter::draw_glyph()`), and OS/2 is used
for the ascender, which Type0's CIDFontType2::draw_glyph()
and TrueTypeFont::draw_glyph() read.

So instead of not trying to read these tables, instead try to read
them but tolerate them failing to read and ignore them then.

Follow-up to #23276.

(I've seen weird glyph positioning from not reading the hmtx table.
I haven't seen any problems caused by not reading the OS/2 table yet,
but since the PDF code does use the ascender value, let's read that
too.)
2024-02-21 19:52:03 +01:00
Nico Weber
e8133c8297 LibGfx/OpenType: Undo minor deletion in #23225
Check if we have a cmap before dereferencing it again.

Fixes a crash on page 8 of 0000188.pdf now that the font no
longer fails to load to due to a missing name table.

Looks like this is a Type2 truetype font, where we don't provide
an external cmap. How this font is supposed to work without a cmap
I don't know -- but for now, we no longer crash on it, and draw
some of the text with the previous font (which happens to work
fine in this particular case).
2024-02-21 13:38:33 +01:00
Nico Weber
08381b20e0 LibGfx/OpenType: Allow zero-sized table entries
Kind of reverts #21675, but #21744 made that better

4 of my 1000 test PDFs complained "Invalid table offset or length in
font" before.

For example, in 0000203.pdf, these tags had length 0: 'cvt ', 'fpgm',
'prep', 'name', 'OS/2'. (Generally it's tables that aren't needed
for rendering PDFs, and the PDF writer figured it's easier to zero
out these tables instead of omitting them altogether for some reason.)

Increases number of PDFs that render without diagnostics from
765 to 767.
2024-02-21 13:38:33 +01:00
Nico Weber
cade76d240 LibPDF+LibGfx: Do not try to read "OS/2" table for PDFs
It is sometimes truncated in fonts embedded in PDFs, and the data
is not needed to render PDFs. 2 of my 1000 test PDFs used to
complain "Could not load OS2 v1: Not enough data" and 1
"Could not load OS2 v2: Not enough data" before.

Increases number of PDFs that render without diagnostics from
764 to 765 (and decreases the number of distinct error messages
from 27 to 25).
2024-02-21 13:38:33 +01:00
Nico Weber
0dee94ef40 LibPDF+LibGfx: Do not try to read "hmtx" table for PDFs
It is sometimes truncated in fonts embedded in PDFs, and the data
is not needed to render PDFs. 26 of my 1000 test files complained
"Could not load Hmtx: Not enough data" before.

Increases number of PDFs that render without diagnostics from
743 to 764.
2024-02-21 13:38:33 +01:00
Nico Weber
5efe80af7f LibPDF+LibGfx: Do not try to read "name" table for PDFs
It is often missing in fonts embedded in PDFs. 75 of my 1000 test
files complained "Font is missing Name" when trying to read fonts
before.

Increases number of PDFs that render without diagnostics from
682 to 743.
2024-02-21 13:38:33 +01:00
Nico Weber
41eca52b50 LibGfx/OpenType: Tweak Font::try_load_from_externally_owned_memory()
It now takes an Options object instead of passing several default
parameters.

No behavior change.
2024-02-21 13:38:33 +01:00
Nico Weber
76a439124d LibGfx/OpenType: Make it possible to provide an external cmap
If this is passed in, we don't use the cmap table from the font,
but use the external lookup object instead.

This conveniently happens to create a place where we can put all the
Cmap configuration logic that was a bit spread out before.

No behavior change yet.
2024-02-17 16:08:48 +01:00
Nico Weber
17b22250b6 LibGfx/OpenType: Replace a magic number with a calculation
Makes this code look like the corresponding code in the ScaledFont ctor.

Similar to the last commit on #20084.

No behavior change.
2024-02-15 22:53:24 -05:00
Nico Weber
073e2bffcb LibGfx: Move POINTS_PER_INCH, DEFAULT_DPI to VectorFont.h
...so we can use it in OpenType/Font.cpp.

No behavior change.
2024-02-15 22:53:24 -05:00
Nico Weber
93ee01041f LibGfx/OpenType: Validate we can read the active cmap subtable format
We now reject fonts where the active cmap subtable is in a format
we can't read yet, instead of silently drawing squares for all glyphs.

This doesn't fire at all for my 1000-file PDF test set, but seems
like a good thing to check.

(Instead of duplicating the switch, I first tried making a
glyph_id_for_code_point_or_else() that returns ErrorOr<u32> and then
make both glyph_id_for_code_point() and validate_format_can_be_read()
call that, but I liked less how that worked out -- felt too clever.)
2024-02-08 13:48:33 +00:00
Nico Weber
be8b5b794f LibGfx/OpenType: Error on fonts without a supported subtable
This would've saved me some debugging on #23103.

We now return an error instead of a font that draws squares for all
characters. That seems preferable since it makes these cases easy to
find. This fires for three files in my 1000-file PDF test set, so it's
not exceedingly common (...but I wasn't aware that three files were
rendering boxes for this reason, and now I am and can just make them
work in the future).
2024-02-08 13:48:33 +00:00
Nico Weber
d3c94d8436 LibGfx: Add a comment to Font::try_load_from_offset()
See #17189 -- this confused me for a bit.
2024-02-07 08:31:18 +00:00
Nico Weber
21ffb118af LibGfx/OpenType: Support cmaps with format Unicode
Some fonts only contain unicode tables. This makes them work.
2024-02-07 08:31:03 +00:00
Sam Atkins
3df3a85235 LibGfx+Userland: Move FontWeight enum into its own file
FontDatabase.h with its includes add up to quite a lot of code. In the
next commit, compiled GML files are going to need to access the
FontWeight enum, so let's allow them to do that without pulling in lots
of other things.

Also, change users to include FontWeight.h instead of FontDatabase.h
where appropriate.
2024-01-21 09:32:10 -05:00
Andreas Kling
d26ad8450f LibGfx/OpenType: Read the correct number of pairs from kern table
We were trying to read exactly 5 pairs for some reason, instead of the
number specified by the format 0 header.

Fixing this makes "OpenSans Condensed" load on my machine.
2024-01-06 23:22:52 +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
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
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
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
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
8634820e73 LibGfx: Use east-mutable style in OpenType font class
No intended behavior change.
2023-12-09 19:05:30 +01:00
Aliaksandr Kalenik
7ae229ead7 LibGfx: Cache family, width, weight, and slope for OpenType fonts
These properties could be cached in the font object once they are
decoded from the table for the first time to make subsequent access
faster.

This change makes `Node::scaled_font()` in LibWeb go down from 6% to
1.5% in my profiles because building a font cache key is now a lot
cheaper.
2023-12-09 19:05:30 +01:00
Idan Horowitz
e1b438bb1a LibGfx: Actually ensure Cmap subtable offset is within expected range
Our previous check was not sufficient, since it merely checked the
first byte of the EncodingRecord offset is within range, while the
actual read is 4-byte wide.

Fixes ossfuzz-64165.
2023-12-02 11:22:48 +01:00
Sam Atkins
54d0aafff0 LibGfx: Use FourCC as OpenType::Tag type
The one deviation from the spec here is to use this in the WOFF
TableDirectoryEntry's tag field. However, *not* making that a Tag made
a lot of things more complicated than they need to be.
2023-11-24 08:42:46 +01:00
Tim Ledbetter
cdfe893717 LibGfx/OpenType: Ensure Cmap subtable offset is within expected range 2023-11-11 22:20:17 +01:00
Tim Ledbetter
1eae02a018 LibGfx/OpenType: Add validation for OpenType head table values
Previously, a crash would occur if a font file had an invalid
IndexToLocFormat value.
2023-11-11 08:51:02 +01:00
Shane Murphy
0e05614710 LibGfx: Improve tie-breaking in Typeface::get_font
Add two new members to Font::AllowInexactMatch: Larger and Smaller.
This allows callers of FontDatabase::get to specify if they want to
prefer a larger or smaller font in the event of a tie.
2023-11-09 16:09:18 +01:00
Tim Schumacher
e9dda2a5f8 AK: Provide a default set of Traits for const types 2023-11-09 10:05:51 -05:00
Tim Schumacher
a2f60911fe AK: Rename GenericTraits to DefaultTraits
This feels like a more fitting name for something that provides the
default values for Traits.
2023-11-09 10:05:51 -05:00
Timothy Flynn
a098b6e371 LibGfx: Ensure const-correctness when reading from the GPOS byte stream
Otherwise, the call to `read_in_place` gives the following error:

    Tried to obtain a non-const span from a read-only FixedMemoryStream
2023-11-08 22:26:36 +00:00
Sam Atkins
21f2f09df4 LibGfx: Remove bit casting in OpenType CBDT table after construction 2023-11-08 09:34:09 +01:00
Sam Atkins
4e944e676b LibGfx: Use to_underlying() to compare ValueFormat enum values
This means we no longer do a bitwise and of a u16 and i16, which feels a
little sketchy.
2023-11-08 09:34:09 +01:00
Sam Atkins
74e5fff77a LibGfx: Reduce bit casting in OpenType GPOS table after construction
Read the basic lists as spans, and use those when looking for kerning.

Kerning lookup still does bit-casting for now. As for CBLC, the data is
a bit complicated.
2023-11-08 09:34:09 +01:00
Sam Atkins
2a4d7a193e LibGfx: Define and use OpenType data types for struct definitions
A few closely-related changes:
- Move our definitions of the OpenType spec's "data types" into their
  own header file.
- Add definitions for the integer types there too, for completeness.
  (Plus Uint16 matches the spec term, and is less verbose than
  BigEndian<u16>.)
- Include Traits for the non-BigEndian types so that we can read them
  from Streams. (BigEndian<integer-type> already has this.)
- Use the integer types in our struct definitions.

As a bonus, this fixes a bug in Hmtx, which read the left-side bearings
as i16 instead of BigEndian<i16>.
2023-11-08 09:34:09 +01:00
Sam Atkins
a28f035d76 LibGfx: Reduce bit casting in OpenType CBLC table after construction
The subtables are still read at use-time for now. I'm sure we could
build some kind of wrapper structures for them though.
2023-11-08 09:34:09 +01:00
Sam Atkins
3c7d654182 LibGfx: Remove bit casting in OpenType Kern table after construction
Do more checks at load time, including categorizing the subtables and
producing our own directory of them.

The format for Kern is a little complicated, so use a Stream instead of
manual offsets.
2023-11-08 09:34:09 +01:00
Sam Atkins
89b35c6dc8 LibGfx: Remove bit casting in OpenType Name table after construction
Store the name records as a span, and a separate bytes span for the
string data.
2023-11-08 09:34:09 +01:00
Sam Atkins
fe2e1a0282 LibGfx: Remove bit casting in OpenType OS2 table after construction 2023-11-08 09:34:09 +01:00