mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 18:25:57 +00:00
windows: Support all OpenType
font features (#10756)
Release Notes: - Added support for all `OpenType` font features to DirectWrite. https://github.com/zed-industries/zed/assets/14981363/cb2848cd-9178-4d87-881a-54dc646b2b61 --------- Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
268cb948a7
commit
11dc3c2582
17 changed files with 114 additions and 25 deletions
|
@ -2873,7 +2873,7 @@ impl InlineAssistant {
|
||||||
cx.theme().colors().text
|
cx.theme().colors().text
|
||||||
},
|
},
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl AuthenticationPrompt {
|
||||||
let text_style = TextStyle {
|
let text_style = TextStyle {
|
||||||
color: cx.theme().colors().text,
|
color: cx.theme().colors().text,
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -522,7 +522,7 @@ impl Render for MessageEditor {
|
||||||
cx.theme().colors().text
|
cx.theme().colors().text
|
||||||
},
|
},
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: TextSize::Small.rems(cx).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -2171,7 +2171,7 @@ impl CollabPanel {
|
||||||
cx.theme().colors().text
|
cx.theme().colors().text
|
||||||
},
|
},
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -10340,7 +10340,7 @@ impl Render for Editor {
|
||||||
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
|
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
|
||||||
color: cx.theme().colors().editor_foreground,
|
color: cx.theme().colors().editor_foreground,
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
@ -10353,7 +10353,7 @@ impl Render for Editor {
|
||||||
EditorMode::Full => TextStyle {
|
EditorMode::Full => TextStyle {
|
||||||
color: cx.theme().colors().editor_foreground,
|
color: cx.theme().colors().editor_foreground,
|
||||||
font_family: settings.buffer_font.family.clone(),
|
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_size: settings.buffer_font_size(cx).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::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);
|
let theme_settings = ThemeSettings::get_global(cx);
|
||||||
text_style.font_family = theme_settings.buffer_font.family.clone();
|
text_style.font_family = theme_settings.buffer_font.family.clone();
|
||||||
text_style.font_style = theme_settings.buffer_font.style;
|
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;
|
text_style.font_weight = theme_settings.buffer_font.weight;
|
||||||
|
|
||||||
let multi_line_diagnostic = diagnostic.message.contains('\n');
|
let multi_line_diagnostic = diagnostic.message.contains('\n');
|
||||||
|
|
|
@ -739,7 +739,7 @@ impl ExtensionsPage {
|
||||||
cx.theme().colors().text
|
cx.theme().colors().text
|
||||||
},
|
},
|
||||||
font_family: settings.ui_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl PlatformTextSystem for CosmicTextSystem {
|
||||||
let candidates = if let Some(font_ids) = state.font_ids_by_family_cache.get(&font.family) {
|
let candidates = if let Some(font_ids) = state.font_ids_by_family_cache.get(&font.family) {
|
||||||
font_ids.as_slice()
|
font_ids.as_slice()
|
||||||
} else {
|
} else {
|
||||||
let font_ids = state.load_family(&font.family, font.features)?;
|
let font_ids = state.load_family(&font.family, &font.features)?;
|
||||||
state
|
state
|
||||||
.font_ids_by_family_cache
|
.font_ids_by_family_cache
|
||||||
.insert(font.family.clone(), font_ids);
|
.insert(font.family.clone(), font_ids);
|
||||||
|
@ -211,7 +211,7 @@ impl CosmicTextSystemState {
|
||||||
fn load_family(
|
fn load_family(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
_features: FontFeatures,
|
_features: &FontFeatures,
|
||||||
) -> Result<SmallVec<[FontId; 4]>> {
|
) -> Result<SmallVec<[FontId; 4]>> {
|
||||||
// TODO: Determine the proper system UI font.
|
// TODO: Determine the proper system UI font.
|
||||||
let name = if name == ".SystemUIFont" {
|
let name = if name == ".SystemUIFont" {
|
||||||
|
|
|
@ -107,7 +107,7 @@ const kTypographicExtrasType: i32 = 14;
|
||||||
const kVerticalFractionsSelector: i32 = 1;
|
const kVerticalFractionsSelector: i32 = 1;
|
||||||
const kVerticalPositionType: i32 = 10;
|
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
|
// See https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/third_party/harfbuzz-ng/src/hb-coretext.cc
|
||||||
// for a reference implementation.
|
// for a reference implementation.
|
||||||
toggle_open_type_feature(
|
toggle_open_type_feature(
|
||||||
|
|
|
@ -123,12 +123,12 @@ impl PlatformTextSystem for MacTextSystem {
|
||||||
let mut lock = RwLockUpgradableReadGuard::upgrade(lock);
|
let mut lock = RwLockUpgradableReadGuard::upgrade(lock);
|
||||||
let font_key = FontKey {
|
let font_key = FontKey {
|
||||||
font_family: font.family.clone(),
|
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) {
|
let candidates = if let Some(font_ids) = lock.font_ids_by_font_key.get(&font_key) {
|
||||||
font_ids.as_slice()
|
font_ids.as_slice()
|
||||||
} else {
|
} 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.insert(font_key.clone(), font_ids);
|
||||||
lock.font_ids_by_font_key[&font_key].as_ref()
|
lock.font_ids_by_font_key[&font_key].as_ref()
|
||||||
};
|
};
|
||||||
|
@ -219,7 +219,11 @@ impl MacTextSystemState {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_family(&mut self, name: &str, features: FontFeatures) -> Result<SmallVec<[FontId; 4]>> {
|
fn load_family(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
features: &FontFeatures,
|
||||||
|
) -> Result<SmallVec<[FontId; 4]>> {
|
||||||
let name = if name == ".SystemUIFont" {
|
let name = if name == ".SystemUIFont" {
|
||||||
".AppleSystemUIFont"
|
".AppleSystemUIFont"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -262,7 +262,7 @@ impl TextStyle {
|
||||||
pub fn font(&self) -> Font {
|
pub fn font(&self) -> Font {
|
||||||
Font {
|
Font {
|
||||||
family: self.font_family.clone(),
|
family: self.font_family.clone(),
|
||||||
features: self.font_features,
|
features: self.font_features.clone(),
|
||||||
weight: self.font_weight,
|
weight: self.font_weight,
|
||||||
style: self.font_style,
|
style: self.font_style,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use crate::SharedString;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use itertools::Itertools;
|
||||||
use schemars::{
|
use schemars::{
|
||||||
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
|
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
|
||||||
JsonSchema,
|
JsonSchema,
|
||||||
|
@ -7,10 +11,14 @@ macro_rules! create_definitions {
|
||||||
($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
|
($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
|
||||||
|
|
||||||
/// The OpenType features that can be configured for a given font.
|
/// 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 {
|
pub struct FontFeatures {
|
||||||
enabled: u64,
|
enabled: u64,
|
||||||
disabled: u64,
|
disabled: u64,
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
other_enabled: SharedString,
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
other_disabled: SharedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontFeatures {
|
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::<String>(), true));
|
||||||
|
}
|
||||||
|
for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() {
|
||||||
|
result.push((name.collect::<String>(), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +75,15 @@ macro_rules! create_definitions {
|
||||||
debug.field(stringify!($name), &value);
|
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::<String>().as_str(), &true);
|
||||||
|
}
|
||||||
|
for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() {
|
||||||
|
debug.field(name.collect::<String>().as_str(), &false);
|
||||||
|
}
|
||||||
|
}
|
||||||
debug.finish()
|
debug.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +105,7 @@ macro_rules! create_definitions {
|
||||||
formatter.write_str("a map of font features")
|
formatter.write_str("a map of font features")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
where
|
where
|
||||||
M: MapAccess<'de>,
|
M: MapAccess<'de>,
|
||||||
|
@ -100,6 +126,54 @@ macro_rules! create_definitions {
|
||||||
}
|
}
|
||||||
Ok(FontFeatures { enabled, disabled })
|
Ok(FontFeatures { enabled, disabled })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
|
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::<String, Option<bool>>()? {
|
||||||
|
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)?;
|
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::<String>().as_str(), &true)?;
|
||||||
|
}
|
||||||
|
for name in self.other_disabled.as_ref().chars().chunks(4).into_iter() {
|
||||||
|
map.serialize_entry(name.collect::<String>().as_str(), &false)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,7 @@ impl PickerDelegate for OutlineViewDelegate {
|
||||||
let text_style = TextStyle {
|
let text_style = TextStyle {
|
||||||
color: cx.theme().colors().text,
|
color: cx.theme().colors().text,
|
||||||
font_family: settings.buffer_font.family.clone(),
|
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_size: settings.buffer_font_size(cx).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -114,7 +114,7 @@ impl BufferSearchBar {
|
||||||
color
|
color
|
||||||
},
|
},
|
||||||
font_family: settings.buffer_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -1307,7 +1307,7 @@ impl ProjectSearchBar {
|
||||||
cx.theme().colors().text
|
cx.theme().colors().text
|
||||||
},
|
},
|
||||||
font_family: settings.buffer_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
|
@ -578,7 +578,8 @@ impl Element for TerminalElement {
|
||||||
|
|
||||||
let font_features = terminal_settings
|
let font_features = terminal_settings
|
||||||
.font_features
|
.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 line_height = terminal_settings.line_height.value();
|
||||||
let font_size = terminal_settings.font_size;
|
let font_size = terminal_settings.font_size;
|
||||||
|
|
|
@ -325,13 +325,13 @@ impl settings::Settings for ThemeSettings {
|
||||||
ui_font_size: defaults.ui_font_size.unwrap().into(),
|
ui_font_size: defaults.ui_font_size.unwrap().into(),
|
||||||
ui_font: Font {
|
ui_font: Font {
|
||||||
family: defaults.ui_font_family.clone().unwrap().into(),
|
family: defaults.ui_font_family.clone().unwrap().into(),
|
||||||
features: defaults.ui_font_features.unwrap(),
|
features: defaults.ui_font_features.clone().unwrap(),
|
||||||
weight: Default::default(),
|
weight: Default::default(),
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
},
|
},
|
||||||
buffer_font: Font {
|
buffer_font: Font {
|
||||||
family: defaults.buffer_font_family.clone().unwrap().into(),
|
family: defaults.buffer_font_family.clone().unwrap().into(),
|
||||||
features: defaults.buffer_font_features.unwrap(),
|
features: defaults.buffer_font_features.clone().unwrap(),
|
||||||
weight: FontWeight::default(),
|
weight: FontWeight::default(),
|
||||||
style: FontStyle::default(),
|
style: FontStyle::default(),
|
||||||
},
|
},
|
||||||
|
@ -349,14 +349,14 @@ impl settings::Settings for ThemeSettings {
|
||||||
if let Some(value) = value.buffer_font_family.clone() {
|
if let Some(value) = value.buffer_font_family.clone() {
|
||||||
this.buffer_font.family = value.into();
|
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;
|
this.buffer_font.features = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(value) = value.ui_font_family.clone() {
|
if let Some(value) = value.ui_font_family.clone() {
|
||||||
this.ui_font.family = value.into();
|
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;
|
this.ui_font.features = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl Render for TextField {
|
||||||
|
|
||||||
let text_style = TextStyle {
|
let text_style = TextStyle {
|
||||||
font_family: settings.buffer_font.family.clone(),
|
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_size: rems(0.875).into(),
|
||||||
font_weight: FontWeight::NORMAL,
|
font_weight: FontWeight::NORMAL,
|
||||||
font_style: FontStyle::Normal,
|
font_style: FontStyle::Normal,
|
||||||
|
|
Loading…
Reference in a new issue