Merge pull request #2300 from zed-industries/ligatures

Allow customization of OpenType features
This commit is contained in:
Antonio Scandurra 2023-03-17 17:34:17 +01:00 committed by GitHub
commit d8758658e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 750 additions and 59 deletions

28
Cargo.lock generated
View file

@ -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",

View file

@ -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" }

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"] }

View file

@ -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"] }

View file

@ -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]

View file

@ -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 }

View file

@ -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();

View file

@ -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())

View file

@ -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();

View file

@ -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())

View file

@ -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())

View file

@ -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" }

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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(),
)

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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],

View file

@ -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(),

View 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;
}

View file

@ -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,

View file

@ -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"] }

View file

@ -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"] }

View file

@ -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]

View file

@ -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"

View file

@ -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" }

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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.,

View file

@ -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"

View file

@ -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"] }

View file

@ -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

View file

@ -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"

View file

@ -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)
}

View file

@ -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"] }

View file

@ -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"] }

View file

@ -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
View file

@ -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",
]

View file

@ -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]

View file

@ -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(