diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index cfb8b983bb..499feae388 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -2873,7 +2873,7 @@ impl InlineAssistant { cx.theme().colors().text }, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/assistant/src/completion_provider/open_ai.rs b/crates/assistant/src/completion_provider/open_ai.rs index 458a3a9d25..9a7398ef7f 100644 --- a/crates/assistant/src/completion_provider/open_ai.rs +++ b/crates/assistant/src/completion_provider/open_ai.rs @@ -241,7 +241,7 @@ impl AuthenticationPrompt { let text_style = TextStyle { color: cx.theme().colors().text, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/collab_ui/src/chat_panel/message_editor.rs b/crates/collab_ui/src/chat_panel/message_editor.rs index f00575c8fd..84014f05c6 100644 --- a/crates/collab_ui/src/chat_panel/message_editor.rs +++ b/crates/collab_ui/src/chat_panel/message_editor.rs @@ -522,7 +522,7 @@ impl Render for MessageEditor { cx.theme().colors().text }, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: TextSize::Small.rems(cx).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 7f843b7a86..4b19c4fb25 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -2171,7 +2171,7 @@ impl CollabPanel { cx.theme().colors().text }, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b2b299e780..cb751a1169 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -10340,7 +10340,7 @@ impl Render for Editor { EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle { color: cx.theme().colors().editor_foreground, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, @@ -10353,7 +10353,7 @@ impl Render for Editor { EditorMode::Full => TextStyle { color: cx.theme().colors().editor_foreground, font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, + font_features: settings.buffer_font.features.clone(), font_size: settings.buffer_font_size(cx).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, @@ -10778,7 +10778,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren let theme_settings = ThemeSettings::get_global(cx); text_style.font_family = theme_settings.buffer_font.family.clone(); text_style.font_style = theme_settings.buffer_font.style; - text_style.font_features = theme_settings.buffer_font.features; + text_style.font_features = theme_settings.buffer_font.features.clone(); text_style.font_weight = theme_settings.buffer_font.weight; let multi_line_diagnostic = diagnostic.message.contains('\n'); diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs index fcc1fd8695..34d9a2ca4d 100644 --- a/crates/extensions_ui/src/extensions_ui.rs +++ b/crates/extensions_ui/src/extensions_ui.rs @@ -739,7 +739,7 @@ impl ExtensionsPage { cx.theme().colors().text }, font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features, + font_features: settings.ui_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/gpui/src/platform/cosmic_text/text_system.rs b/crates/gpui/src/platform/cosmic_text/text_system.rs index 13467361e4..a6f131ff7f 100644 --- a/crates/gpui/src/platform/cosmic_text/text_system.rs +++ b/crates/gpui/src/platform/cosmic_text/text_system.rs @@ -90,7 +90,7 @@ impl PlatformTextSystem for CosmicTextSystem { let candidates = if let Some(font_ids) = state.font_ids_by_family_cache.get(&font.family) { font_ids.as_slice() } else { - let font_ids = state.load_family(&font.family, font.features)?; + let font_ids = state.load_family(&font.family, &font.features)?; state .font_ids_by_family_cache .insert(font.family.clone(), font_ids); @@ -211,7 +211,7 @@ impl CosmicTextSystemState { fn load_family( &mut self, name: &str, - _features: FontFeatures, + _features: &FontFeatures, ) -> Result> { // TODO: Determine the proper system UI font. let name = if name == ".SystemUIFont" { diff --git a/crates/gpui/src/platform/mac/open_type.rs b/crates/gpui/src/platform/mac/open_type.rs index c9d7197c0d..d465e8f745 100644 --- a/crates/gpui/src/platform/mac/open_type.rs +++ b/crates/gpui/src/platform/mac/open_type.rs @@ -107,7 +107,7 @@ const kTypographicExtrasType: i32 = 14; const kVerticalFractionsSelector: i32 = 1; const kVerticalPositionType: i32 = 10; -pub fn apply_features(font: &mut Font, features: FontFeatures) { +pub fn apply_features(font: &mut Font, features: &FontFeatures) { // 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( diff --git a/crates/gpui/src/platform/mac/text_system.rs b/crates/gpui/src/platform/mac/text_system.rs index 64ba6cbd36..6c4a10af00 100644 --- a/crates/gpui/src/platform/mac/text_system.rs +++ b/crates/gpui/src/platform/mac/text_system.rs @@ -123,12 +123,12 @@ impl PlatformTextSystem for MacTextSystem { let mut lock = RwLockUpgradableReadGuard::upgrade(lock); let font_key = FontKey { font_family: font.family.clone(), - font_features: font.features, + font_features: font.features.clone(), }; let candidates = if let Some(font_ids) = lock.font_ids_by_font_key.get(&font_key) { font_ids.as_slice() } else { - let font_ids = lock.load_family(&font.family, font.features)?; + let font_ids = lock.load_family(&font.family, &font.features)?; lock.font_ids_by_font_key.insert(font_key.clone(), font_ids); lock.font_ids_by_font_key[&font_key].as_ref() }; @@ -219,7 +219,11 @@ impl MacTextSystemState { Ok(()) } - fn load_family(&mut self, name: &str, features: FontFeatures) -> Result> { + fn load_family( + &mut self, + name: &str, + features: &FontFeatures, + ) -> Result> { let name = if name == ".SystemUIFont" { ".AppleSystemUIFont" } else { diff --git a/crates/gpui/src/style.rs b/crates/gpui/src/style.rs index 6d7e3ac94e..49111f48f8 100644 --- a/crates/gpui/src/style.rs +++ b/crates/gpui/src/style.rs @@ -262,7 +262,7 @@ impl TextStyle { pub fn font(&self) -> Font { Font { family: self.font_family.clone(), - features: self.font_features, + features: self.font_features.clone(), weight: self.font_weight, style: self.font_style, } diff --git a/crates/gpui/src/text_system/font_features.rs b/crates/gpui/src/text_system/font_features.rs index 303cdbef26..39ec18f74b 100644 --- a/crates/gpui/src/text_system/font_features.rs +++ b/crates/gpui/src/text_system/font_features.rs @@ -1,3 +1,7 @@ +#[cfg(target_os = "windows")] +use crate::SharedString; +#[cfg(target_os = "windows")] +use itertools::Itertools; use schemars::{ schema::{InstanceType, Schema, SchemaObject, SingleOrVec}, JsonSchema, @@ -7,10 +11,14 @@ macro_rules! create_definitions { ($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => { /// The OpenType features that can be configured for a given font. - #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] + #[derive(Default, Clone, Eq, PartialEq, Hash)] pub struct FontFeatures { enabled: u64, disabled: u64, + #[cfg(target_os = "windows")] + other_enabled: SharedString, + #[cfg(target_os = "windows")] + other_disabled: SharedString, } impl FontFeatures { @@ -47,6 +55,14 @@ macro_rules! create_definitions { } } )* + { + for name in self.other_enabled.as_ref().chars().chunks(4).into_iter() { + result.push((name.collect::(), true)); + } + for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() { + result.push((name.collect::(), false)); + } + } result } } @@ -59,6 +75,15 @@ macro_rules! create_definitions { debug.field(stringify!($name), &value); }; )* + #[cfg(target_os = "windows")] + { + for name in self.other_enabled.as_ref().chars().chunks(4).into_iter() { + debug.field(name.collect::().as_str(), &true); + } + for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() { + debug.field(name.collect::().as_str(), &false); + } + } debug.finish() } } @@ -80,6 +105,7 @@ macro_rules! create_definitions { formatter.write_str("a map of font features") } + #[cfg(not(target_os = "windows"))] fn visit_map(self, mut access: M) -> Result where M: MapAccess<'de>, @@ -100,6 +126,54 @@ macro_rules! create_definitions { } Ok(FontFeatures { enabled, disabled }) } + + #[cfg(target_os = "windows")] + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut enabled: u64 = 0; + let mut disabled: u64 = 0; + let mut other_enabled = "".to_owned(); + let mut other_disabled = "".to_owned(); + + while let Some((key, value)) = access.next_entry::>()? { + let idx = match key.as_str() { + $(stringify!($name) => Some($idx),)* + other_feature => { + if other_feature.len() != 4 || !other_feature.is_ascii() { + log::error!("Incorrect feature name: {}", other_feature); + continue; + } + None + }, + }; + if let Some(idx) = idx { + match value { + Some(true) => enabled |= 1 << idx, + Some(false) => disabled |= 1 << idx, + None => {} + }; + } else { + match value { + Some(true) => other_enabled.push_str(key.as_str()), + Some(false) => other_disabled.push_str(key.as_str()), + None => {} + }; + } + } + let other_enabled = if other_enabled.is_empty() { + "".into() + } else { + other_enabled.into() + }; + let other_disabled = if other_disabled.is_empty() { + "".into() + } else { + other_disabled.into() + }; + Ok(FontFeatures { enabled, disabled, other_enabled, other_disabled }) + } } let features = deserializer.deserialize_map(FontFeaturesVisitor)?; @@ -125,6 +199,16 @@ macro_rules! create_definitions { } )* + #[cfg(target_os = "windows")] + { + for name in self.other_enabled.as_ref().chars().chunks(4).into_iter() { + map.serialize_entry(name.collect::().as_str(), &true)?; + } + for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() { + map.serialize_entry(name.collect::().as_str(), &false)?; + } + } + map.end() } } diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 63a49e6220..dab806ad54 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -274,7 +274,7 @@ impl PickerDelegate for OutlineViewDelegate { let text_style = TextStyle { color: cx.theme().colors().text, font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, + font_features: settings.buffer_font.features.clone(), font_size: settings.buffer_font_size(cx).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 0e0c33c265..3e0b8fb748 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -114,7 +114,7 @@ impl BufferSearchBar { color }, font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, + font_features: settings.buffer_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 111a0ace61..c75e5ac6a6 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -1307,7 +1307,7 @@ impl ProjectSearchBar { cx.theme().colors().text }, font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, + font_features: settings.buffer_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 909ab2a6f1..b0bee7fa5e 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -578,7 +578,8 @@ impl Element for TerminalElement { let font_features = terminal_settings .font_features - .unwrap_or(settings.buffer_font.features); + .clone() + .unwrap_or(settings.buffer_font.features.clone()); let line_height = terminal_settings.line_height.value(); let font_size = terminal_settings.font_size; diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index b7f08b2450..e5a6b6b2c7 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -325,13 +325,13 @@ impl settings::Settings for ThemeSettings { ui_font_size: defaults.ui_font_size.unwrap().into(), ui_font: Font { family: defaults.ui_font_family.clone().unwrap().into(), - features: defaults.ui_font_features.unwrap(), + features: defaults.ui_font_features.clone().unwrap(), weight: Default::default(), style: Default::default(), }, buffer_font: Font { family: defaults.buffer_font_family.clone().unwrap().into(), - features: defaults.buffer_font_features.unwrap(), + features: defaults.buffer_font_features.clone().unwrap(), weight: FontWeight::default(), style: FontStyle::default(), }, @@ -349,14 +349,14 @@ impl settings::Settings for ThemeSettings { if let Some(value) = value.buffer_font_family.clone() { this.buffer_font.family = value.into(); } - if let Some(value) = value.buffer_font_features { + if let Some(value) = value.buffer_font_features.clone() { this.buffer_font.features = value; } if let Some(value) = value.ui_font_family.clone() { this.ui_font.family = value.into(); } - if let Some(value) = value.ui_font_features { + if let Some(value) = value.ui_font_features.clone() { this.ui_font.features = value; } diff --git a/crates/ui_text_field/src/ui_text_field.rs b/crates/ui_text_field/src/ui_text_field.rs index f5addf3a9f..548756de1f 100644 --- a/crates/ui_text_field/src/ui_text_field.rs +++ b/crates/ui_text_field/src/ui_text_field.rs @@ -123,7 +123,7 @@ impl Render for TextField { let text_style = TextStyle { font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, + font_features: settings.buffer_font.features.clone(), font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal,