* Use 2024 style edition
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Reformat all code
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Instead of keeping a per-FontGroup cache of the previously used fallback
font, cache this value in the caller of `FontGroup::find_by_codepoint`.
The problem with caching this value in the `FontGroup` is that it can
make one layout different from the next.
Still, it is important to cache the value somewhere so that, for
instance, Chinese character don't have to continuously walk through the
entire fallback list when laying out. The heuristic here is to try to
last used font first if the `Script`s match. At the very least this
should make one layout consistent with the next.
Fixes#35704.
Fixes#35697.
Fixes#35689.
Fixes#35679.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Instead of a blocking a layout thread on the generation of WebRender
`FontKey`s and `FontInstanceKey`s, generate the keys ahead of time and
send the font data to WebRender asynchronously. This has the benefit of
allowing use of the font much more quickly in layout, though blocking
display list sending itself on the font data upload.
In order to make this work for web fonts, `FontContext` now asks the
`SystemFontService` for a `FontKey`s and `FontInstanceKey`s for new web
fonts. This should happen much more quickly as the `SystemFontService`
is only blocking in order to load system fonts into memory now. In
practice this still drops layout thread blocking to fractions of a
millisecond instead of multiple milliseconds as before.
In addition, ensure that we don't send font data or generate keys for
fonts that are used in layout but never added to display lists. This
should help to reduce memory usage and increase performance.
Performance of this change was verified by putting a microbenchmark
around `FontContext::create_font` which is what triggered font key
generation.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This is done by no longer forwarding compositor-bound messages through
SystemFontService and making `FontContext` non-generic:
- Messages from the `FontContext` to the `Compositor` no longer need to be
forwarded through the `SystemFontService`. Instead send these messages
directly through the script IPC channel to the `Compositor`.
- Instead of adding a mock `SystemFontServiceProxy`, simply implement a
mock `SystemFontService` on the other side of an IPC channel in the
`font_context` unit test. This allows making `FontContext`
non-generic, greatly simplifying the code. The extra complexity moves
into the unit test.
These changes necessitate adding a new kind of `FontIdentifier`,
`FontIdentifier::Mock` due to the fact that local fonts have
platform-specific identifiers. This avoids having to pretend like the
system font service can have web fonts -- which was always a bit of a
hack.
These two changes are combined into one PR because they both require
extensive and similar chages in the font_context unit test which
dependended on the details of both of them.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This crate only takes care of fonts now as graphics related things are
split into other crates. In addition, this exposes data structures at
the top of the crate, hiding the implementation details and making it
simpler to import them.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Remove the `ucd` dependency which has not been updated in 8 years. In
addition, replace it with a generated UnicodeBlock enum which reflects
the modern Unicode standard. This is generated via a Python script which
is included in the repository. The generation is not part of the build
process, because the Unicode database is hosted on the web and it does
not change the frequently.
This is done instead of bringing in the more up-to-date `unicode_blocks`
dependency. `unicode_blocks` defines each block as constant, which means
that they cannot be used in match statements -- which we do in Servo.
Co-authored-by: Lauryn Menard <lauryn.menard@gmail.com>
This change adds support for `white-space-collapse: break-spaces` and
adds initial parsing support for `overflow-wrap` and `word-break`. The
later two properties are not fully supported, only in their interaction
with `break-spaces`. This is a preliminary change preparing to implement
them.
In addition, `break_and_shape` is now forked and added to Layout 2020.
This function is going to change a lot soon and forking is preparation
for this. More code that is only used by Layout 2013 is moved from `gfx`
to that crate.
Co-authored-by: Rakhi Sharma <atbrakhi@igalia.com>
- Better detect situations where emoji is necessary by looking ahead one
character while laying out. This allow processing Unicode presentation
selectors. When detecting emoji, put emoji fonts at the front of
fallback lists for all platforms.
This enables monochrome emoji on Windows. Full-color emoji on Windows
probably needs full support for processing the COLR table and drawing
separate glyph color layers.
- Improve the font fallback list on FreeType platforms. Ideally, Servo
would be able to look through the entire font list to find the best
font for a certain character, but until that time we can make sure the
font list contains the "Noto Sans" fonts which cover most situations.
Fixes#31664.
Fixes#12944.
This allows sharing font templates, fonts, and platform fonts across
layout threads. It's the first step toward storing web fonts in the
layout versus the shared `FontCacheThread`. Now fonts and font groups
have some locking (especially on FreeType), which will probably affect
performance. On the other hand, we measured memory usage and this saves
roughly 40 megabytes of memory when loading servo.org based on data from
the memory profiler.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Bumps Stylo to servo/stylo#37
`white-space` is split into `white-space-collapse` and `text-wrap-mode`:
| white-space | white-space-collapse | text-wrap-mode |
| ----------- | -------------------- | -------------- |
| normal | collapse | wrap |
| nowrap | collapse | nowrap |
| pre-wrap | preserve | wrap |
| pre | preserve | nowrap |
| pre-line | preserve-breaks | wrap |
| - | preserve-breaks | nowrap |
Note this introduces a combination that wasn't previously possible,
but I think the existing logic can handle it well enough.
The old `allow_wrap()` is replaced by checking whether `text-wrap-mode`
is set to `wrap`.
The old `preserve_newlines()` is replaced by checking whether
`white-space-collapse` is *not* set to `collapse`.
The old `preserve_spaces()` is replaced by checking whether
`white-space-collapse` is set to `preserve`.
Instead of using a simple `Atom` to identify a local font, use a data
structure. This allows us to carry more information necessary to
identify a local font (such as a path on MacOS). We need this for the
new version of WebRender, as fonts on MacOS now require a path.
This has a lot of benefits:
1. We can avoid loading fonts without paths on MacOS, which should
avoid a lot of problems with flakiness and ensure we always load the
same font for a given identifier.
2. This clarifies the difference between web fonts and local fonts,
though there is more work to do here.
3. This avoid a *lot* of font shenanigans, such as trying to work
backwards from the name of the font to the path of the font we
actually matched. In general, we can remove a lot of code trying to
accomplish these shenanigans.
4. Getting the font bytes always returns an `Arc` now avoiding an extra
full font copy in the case of Canvas.
Synthetic small caps is supported by the font subsystem, but this is
disabled in Layout 2020. We can turn this on to bring support to parity
with the old layout system.
In addition to turning on synthetic small-caps this change also improves
the way that they work. Before, synthetic small caps meant that every
character was a small version of capitalized character. After this
change, capital letters are larger than small caps versions of small
letters -- matching other browsers and the common expectation of how
small caps works.
It's not possible anymore, in the presence of min() / max(), to split a
<length-percentage> value into a <length> and a <percentage> component.
Tweak word_spacing to do what Gecko does (resolving it in advance).
We can encounter control characters here, for example when processing a
<pre> element which contains newlines. Control characters are inherently
non-printing, therefore if we try to call find_by_codepoint for these
characters we will end up triggering an unnecessary font fallback
search.
Unfortunately, this required quite a bit of changes to the non-test
code. That's because FontContext depends on a FontCacheThread, which in
turn depends on a CoreResourceThread and therefore lots of other data
structures.
It seemed like it would be very difficult to instantiate a FontContext
as it was, and even if we could it seems like overkill to have all these
data structures present for a relatively focused test.
Therefore, I created a FontSource trait which represents the interface
which FontContext uses to talk to FontCacheThread. FontCacheThread then
implements FontSource. Then, in the test, we can create a dummy
implementation of FontSource rather than using FontCacheThread.
This actually has the advantage that we can make our dummy
implementation behave in certain specific way which are useful for
testing, for example it can count the number of times
find_font_template() is called, which helps us verify that
caching/lazy-loading is working as intended.
This is a step towards fixing #17267. To fix that, we need to be able to
try various different fallback fonts in turn, which would become
unweildy with the prior eager-loading strategy.
Prior to this change, FontGroup loaded up all Font instances, including
the fallback font, before any of them were checked for the presence of
the glyphs we're trying to render.
So for the following CSS:
font-family: Helvetica, Arial;
The FontGroup would contain a Font instance for Helvetica, and a Font
instance for Arial, and a Font instance for the fallback font.
It may be that Helvetica contains glyphs for every character in the
document, and therefore Arial and the fallback font are not needed at
all.
This change makes the strategy lazy, so that we'll only create a Font
for Arial if we cannot find a glyph within Helvetica. I've also
substantially refactored the existing code in the process and added
some documentation along the way.