mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
Merge pull request #2300 from zed-industries/ligatures
Allow customization of OpenType features
This commit is contained in:
commit
d8758658e3
49 changed files with 750 additions and 59 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -518,6 +518,7 @@ dependencies = [
|
|||
"menu",
|
||||
"project",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smol",
|
||||
|
@ -1097,6 +1098,7 @@ dependencies = [
|
|||
"ipc-channel",
|
||||
"plist",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1119,6 +1121,7 @@ dependencies = [
|
|||
"rand 0.8.5",
|
||||
"rpc",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"smol",
|
||||
"sum_tree",
|
||||
|
@ -1228,6 +1231,7 @@ dependencies = [
|
|||
"sea-orm",
|
||||
"sea-query",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"sha-1 0.9.8",
|
||||
|
@ -1269,6 +1273,7 @@ dependencies = [
|
|||
"postage",
|
||||
"project",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"theme",
|
||||
"util",
|
||||
|
@ -1739,6 +1744,7 @@ dependencies = [
|
|||
"log",
|
||||
"parking_lot 0.11.2",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"smol",
|
||||
"sqlez",
|
||||
"sqlez_macros",
|
||||
|
@ -1947,6 +1953,7 @@ dependencies = [
|
|||
"rand 0.8.5",
|
||||
"rpc",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"smallvec",
|
||||
"smol",
|
||||
|
@ -2100,6 +2107,7 @@ dependencies = [
|
|||
"project",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"sysinfo",
|
||||
"theme",
|
||||
|
@ -2296,6 +2304,7 @@ dependencies = [
|
|||
"regex",
|
||||
"rope",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"tempfile",
|
||||
|
@ -2664,8 +2673,10 @@ dependencies = [
|
|||
"postage",
|
||||
"rand 0.8.5",
|
||||
"resvg",
|
||||
"schemars",
|
||||
"seahash",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
"smallvec",
|
||||
|
@ -3275,6 +3286,7 @@ dependencies = [
|
|||
"regex",
|
||||
"rpc",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"similar",
|
||||
|
@ -3470,6 +3482,7 @@ dependencies = [
|
|||
"parking_lot 0.11.2",
|
||||
"postage",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha2 0.10.6",
|
||||
"simplelog",
|
||||
|
@ -3490,6 +3503,7 @@ dependencies = [
|
|||
"prost-types 0.8.0",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"sha2 0.10.6",
|
||||
]
|
||||
|
||||
|
@ -3530,6 +3544,7 @@ dependencies = [
|
|||
"parking_lot 0.11.2",
|
||||
"postage",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"unindent",
|
||||
|
@ -4449,6 +4464,7 @@ dependencies = [
|
|||
"bincode",
|
||||
"plugin_macros",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4459,6 +4475,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -4470,6 +4487,7 @@ dependencies = [
|
|||
"bincode",
|
||||
"pollster",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"wasi-common",
|
||||
|
@ -4627,6 +4645,7 @@ dependencies = [
|
|||
"regex",
|
||||
"rpc",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"sha2 0.10.6",
|
||||
|
@ -5249,6 +5268,7 @@ dependencies = [
|
|||
"rand 0.8.5",
|
||||
"rsa",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"smol",
|
||||
"smol-timeout",
|
||||
"tempdir",
|
||||
|
@ -5672,6 +5692,7 @@ dependencies = [
|
|||
"postage",
|
||||
"project",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smallvec",
|
||||
|
@ -5860,6 +5881,7 @@ dependencies = [
|
|||
"postage",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"sqlez",
|
||||
|
@ -6480,6 +6502,7 @@ dependencies = [
|
|||
"procinfo",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"shellexpand",
|
||||
"smallvec",
|
||||
|
@ -6511,6 +6534,7 @@ dependencies = [
|
|||
"project",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"shellexpand",
|
||||
"smallvec",
|
||||
|
@ -6570,6 +6594,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"parking_lot 0.11.2",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"toml",
|
||||
|
@ -7563,6 +7588,7 @@ dependencies = [
|
|||
"project",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"tokio",
|
||||
|
@ -8346,6 +8372,7 @@ dependencies = [
|
|||
"postage",
|
||||
"project",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smallvec",
|
||||
|
@ -8472,6 +8499,7 @@ dependencies = [
|
|||
"rust-embed",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"settings",
|
||||
|
|
|
@ -68,6 +68,7 @@ resolver = "2"
|
|||
|
||||
[workspace.dependencies]
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
|
||||
rand = { version = "0.8" }
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
"theme": "One Dark",
|
||||
// The name of a font to use for rendering text in the editor
|
||||
"buffer_font_family": "Zed Mono",
|
||||
// The OpenType features to enable for text in the editor.
|
||||
"buffer_font_features": {
|
||||
// Disable ligatures:
|
||||
// "calt": false
|
||||
},
|
||||
// The default font size for text in the editor
|
||||
"buffer_font_size": 15,
|
||||
// The factor to grow the active pane by. Defaults to 1.0
|
||||
|
|
|
@ -23,6 +23,7 @@ isahc = "1.7"
|
|||
lazy_static = "1.4"
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
smol = "1.2.5"
|
||||
tempdir = "0.3.7"
|
||||
|
|
|
@ -18,6 +18,7 @@ clap = { version = "3.1", features = ["derive"] }
|
|||
dirs = "3.0"
|
||||
ipc-channel = "0.16"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.9"
|
||||
|
|
|
@ -35,7 +35,8 @@ time = { version = "0.3", features = ["serde", "serde-well-known"] }
|
|||
tiny_http = "0.8"
|
||||
uuid = { version = "1.1.2", features = ["v4"] }
|
||||
url = "2.2"
|
||||
serde = { version = "*", features = ["derive"] }
|
||||
serde = { version = "*", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
settings = { path = "../settings" }
|
||||
tempfile = "3"
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ scrypt = "0.7"
|
|||
sea-orm = { git = "https://github.com/zed-industries/sea-orm", rev = "18f4c691085712ad014a51792af75a9044bacee6", features = ["sqlx-postgres", "postgres-array", "runtime-tokio-rustls"] }
|
||||
sea-query = "0.27"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = "1.0"
|
||||
sha-1 = "0.9"
|
||||
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "postgres", "json", "time", "uuid", "any"] }
|
||||
|
|
|
@ -44,6 +44,7 @@ futures = "0.3"
|
|||
log = "0.4"
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
|
||||
[dev-dependencies]
|
||||
call = { path = "../call", features = ["test-support"] }
|
||||
|
|
|
@ -24,6 +24,7 @@ lazy_static = "1.4.0"
|
|||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
parking_lot = "0.11.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
smol = "1.2"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -54,6 +54,7 @@ parking_lot = "0.11"
|
|||
postage = { version = "0.4", features = ["futures-traits"] }
|
||||
rand = { version = "0.8.3", optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2"
|
||||
tree-sitter-rust = { version = "*", optional = true }
|
||||
|
|
|
@ -785,7 +785,9 @@ pub mod tests {
|
|||
let mut tab_size = rng.gen_range(1..=4);
|
||||
let buffer_start_excerpt_header_height = rng.gen_range(1..=5);
|
||||
let excerpt_header_height = rng.gen_range(1..=5);
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1042,7 +1044,9 @@ pub mod tests {
|
|||
|
||||
let font_cache = cx.font_cache();
|
||||
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1131,7 +1135,10 @@ pub mod tests {
|
|||
cx.set_global(Settings::test(cx));
|
||||
let text = sample_text(6, 6, 'a');
|
||||
let buffer = MultiBuffer::build_simple(&text, cx);
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
@ -1214,7 +1221,9 @@ pub mod tests {
|
|||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
|
||||
let font_cache = cx.font_cache();
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1302,7 +1311,9 @@ pub mod tests {
|
|||
|
||||
let font_cache = cx.font_cache();
|
||||
|
||||
let family_id = font_cache.load_family(&["Courier"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Courier"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1374,7 +1385,9 @@ pub mod tests {
|
|||
let buffer_snapshot = buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx));
|
||||
|
||||
let font_cache = cx.font_cache();
|
||||
let family_id = font_cache.load_family(&["Courier"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Courier"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1490,7 +1503,9 @@ pub mod tests {
|
|||
let text = "✅\t\tα\nβ\t\n🏀β\t\tγ";
|
||||
let buffer = MultiBuffer::build_simple(text, cx);
|
||||
let font_cache = cx.font_cache();
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
@ -1548,7 +1563,9 @@ pub mod tests {
|
|||
cx.set_global(Settings::test(cx));
|
||||
let buffer = MultiBuffer::build_simple("aaa\n\t\tbbb", cx);
|
||||
let font_cache = cx.font_cache();
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
|
|
@ -1015,7 +1015,10 @@ mod tests {
|
|||
fn test_basic_blocks(cx: &mut gpui::MutableAppContext) {
|
||||
cx.set_global(Settings::test(cx));
|
||||
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
@ -1185,7 +1188,10 @@ mod tests {
|
|||
fn test_blocks_on_wrapped_lines(cx: &mut gpui::MutableAppContext) {
|
||||
cx.set_global(Settings::test(cx));
|
||||
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
@ -1241,7 +1247,10 @@ mod tests {
|
|||
Some(rng.gen_range(0.0..=100.0))
|
||||
};
|
||||
let tab_size = 1.try_into().unwrap();
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
|
|
@ -1053,7 +1053,9 @@ mod tests {
|
|||
Some(rng.gen_range(0.0..=1000.0))
|
||||
};
|
||||
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
|
||||
let family_id = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
|
|
@ -587,7 +587,10 @@ mod tests {
|
|||
#[gpui::test]
|
||||
fn test_move_up_and_down_with_excerpts(cx: &mut gpui::MutableAppContext) {
|
||||
cx.set_global(Settings::test(cx));
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
|
|
@ -25,7 +25,10 @@ pub fn marked_display_snapshot(
|
|||
) -> (DisplaySnapshot, Vec<DisplayPoint>) {
|
||||
let (unmarked_text, markers) = marked_text_offsets(text);
|
||||
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let family_id = cx
|
||||
.font_cache()
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
|
|
|
@ -25,10 +25,11 @@ postage = { version = "0.4", features = ["futures-traits"] }
|
|||
project = { path = "../project" }
|
||||
search = { path = "../search" }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
settings = { path = "../settings" }
|
||||
sysinfo = "0.27.1"
|
||||
theme = { path = "../theme" }
|
||||
tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" }
|
||||
urlencoding = "2.1.2"
|
||||
util = { path = "../util" }
|
||||
workspace = { path = "../workspace" }
|
||||
workspace = { path = "../workspace" }
|
||||
|
|
|
@ -24,6 +24,7 @@ smol = "1.2.5"
|
|||
regex = "1.5"
|
||||
git2 = { version = "0.15", default-features = false }
|
||||
serde = { workspace = true }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { workspace = true }
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
libc = "0.2"
|
||||
|
|
|
@ -39,8 +39,10 @@ pathfinder_geometry = "0.5"
|
|||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
rand = "0.8.3"
|
||||
resvg = "0.14"
|
||||
schemars = "0.8"
|
||||
seahash = "4.1"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = "1.0"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2"
|
||||
|
|
|
@ -56,7 +56,10 @@ impl gpui::Element for TextElement {
|
|||
cx: &mut gpui::PaintContext,
|
||||
) -> Self::PaintState {
|
||||
let font_size = 12.;
|
||||
let family = cx.font_cache.load_family(&["SF Pro Display"]).unwrap();
|
||||
let family = cx
|
||||
.font_cache
|
||||
.load_family(&["SF Pro Display"], &Default::default())
|
||||
.unwrap();
|
||||
let normal = RunStyle {
|
||||
font_id: cx
|
||||
.font_cache
|
||||
|
|
|
@ -216,6 +216,7 @@ mod tests {
|
|||
12.,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Color::black(),
|
||||
cx.font_cache(),
|
||||
)
|
||||
|
@ -225,6 +226,7 @@ mod tests {
|
|||
12.,
|
||||
*FontProperties::new().weight(Weight::BOLD),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Color::new(255, 0, 0, 255),
|
||||
cx.font_cache(),
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
fonts::{FontId, Metrics, Properties},
|
||||
fonts::{Features, FontId, Metrics, Properties},
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
platform,
|
||||
text_layout::LineWrapper,
|
||||
|
@ -18,6 +18,7 @@ pub struct FamilyId(usize);
|
|||
|
||||
struct Family {
|
||||
name: Arc<str>,
|
||||
font_features: Features,
|
||||
font_ids: Vec<FontId>,
|
||||
}
|
||||
|
||||
|
@ -58,17 +59,21 @@ impl FontCache {
|
|||
.map(|family| family.name.clone())
|
||||
}
|
||||
|
||||
pub fn load_family(&self, names: &[&str]) -> Result<FamilyId> {
|
||||
pub fn load_family(&self, names: &[&str], features: &Features) -> Result<FamilyId> {
|
||||
for name in names {
|
||||
let state = self.0.upgradable_read();
|
||||
|
||||
if let Some(ix) = state.families.iter().position(|f| f.name.as_ref() == *name) {
|
||||
if let Some(ix) = state
|
||||
.families
|
||||
.iter()
|
||||
.position(|f| f.name.as_ref() == *name && f.font_features == *features)
|
||||
{
|
||||
return Ok(FamilyId(ix));
|
||||
}
|
||||
|
||||
let mut state = RwLockUpgradableReadGuard::upgrade(state);
|
||||
|
||||
if let Ok(font_ids) = state.fonts.load_family(name) {
|
||||
if let Ok(font_ids) = state.fonts.load_family(name, features) {
|
||||
if font_ids.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
@ -82,6 +87,7 @@ impl FontCache {
|
|||
|
||||
state.families.push(Family {
|
||||
name: Arc::from(*name),
|
||||
font_features: features.clone(),
|
||||
font_ids,
|
||||
});
|
||||
return Ok(family_id);
|
||||
|
@ -254,7 +260,15 @@ mod tests {
|
|||
fn test_select_font() {
|
||||
let platform = test::platform();
|
||||
let fonts = FontCache::new(platform.fonts());
|
||||
let arial = fonts.load_family(&["Arial"]).unwrap();
|
||||
let arial = fonts
|
||||
.load_family(
|
||||
&["Arial"],
|
||||
&Features {
|
||||
calt: Some(false),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let arial_regular = fonts.select_font(arial, &Properties::new()).unwrap();
|
||||
let arial_italic = fonts
|
||||
.select_font(arial, Properties::new().style(Style::Italic))
|
||||
|
@ -265,5 +279,16 @@ mod tests {
|
|||
assert_ne!(arial_regular, arial_italic);
|
||||
assert_ne!(arial_regular, arial_bold);
|
||||
assert_ne!(arial_italic, arial_bold);
|
||||
|
||||
let arial_with_calt = fonts
|
||||
.load_family(
|
||||
&["Arial"],
|
||||
&Features {
|
||||
calt: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert_ne!(arial_with_calt, arial);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ pub use font_kit::{
|
|||
properties::{Properties, Stretch, Style, Weight},
|
||||
};
|
||||
use ordered_float::OrderedFloat;
|
||||
use serde::{de, Deserialize};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{de, Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::{cell::RefCell, sync::Arc};
|
||||
|
||||
|
@ -20,6 +21,44 @@ pub struct FontId(pub usize);
|
|||
|
||||
pub type GlyphId = u32;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct Features {
|
||||
pub calt: Option<bool>,
|
||||
pub case: Option<bool>,
|
||||
pub cpsp: Option<bool>,
|
||||
pub frac: Option<bool>,
|
||||
pub liga: Option<bool>,
|
||||
pub onum: Option<bool>,
|
||||
pub ordn: Option<bool>,
|
||||
pub pnum: Option<bool>,
|
||||
pub ss01: Option<bool>,
|
||||
pub ss02: Option<bool>,
|
||||
pub ss03: Option<bool>,
|
||||
pub ss04: Option<bool>,
|
||||
pub ss05: Option<bool>,
|
||||
pub ss06: Option<bool>,
|
||||
pub ss07: Option<bool>,
|
||||
pub ss08: Option<bool>,
|
||||
pub ss09: Option<bool>,
|
||||
pub ss10: Option<bool>,
|
||||
pub ss11: Option<bool>,
|
||||
pub ss12: Option<bool>,
|
||||
pub ss13: Option<bool>,
|
||||
pub ss14: Option<bool>,
|
||||
pub ss15: Option<bool>,
|
||||
pub ss16: Option<bool>,
|
||||
pub ss17: Option<bool>,
|
||||
pub ss18: Option<bool>,
|
||||
pub ss19: Option<bool>,
|
||||
pub ss20: Option<bool>,
|
||||
pub subs: Option<bool>,
|
||||
pub sups: Option<bool>,
|
||||
pub swsh: Option<bool>,
|
||||
pub titl: Option<bool>,
|
||||
pub tnum: Option<bool>,
|
||||
pub zero: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TextStyle {
|
||||
pub color: Color,
|
||||
|
@ -71,6 +110,8 @@ thread_local! {
|
|||
struct TextStyleJson {
|
||||
color: Color,
|
||||
family: String,
|
||||
#[serde(default)]
|
||||
features: Features,
|
||||
weight: Option<WeightJson>,
|
||||
size: f32,
|
||||
#[serde(default)]
|
||||
|
@ -107,12 +148,13 @@ impl TextStyle {
|
|||
font_family_name: impl Into<Arc<str>>,
|
||||
font_size: f32,
|
||||
font_properties: Properties,
|
||||
font_features: Features,
|
||||
underline: Underline,
|
||||
color: Color,
|
||||
font_cache: &FontCache,
|
||||
) -> Result<Self> {
|
||||
let font_family_name = font_family_name.into();
|
||||
let font_family_id = font_cache.load_family(&[&font_family_name])?;
|
||||
let font_family_id = font_cache.load_family(&[&font_family_name], &font_features)?;
|
||||
let font_id = font_cache.select_font(font_family_id, &font_properties)?;
|
||||
Ok(Self {
|
||||
color,
|
||||
|
@ -175,6 +217,7 @@ impl TextStyle {
|
|||
json.family,
|
||||
json.size,
|
||||
font_properties,
|
||||
json.features,
|
||||
underline_from_json(json.underline),
|
||||
json.color,
|
||||
font_cache,
|
||||
|
@ -253,7 +296,9 @@ impl Default for TextStyle {
|
|||
.expect("TextStyle::default can only be called within a call to with_font_cache");
|
||||
|
||||
let font_family_name = Arc::from("Courier");
|
||||
let font_family_id = font_cache.load_family(&[&font_family_name]).unwrap();
|
||||
let font_family_id = font_cache
|
||||
.load_family(&[&font_family_name], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache
|
||||
.select_font(font_family_id, &Default::default())
|
||||
.unwrap();
|
||||
|
|
|
@ -9,7 +9,10 @@ pub mod current {
|
|||
|
||||
use crate::{
|
||||
executor,
|
||||
fonts::{FontId, GlyphId, Metrics as FontMetrics, Properties as FontProperties},
|
||||
fonts::{
|
||||
Features as FontFeatures, FontId, GlyphId, Metrics as FontMetrics,
|
||||
Properties as FontProperties,
|
||||
},
|
||||
geometry::{
|
||||
rect::{RectF, RectI},
|
||||
vector::Vector2F,
|
||||
|
@ -335,7 +338,7 @@ pub enum RasterizationOptions {
|
|||
|
||||
pub trait FontSystem: Send + Sync {
|
||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()>;
|
||||
fn load_family(&self, name: &str) -> anyhow::Result<Vec<FontId>>;
|
||||
fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>>;
|
||||
fn select_font(
|
||||
&self,
|
||||
font_ids: &[FontId],
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
mod open_type;
|
||||
|
||||
use crate::{
|
||||
fonts::{FontId, GlyphId, Metrics, Properties},
|
||||
fonts::{Features, FontId, GlyphId, Metrics, Properties},
|
||||
geometry::{
|
||||
rect::{RectF, RectI},
|
||||
transform2d::Transform2F,
|
||||
|
@ -64,8 +66,8 @@ impl platform::FontSystem for FontSystem {
|
|||
self.0.write().add_fonts(fonts)
|
||||
}
|
||||
|
||||
fn load_family(&self, name: &str) -> anyhow::Result<Vec<FontId>> {
|
||||
self.0.write().load_family(name)
|
||||
fn load_family(&self, name: &str, features: &Features) -> anyhow::Result<Vec<FontId>> {
|
||||
self.0.write().load_family(name, features)
|
||||
}
|
||||
|
||||
fn select_font(&self, font_ids: &[FontId], properties: &Properties) -> anyhow::Result<FontId> {
|
||||
|
@ -126,7 +128,7 @@ impl FontSystemState {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_family(&mut self, name: &str) -> anyhow::Result<Vec<FontId>> {
|
||||
fn load_family(&mut self, name: &str, features: &Features) -> anyhow::Result<Vec<FontId>> {
|
||||
let mut font_ids = Vec::new();
|
||||
|
||||
let family = self
|
||||
|
@ -134,7 +136,8 @@ impl FontSystemState {
|
|||
.select_family_by_name(name)
|
||||
.or_else(|_| self.system_source.select_family_by_name(name))?;
|
||||
for font in family.fonts() {
|
||||
let font = font.load()?;
|
||||
let mut font = font.load()?;
|
||||
open_type::apply_features(&mut font, features);
|
||||
let font_id = FontId(self.fonts.len());
|
||||
font_ids.push(font_id);
|
||||
let postscript_name = font.postscript_name().unwrap();
|
||||
|
@ -503,7 +506,7 @@ mod tests {
|
|||
fn test_layout_str(_: &mut MutableAppContext) {
|
||||
// This is failing intermittently on CI and we don't have time to figure it out
|
||||
let fonts = FontSystem::new();
|
||||
let menlo = fonts.load_family("Menlo").unwrap();
|
||||
let menlo = fonts.load_family("Menlo", &Default::default()).unwrap();
|
||||
let menlo_regular = RunStyle {
|
||||
font_id: fonts.select_font(&menlo, &Properties::new()).unwrap(),
|
||||
color: Default::default(),
|
||||
|
@ -544,13 +547,13 @@ mod tests {
|
|||
#[test]
|
||||
fn test_glyph_offsets() -> anyhow::Result<()> {
|
||||
let fonts = FontSystem::new();
|
||||
let zapfino = fonts.load_family("Zapfino")?;
|
||||
let zapfino = fonts.load_family("Zapfino", &Default::default())?;
|
||||
let zapfino_regular = RunStyle {
|
||||
font_id: fonts.select_font(&zapfino, &Properties::new())?,
|
||||
color: Default::default(),
|
||||
underline: Default::default(),
|
||||
};
|
||||
let menlo = fonts.load_family("Menlo")?;
|
||||
let menlo = fonts.load_family("Menlo", &Default::default())?;
|
||||
let menlo_regular = RunStyle {
|
||||
font_id: fonts.select_font(&menlo, &Properties::new())?,
|
||||
color: Default::default(),
|
||||
|
@ -584,7 +587,7 @@ mod tests {
|
|||
use std::{fs::File, io::BufWriter, path::Path};
|
||||
|
||||
let fonts = FontSystem::new();
|
||||
let font_ids = fonts.load_family("Fira Code").unwrap();
|
||||
let font_ids = fonts.load_family("Fira Code", &Default::default()).unwrap();
|
||||
let font_id = fonts.select_font(&font_ids, &Default::default()).unwrap();
|
||||
let glyph_id = fonts.glyph_for_char(font_id, 'G').unwrap();
|
||||
|
||||
|
@ -618,7 +621,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_wrap_line() {
|
||||
let fonts = FontSystem::new();
|
||||
let font_ids = fonts.load_family("Helvetica").unwrap();
|
||||
let font_ids = fonts.load_family("Helvetica", &Default::default()).unwrap();
|
||||
let font_id = fonts.select_font(&font_ids, &Default::default()).unwrap();
|
||||
|
||||
let line = "one two three four five\n";
|
||||
|
@ -636,7 +639,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_layout_line_bom_char() {
|
||||
let fonts = FontSystem::new();
|
||||
let font_ids = fonts.load_family("Helvetica").unwrap();
|
||||
let font_ids = fonts.load_family("Helvetica", &Default::default()).unwrap();
|
||||
let style = RunStyle {
|
||||
font_id: fonts.select_font(&font_ids, &Default::default()).unwrap(),
|
||||
color: Default::default(),
|
||||
|
|
395
crates/gpui/src/platform/mac/fonts/open_type.rs
Normal file
395
crates/gpui/src/platform/mac/fonts/open_type.rs
Normal file
|
@ -0,0 +1,395 @@
|
|||
#![allow(unused, non_upper_case_globals)]
|
||||
|
||||
use std::ptr;
|
||||
|
||||
use crate::fonts::Features;
|
||||
use cocoa::appkit::CGFloat;
|
||||
use core_foundation::{base::TCFType, number::CFNumber};
|
||||
use core_graphics::geometry::CGAffineTransform;
|
||||
use core_text::{
|
||||
font::{CTFont, CTFontRef},
|
||||
font_descriptor::{
|
||||
CTFontDescriptor, CTFontDescriptorCreateCopyWithFeature, CTFontDescriptorRef,
|
||||
},
|
||||
};
|
||||
use font_kit::font::Font;
|
||||
|
||||
const kCaseSensitiveLayoutOffSelector: i32 = 1;
|
||||
const kCaseSensitiveLayoutOnSelector: i32 = 0;
|
||||
const kCaseSensitiveLayoutType: i32 = 33;
|
||||
const kCaseSensitiveSpacingOffSelector: i32 = 3;
|
||||
const kCaseSensitiveSpacingOnSelector: i32 = 2;
|
||||
const kCharacterAlternativesType: i32 = 17;
|
||||
const kCommonLigaturesOffSelector: i32 = 3;
|
||||
const kCommonLigaturesOnSelector: i32 = 2;
|
||||
const kContextualAlternatesOffSelector: i32 = 1;
|
||||
const kContextualAlternatesOnSelector: i32 = 0;
|
||||
const kContextualAlternatesType: i32 = 36;
|
||||
const kContextualLigaturesOffSelector: i32 = 19;
|
||||
const kContextualLigaturesOnSelector: i32 = 18;
|
||||
const kContextualSwashAlternatesOffSelector: i32 = 5;
|
||||
const kContextualSwashAlternatesOnSelector: i32 = 4;
|
||||
const kDefaultLowerCaseSelector: i32 = 0;
|
||||
const kDefaultUpperCaseSelector: i32 = 0;
|
||||
const kDiagonalFractionsSelector: i32 = 2;
|
||||
const kFractionsType: i32 = 11;
|
||||
const kHistoricalLigaturesOffSelector: i32 = 21;
|
||||
const kHistoricalLigaturesOnSelector: i32 = 20;
|
||||
const kHojoCharactersSelector: i32 = 12;
|
||||
const kInferiorsSelector: i32 = 2;
|
||||
const kJIS2004CharactersSelector: i32 = 11;
|
||||
const kLigaturesType: i32 = 1;
|
||||
const kLowerCasePetiteCapsSelector: i32 = 2;
|
||||
const kLowerCaseSmallCapsSelector: i32 = 1;
|
||||
const kLowerCaseType: i32 = 37;
|
||||
const kLowerCaseNumbersSelector: i32 = 0;
|
||||
const kMathematicalGreekOffSelector: i32 = 11;
|
||||
const kMathematicalGreekOnSelector: i32 = 10;
|
||||
const kMonospacedNumbersSelector: i32 = 0;
|
||||
const kNLCCharactersSelector: i32 = 13;
|
||||
const kNoFractionsSelector: i32 = 0;
|
||||
const kNormalPositionSelector: i32 = 0;
|
||||
const kNoStyleOptionsSelector: i32 = 0;
|
||||
const kNumberCaseType: i32 = 21;
|
||||
const kNumberSpacingType: i32 = 6;
|
||||
const kOrdinalsSelector: i32 = 3;
|
||||
const kProportionalNumbersSelector: i32 = 1;
|
||||
const kQuarterWidthTextSelector: i32 = 4;
|
||||
const kScientificInferiorsSelector: i32 = 4;
|
||||
const kSlashedZeroOffSelector: i32 = 5;
|
||||
const kSlashedZeroOnSelector: i32 = 4;
|
||||
const kStyleOptionsType: i32 = 19;
|
||||
const kStylisticAltEighteenOffSelector: i32 = 37;
|
||||
const kStylisticAltEighteenOnSelector: i32 = 36;
|
||||
const kStylisticAltEightOffSelector: i32 = 17;
|
||||
const kStylisticAltEightOnSelector: i32 = 16;
|
||||
const kStylisticAltElevenOffSelector: i32 = 23;
|
||||
const kStylisticAltElevenOnSelector: i32 = 22;
|
||||
const kStylisticAlternativesType: i32 = 35;
|
||||
const kStylisticAltFifteenOffSelector: i32 = 31;
|
||||
const kStylisticAltFifteenOnSelector: i32 = 30;
|
||||
const kStylisticAltFiveOffSelector: i32 = 11;
|
||||
const kStylisticAltFiveOnSelector: i32 = 10;
|
||||
const kStylisticAltFourOffSelector: i32 = 9;
|
||||
const kStylisticAltFourOnSelector: i32 = 8;
|
||||
const kStylisticAltFourteenOffSelector: i32 = 29;
|
||||
const kStylisticAltFourteenOnSelector: i32 = 28;
|
||||
const kStylisticAltNineOffSelector: i32 = 19;
|
||||
const kStylisticAltNineOnSelector: i32 = 18;
|
||||
const kStylisticAltNineteenOffSelector: i32 = 39;
|
||||
const kStylisticAltNineteenOnSelector: i32 = 38;
|
||||
const kStylisticAltOneOffSelector: i32 = 3;
|
||||
const kStylisticAltOneOnSelector: i32 = 2;
|
||||
const kStylisticAltSevenOffSelector: i32 = 15;
|
||||
const kStylisticAltSevenOnSelector: i32 = 14;
|
||||
const kStylisticAltSeventeenOffSelector: i32 = 35;
|
||||
const kStylisticAltSeventeenOnSelector: i32 = 34;
|
||||
const kStylisticAltSixOffSelector: i32 = 13;
|
||||
const kStylisticAltSixOnSelector: i32 = 12;
|
||||
const kStylisticAltSixteenOffSelector: i32 = 33;
|
||||
const kStylisticAltSixteenOnSelector: i32 = 32;
|
||||
const kStylisticAltTenOffSelector: i32 = 21;
|
||||
const kStylisticAltTenOnSelector: i32 = 20;
|
||||
const kStylisticAltThirteenOffSelector: i32 = 27;
|
||||
const kStylisticAltThirteenOnSelector: i32 = 26;
|
||||
const kStylisticAltThreeOffSelector: i32 = 7;
|
||||
const kStylisticAltThreeOnSelector: i32 = 6;
|
||||
const kStylisticAltTwelveOffSelector: i32 = 25;
|
||||
const kStylisticAltTwelveOnSelector: i32 = 24;
|
||||
const kStylisticAltTwentyOffSelector: i32 = 41;
|
||||
const kStylisticAltTwentyOnSelector: i32 = 40;
|
||||
const kStylisticAltTwoOffSelector: i32 = 5;
|
||||
const kStylisticAltTwoOnSelector: i32 = 4;
|
||||
const kSuperiorsSelector: i32 = 1;
|
||||
const kSwashAlternatesOffSelector: i32 = 3;
|
||||
const kSwashAlternatesOnSelector: i32 = 2;
|
||||
const kTitlingCapsSelector: i32 = 4;
|
||||
const kTypographicExtrasType: i32 = 14;
|
||||
const kVerticalFractionsSelector: i32 = 1;
|
||||
const kVerticalPositionType: i32 = 10;
|
||||
|
||||
pub fn apply_features(font: &mut Font, features: &Features) {
|
||||
// See https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/third_party/harfbuzz-ng/src/hb-coretext.cc
|
||||
// for a reference implementation.
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.calt,
|
||||
kContextualAlternatesType,
|
||||
kContextualAlternatesOnSelector,
|
||||
kContextualAlternatesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.case,
|
||||
kCaseSensitiveLayoutType,
|
||||
kCaseSensitiveLayoutOnSelector,
|
||||
kCaseSensitiveLayoutOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.cpsp,
|
||||
kCaseSensitiveLayoutType,
|
||||
kCaseSensitiveSpacingOnSelector,
|
||||
kCaseSensitiveSpacingOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.frac,
|
||||
kFractionsType,
|
||||
kDiagonalFractionsSelector,
|
||||
kNoFractionsSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.liga,
|
||||
kLigaturesType,
|
||||
kCommonLigaturesOnSelector,
|
||||
kCommonLigaturesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.onum,
|
||||
kNumberCaseType,
|
||||
kLowerCaseNumbersSelector,
|
||||
2,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ordn,
|
||||
kVerticalPositionType,
|
||||
kOrdinalsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.pnum,
|
||||
kNumberSpacingType,
|
||||
kProportionalNumbersSelector,
|
||||
4,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss01,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltOneOnSelector,
|
||||
kStylisticAltOneOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss02,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwoOnSelector,
|
||||
kStylisticAltTwoOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss03,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltThreeOnSelector,
|
||||
kStylisticAltThreeOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss04,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFourOnSelector,
|
||||
kStylisticAltFourOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss05,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFiveOnSelector,
|
||||
kStylisticAltFiveOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss06,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSixOnSelector,
|
||||
kStylisticAltSixOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss07,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSevenOnSelector,
|
||||
kStylisticAltSevenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss08,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltEightOnSelector,
|
||||
kStylisticAltEightOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss09,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltNineOnSelector,
|
||||
kStylisticAltNineOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss10,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTenOnSelector,
|
||||
kStylisticAltTenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss11,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltElevenOnSelector,
|
||||
kStylisticAltElevenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss12,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwelveOnSelector,
|
||||
kStylisticAltTwelveOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss13,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltThirteenOnSelector,
|
||||
kStylisticAltThirteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss14,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFourteenOnSelector,
|
||||
kStylisticAltFourteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss15,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFifteenOnSelector,
|
||||
kStylisticAltFifteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss16,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSixteenOnSelector,
|
||||
kStylisticAltSixteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss17,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSeventeenOnSelector,
|
||||
kStylisticAltSeventeenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss18,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltEighteenOnSelector,
|
||||
kStylisticAltEighteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss19,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltNineteenOnSelector,
|
||||
kStylisticAltNineteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss20,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwentyOnSelector,
|
||||
kStylisticAltTwentyOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.subs,
|
||||
kVerticalPositionType,
|
||||
kInferiorsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.sups,
|
||||
kVerticalPositionType,
|
||||
kSuperiorsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.swsh,
|
||||
kContextualAlternatesType,
|
||||
kSwashAlternatesOnSelector,
|
||||
kSwashAlternatesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.titl,
|
||||
kStyleOptionsType,
|
||||
kTitlingCapsSelector,
|
||||
kNoStyleOptionsSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.tnum,
|
||||
kNumberSpacingType,
|
||||
kMonospacedNumbersSelector,
|
||||
4,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.zero,
|
||||
kTypographicExtrasType,
|
||||
kSlashedZeroOnSelector,
|
||||
kSlashedZeroOffSelector,
|
||||
);
|
||||
}
|
||||
|
||||
fn toggle_open_type_feature(
|
||||
font: &mut Font,
|
||||
enabled: Option<bool>,
|
||||
type_identifier: i32,
|
||||
on_selector_identifier: i32,
|
||||
off_selector_identifier: i32,
|
||||
) {
|
||||
if let Some(enabled) = enabled {
|
||||
let native_font = font.native_font();
|
||||
unsafe {
|
||||
let selector_identifier = if enabled {
|
||||
on_selector_identifier
|
||||
} else {
|
||||
off_selector_identifier
|
||||
};
|
||||
let new_descriptor = CTFontDescriptorCreateCopyWithFeature(
|
||||
native_font.copy_descriptor().as_concrete_TypeRef(),
|
||||
CFNumber::from(type_identifier).as_concrete_TypeRef(),
|
||||
CFNumber::from(selector_identifier).as_concrete_TypeRef(),
|
||||
);
|
||||
let new_descriptor = CTFontDescriptor::wrap_under_create_rule(new_descriptor);
|
||||
let new_font = CTFontCreateCopyWithAttributes(
|
||||
font.native_font().as_concrete_TypeRef(),
|
||||
0.0,
|
||||
ptr::null(),
|
||||
new_descriptor.as_concrete_TypeRef(),
|
||||
);
|
||||
let new_font = CTFont::wrap_under_create_rule(new_font);
|
||||
*font = Font::from_native_font(new_font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreText", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CTFontCreateCopyWithAttributes(
|
||||
font: CTFontRef,
|
||||
size: CGFloat,
|
||||
matrix: *const CGAffineTransform,
|
||||
attributes: CTFontDescriptorRef,
|
||||
) -> CTFontRef;
|
||||
}
|
|
@ -663,7 +663,9 @@ mod tests {
|
|||
fn test_wrap_line(cx: &mut crate::MutableAppContext) {
|
||||
let font_cache = cx.font_cache().clone();
|
||||
let font_system = cx.platform().fonts();
|
||||
let family = font_cache.load_family(&["Courier"]).unwrap();
|
||||
let family = font_cache
|
||||
.load_family(&["Courier"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache.select_font(family, &Default::default()).unwrap();
|
||||
|
||||
let mut wrapper = LineWrapper::new(font_id, 16., font_system);
|
||||
|
@ -725,7 +727,9 @@ mod tests {
|
|||
let font_system = cx.platform().fonts();
|
||||
let text_layout_cache = TextLayoutCache::new(font_system.clone());
|
||||
|
||||
let family = font_cache.load_family(&["Helvetica"]).unwrap();
|
||||
let family = font_cache
|
||||
.load_family(&["Helvetica"], &Default::default())
|
||||
.unwrap();
|
||||
let font_id = font_cache.select_font(family, &Default::default()).unwrap();
|
||||
let normal = RunStyle {
|
||||
font_id,
|
||||
|
|
|
@ -47,6 +47,7 @@ postage = { version = "0.4.1", features = ["futures-traits"] }
|
|||
rand = { version = "0.8.3", optional = true }
|
||||
regex = "1.5"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1", features = ["preserve_order"] }
|
||||
similar = "1.3"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
|
|
|
@ -14,7 +14,7 @@ name = "test_app"
|
|||
|
||||
[features]
|
||||
test-support = [
|
||||
"async-trait",
|
||||
"async-trait",
|
||||
"collections/test-support",
|
||||
"gpui/test-support",
|
||||
"lazy_static",
|
||||
|
@ -63,9 +63,11 @@ lazy_static = "1.4"
|
|||
objc = "0.2"
|
||||
parking_lot = "0.11.1"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
sha2 = "0.10"
|
||||
simplelog = "0.9"
|
||||
|
||||
[build-dependencies]
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
|
|
|
@ -20,6 +20,7 @@ prost = "0.8"
|
|||
prost-types = "0.8"
|
||||
reqwest = "0.11"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
sha2 = "0.10"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -23,6 +23,7 @@ lsp-types = "0.91"
|
|||
parking_lot = "0.11"
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||
smol = "1.2"
|
||||
|
||||
|
|
|
@ -6,5 +6,6 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
serde = "1.0"
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
bincode = "1.3"
|
||||
plugin_macros = { path = "../plugin_macros" }
|
||||
|
|
|
@ -12,4 +12,5 @@ syn = { version = "1.0", features = ["full", "extra-traits"] }
|
|||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
bincode = "1.3"
|
||||
|
|
|
@ -10,6 +10,7 @@ wasmtime-wasi = "0.38"
|
|||
wasi-common = "0.38"
|
||||
anyhow = { version = "1.0", features = ["std"] }
|
||||
serde = "1.0"
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = "1.0"
|
||||
bincode = "1.3"
|
||||
pollster = "0.2.5"
|
||||
|
|
|
@ -49,6 +49,7 @@ pulldown-cmark = { version = "0.9.1", default-features = false }
|
|||
rand = "0.8.3"
|
||||
regex = "1.5"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
sha2 = "0.10"
|
||||
similar = "1.3"
|
||||
|
|
|
@ -27,6 +27,7 @@ prost = "0.8"
|
|||
rand = "0.8"
|
||||
rsa = "0.4"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
smol-timeout = "0.6"
|
||||
tracing = { version = "0.1.34", features = ["log"] }
|
||||
zstd = "0.11"
|
||||
|
|
|
@ -24,6 +24,7 @@ futures = "0.3"
|
|||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2"
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ json_comments = "0.2"
|
|||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
schemars = "0.8"
|
||||
serde = { workspace = true }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { workspace = true }
|
||||
serde_path_to_error = "0.1.4"
|
||||
toml = "0.5"
|
||||
|
|
|
@ -5,7 +5,7 @@ pub mod watched_json;
|
|||
use anyhow::{bail, Result};
|
||||
use gpui::{
|
||||
font_cache::{FamilyId, FontCache},
|
||||
AssetSource,
|
||||
fonts, AssetSource,
|
||||
};
|
||||
use schemars::{
|
||||
gen::{SchemaGenerator, SchemaSettings},
|
||||
|
@ -28,6 +28,8 @@ pub use watched_json::watch_files;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Settings {
|
||||
pub buffer_font_family_name: String,
|
||||
pub buffer_font_features: fonts::Features,
|
||||
pub buffer_font_family: FamilyId,
|
||||
pub default_buffer_font_size: f32,
|
||||
pub buffer_font_size: f32,
|
||||
|
@ -225,6 +227,7 @@ pub struct TerminalSettings {
|
|||
pub working_directory: Option<WorkingDirectory>,
|
||||
pub font_size: Option<f32>,
|
||||
pub font_family: Option<String>,
|
||||
pub font_features: Option<fonts::Features>,
|
||||
pub env: Option<HashMap<String, String>>,
|
||||
pub blinking: Option<TerminalBlink>,
|
||||
pub alternate_scroll: Option<AlternateScroll>,
|
||||
|
@ -332,6 +335,8 @@ pub struct SettingsFileContent {
|
|||
#[serde(default)]
|
||||
pub buffer_font_size: Option<f32>,
|
||||
#[serde(default)]
|
||||
pub buffer_font_features: Option<fonts::Features>,
|
||||
#[serde(default)]
|
||||
pub active_pane_magnification: Option<f32>,
|
||||
#[serde(default)]
|
||||
pub cursor_blink: Option<bool>,
|
||||
|
@ -396,10 +401,16 @@ impl Settings {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let buffer_font_features = defaults.buffer_font_features.unwrap();
|
||||
Self {
|
||||
buffer_font_family: font_cache
|
||||
.load_family(&[defaults.buffer_font_family.as_ref().unwrap()])
|
||||
.load_family(
|
||||
&[defaults.buffer_font_family.as_ref().unwrap()],
|
||||
&buffer_font_features,
|
||||
)
|
||||
.unwrap(),
|
||||
buffer_font_family_name: defaults.buffer_font_family.unwrap(),
|
||||
buffer_font_features,
|
||||
buffer_font_size: defaults.buffer_font_size.unwrap(),
|
||||
active_pane_magnification: defaults.active_pane_magnification.unwrap(),
|
||||
default_buffer_font_size: defaults.buffer_font_size.unwrap(),
|
||||
|
@ -451,11 +462,24 @@ impl Settings {
|
|||
theme_registry: &ThemeRegistry,
|
||||
font_cache: &FontCache,
|
||||
) {
|
||||
if let Some(value) = &data.buffer_font_family {
|
||||
if let Some(id) = font_cache.load_family(&[value]).log_err() {
|
||||
let mut family_changed = false;
|
||||
if let Some(value) = data.buffer_font_family {
|
||||
self.buffer_font_family_name = value;
|
||||
family_changed = true;
|
||||
}
|
||||
if let Some(value) = data.buffer_font_features {
|
||||
self.buffer_font_features = value;
|
||||
family_changed = true;
|
||||
}
|
||||
if family_changed {
|
||||
if let Some(id) = font_cache
|
||||
.load_family(&[&self.buffer_font_family_name], &self.buffer_font_features)
|
||||
.log_err()
|
||||
{
|
||||
self.buffer_font_family = id;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = &data.theme {
|
||||
if let Some(theme) = theme_registry.get(value).log_err() {
|
||||
self.theme = theme;
|
||||
|
@ -480,11 +504,6 @@ impl Settings {
|
|||
merge(&mut self.default_dock_anchor, data.default_dock_anchor);
|
||||
merge(&mut self.base_keymap, data.base_keymap);
|
||||
|
||||
// Ensure terminal font is loaded, so we can request it in terminal_element layout
|
||||
if let Some(terminal_font) = &data.terminal.font_family {
|
||||
font_cache.load_family(&[terminal_font]).log_err();
|
||||
}
|
||||
|
||||
self.editor_overrides = data.editor;
|
||||
self.git_overrides = data.git.unwrap_or_default();
|
||||
self.journal_overrides = data.journal;
|
||||
|
@ -616,7 +635,12 @@ impl Settings {
|
|||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn test(cx: &gpui::AppContext) -> Settings {
|
||||
Settings {
|
||||
buffer_font_family: cx.font_cache().load_family(&["Monaco"]).unwrap(),
|
||||
buffer_font_family_name: "Monaco".to_string(),
|
||||
buffer_font_features: Default::default(),
|
||||
buffer_font_family: cx
|
||||
.font_cache()
|
||||
.load_family(&["Monaco"], &Default::default())
|
||||
.unwrap(),
|
||||
buffer_font_size: 14.,
|
||||
active_pane_magnification: 1.,
|
||||
default_buffer_font_size: 14.,
|
||||
|
|
|
@ -30,6 +30,7 @@ anyhow = "1"
|
|||
thiserror = "1.0"
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8.5"
|
||||
|
|
|
@ -34,6 +34,7 @@ anyhow = "1"
|
|||
thiserror = "1.0"
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -505,13 +505,22 @@ impl TerminalElement {
|
|||
|
||||
///Configures a text style from the current settings.
|
||||
pub fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle {
|
||||
// Pull the font family from settings properly overriding
|
||||
let family_id = settings
|
||||
let font_family_name = settings
|
||||
.terminal_overrides
|
||||
.font_family
|
||||
.as_ref()
|
||||
.or(settings.terminal_defaults.font_family.as_ref())
|
||||
.and_then(|family_name| font_cache.load_family(&[family_name]).log_err())
|
||||
.unwrap_or(&settings.buffer_font_family_name);
|
||||
let font_features = settings
|
||||
.terminal_overrides
|
||||
.font_features
|
||||
.as_ref()
|
||||
.or(settings.terminal_defaults.font_features.as_ref())
|
||||
.unwrap_or(&settings.buffer_font_features);
|
||||
|
||||
let family_id = font_cache
|
||||
.load_family(&[font_family_name], &font_features)
|
||||
.log_err()
|
||||
.unwrap_or(settings.buffer_font_family);
|
||||
|
||||
let font_size = settings
|
||||
|
|
|
@ -14,6 +14,7 @@ anyhow = "1.0.38"
|
|||
indexmap = "1.6.2"
|
||||
parking_lot = "0.11.1"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_path_to_error = "0.1.4"
|
||||
toml = "0.5"
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::{Theme, ThemeMeta};
|
|||
use anyhow::{Context, Result};
|
||||
use gpui::{fonts, AssetSource, FontCache};
|
||||
use parking_lot::Mutex;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
|
@ -56,12 +57,16 @@ impl ThemeRegistry {
|
|||
.with_context(|| format!("failed to load theme file {}", asset_path))?;
|
||||
|
||||
// Allocate into the heap directly, the Theme struct is too large to fit in the stack.
|
||||
let mut theme: Arc<Theme> = fonts::with_font_cache(self.font_cache.clone(), || {
|
||||
serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&theme_json))
|
||||
let mut theme = fonts::with_font_cache(self.font_cache.clone(), || {
|
||||
let mut theme = Box::new(Theme::default());
|
||||
let mut deserializer = serde_json::Deserializer::from_slice(&theme_json);
|
||||
let result = Theme::deserialize_in_place(&mut deserializer, &mut theme);
|
||||
result.map(|_| theme)
|
||||
})?;
|
||||
|
||||
// Reset name to be the file path, so that we can use it to access the stored themes
|
||||
Arc::get_mut(&mut theme).unwrap().meta.name = name.into();
|
||||
theme.meta.name = name.into();
|
||||
let theme: Arc<Theme> = theme.into();
|
||||
self.themes.lock().insert(name.to_string(), theme.clone());
|
||||
Ok(theme)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ neovim = ["nvim-rs", "async-compat", "async-trait", "tokio"]
|
|||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
itertools = "0.10"
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
|||
parking_lot = "0.11.1"
|
||||
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
indoc = "1.0.4"
|
||||
|
@ -57,4 +58,4 @@ gpui = { path = "../gpui", features = ["test-support"] }
|
|||
project = { path = "../project", features = ["test-support"] }
|
||||
settings = { path = "../settings", features = ["test-support"] }
|
||||
fs = { path = "../fs", features = ["test-support"] }
|
||||
db = { path = "../db", features = ["test-support"] }
|
||||
db = { path = "../db", features = ["test-support"] }
|
||||
|
|
|
@ -88,6 +88,7 @@ regex = "1.5"
|
|||
rsa = "0.4"
|
||||
rust-embed = { version = "6.3", features = ["include-exclude"] }
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_path_to_error = "0.1.4"
|
||||
simplelog = "0.9"
|
||||
|
|
3
plugins/Cargo.lock
generated
3
plugins/Cargo.lock
generated
|
@ -23,6 +23,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"plugin",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
|
@ -33,6 +34,7 @@ dependencies = [
|
|||
"bincode",
|
||||
"plugin_macros",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -43,6 +45,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
plugin = { path = "../../crates/plugin" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -97,7 +97,79 @@ export interface TextProperties {
|
|||
size?: keyof typeof fontSizes
|
||||
weight?: FontWeight
|
||||
underline?: boolean
|
||||
color?: string
|
||||
color?: string,
|
||||
features?: FontFeatures,
|
||||
}
|
||||
|
||||
interface FontFeatures {
|
||||
/** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
|
||||
calt?: boolean;
|
||||
/** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
|
||||
case?: boolean;
|
||||
/** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
|
||||
cpsp?: boolean;
|
||||
/** Fractions: Replaces figures separated by a slash with diagonal fractions */
|
||||
frac?: boolean;
|
||||
/** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
|
||||
liga?: boolean;
|
||||
/** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
|
||||
onum?: boolean;
|
||||
/** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
|
||||
ordn?: boolean;
|
||||
/** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
|
||||
pnum?: boolean;
|
||||
/** Stylistic set 01 */
|
||||
ss01?: boolean;
|
||||
/** Stylistic set 02 */
|
||||
ss02?: boolean;
|
||||
/** Stylistic set 03 */
|
||||
ss03?: boolean;
|
||||
/** Stylistic set 04 */
|
||||
ss04?: boolean;
|
||||
/** Stylistic set 05 */
|
||||
ss05?: boolean;
|
||||
/** Stylistic set 06 */
|
||||
ss06?: boolean;
|
||||
/** Stylistic set 07 */
|
||||
ss07?: boolean;
|
||||
/** Stylistic set 08 */
|
||||
ss08?: boolean;
|
||||
/** Stylistic set 09 */
|
||||
ss09?: boolean;
|
||||
/** Stylistic set 10 */
|
||||
ss10?: boolean;
|
||||
/** Stylistic set 11 */
|
||||
ss11?: boolean;
|
||||
/** Stylistic set 12 */
|
||||
ss12?: boolean;
|
||||
/** Stylistic set 13 */
|
||||
ss13?: boolean;
|
||||
/** Stylistic set 14 */
|
||||
ss14?: boolean;
|
||||
/** Stylistic set 15 */
|
||||
ss15?: boolean;
|
||||
/** Stylistic set 16 */
|
||||
ss16?: boolean;
|
||||
/** Stylistic set 17 */
|
||||
ss17?: boolean;
|
||||
/** Stylistic set 18 */
|
||||
ss18?: boolean;
|
||||
/** Stylistic set 19 */
|
||||
ss19?: boolean;
|
||||
/** Stylistic set 20 */
|
||||
ss20?: boolean;
|
||||
/** Subscript: Replaces default glyphs with subscript glyphs */
|
||||
subs?: boolean;
|
||||
/** Superscript: Replaces default glyphs with superscript glyphs */
|
||||
sups?: boolean;
|
||||
/** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
|
||||
swsh?: boolean;
|
||||
/** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
|
||||
titl?: boolean;
|
||||
/** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
|
||||
tnum?: boolean;
|
||||
/** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
|
||||
zero?: boolean;
|
||||
}
|
||||
|
||||
export function text(
|
||||
|
|
Loading…
Reference in a new issue