Skip to content

Commit 5ba8206

Browse files
committed
Skia: Use parley for text layout
cc #9559
1 parent 9c20bea commit 5ba8206

File tree

5 files changed

+209
-691
lines changed

5 files changed

+209
-691
lines changed

internal/renderers/skia/Cargo.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ unstable-wgpu-26 = [
3535
default = []
3636

3737
[dependencies]
38-
i-slint-core = { workspace = true, features = ["default", "box-shadow-cache"] }
38+
i-slint-core = { workspace = true, features = ["default", "box-shadow-cache", "shared-parley"] }
3939
i-slint-core-macros = { workspace = true, features = ["default"] }
4040
i-slint-common = { workspace = true, features = ["default"] }
4141

@@ -49,7 +49,7 @@ pin-weak = "1"
4949
scoped-tls-hkt = "0.1"
5050
raw-window-handle = { version = "0.6", features = ["std"] }
5151

52-
skia-safe = { version = "0.88", features = ["textlayout", "gl"] }
52+
skia-safe = { version = "0.88", features = ["gl"] }
5353
glow = { workspace = true }
5454
unicode-segmentation = { workspace = true }
5555

@@ -89,10 +89,17 @@ metal = { version = "0.31", optional = true }
8989
foreign-types = { version = "0.5.0", optional = true }
9090
wgpu-26 = { workspace = true, optional = true, features = ["metal"] }
9191

92+
read-fonts = { version = "0.35" }
93+
write-fonts = { version = "0.43" }
94+
9295
[target.'cfg(not(any(target_vendor = "apple", target_family = "windows")))'.dependencies]
9396
skia-safe = { version = "0.88", features = ["gl", "vulkan"] }
9497
wgpu-26 = { workspace = true, optional = true, features = ["vulkan"] }
9598

99+
[target.'cfg(any(target_os = "ios", target_os="windows", target_os="android"))'.dependencies]
100+
# Text layout is enabled here just so that we can make use of the pre-built Skia libraries.
101+
skia-safe = { version = "0.88", features = ["textlayout"] }
102+
96103
[build-dependencies]
97104
cfg_aliases = { workspace = true }
98105

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright © SixtyFPS GmbH <[email protected]>
2+
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3+
4+
use i_slint_core::textlayout::sharedparley::parley;
5+
use std::cell::RefCell;
6+
use std::collections::HashMap;
7+
8+
pub struct FontCache {
9+
font_mgr: skia_safe::FontMgr,
10+
fonts: HashMap<(u64, u32), Option<skia_safe::Typeface>>,
11+
}
12+
13+
impl Default for FontCache {
14+
fn default() -> Self {
15+
Self { font_mgr: skia_safe::FontMgr::new(), fonts: Default::default() }
16+
}
17+
}
18+
19+
impl FontCache {
20+
pub fn font(&mut self, font: &parley::Font) -> Option<skia_safe::Typeface> {
21+
self.fonts
22+
.entry((font.data.id(), font.index))
23+
.or_insert_with(|| {
24+
let typeface = self.font_mgr.new_from_data(
25+
font.data.as_ref(),
26+
if font.index > 0 { Some(font.index as _) } else { None },
27+
);
28+
29+
// Due to https://issues.skia.org/issues/310510989, fonts from true type collections
30+
// with an index > 0 fail to load on macOS. As a workaround, we manually extract the font from the
31+
// collection and load it as a single font.
32+
#[cfg(target_vendor = "apple")]
33+
if font.index > 0 && typeface.is_none() {
34+
{
35+
if let Some(typeface) = read_fonts::CollectionRef::new(font.data.as_ref())
36+
.ok()
37+
.and_then(|ttc| ttc.get(font.index).ok())
38+
.map(|ttf| {
39+
write_fonts::FontBuilder::new().copy_missing_tables(ttf).build()
40+
})
41+
.and_then(|new_ttf| self.font_mgr.new_from_data(&new_ttf, None))
42+
{
43+
return Some(typeface);
44+
}
45+
}
46+
}
47+
48+
typeface
49+
})
50+
.clone()
51+
}
52+
}
53+
54+
thread_local! {
55+
pub static FONT_CACHE: RefCell<FontCache> = RefCell::new(Default::default())
56+
}

0 commit comments

Comments
 (0)