Cargo.lock 🔗
@@ -3243,6 +3243,7 @@ dependencies = [
"async-task",
"backtrace",
"bindgen 0.65.1",
+ "bitflags 2.4.0",
"block",
"bytemuck",
"cbindgen",
Nathan Sobo created
Cargo.lock | 1
crates/gpui3/Cargo.toml | 1
crates/gpui3/src/app.rs | 5
crates/gpui3/src/gpui3.rs | 2
crates/gpui3/src/platform.rs | 44 +++-
crates/gpui3/src/platform/mac/open_type.rs | 73 ++++----
crates/gpui3/src/platform/mac/screen.rs | 4
crates/gpui3/src/platform/mac/text_system.rs | 150 ++++++++++++-------
crates/gpui3/src/text_system.rs | 113 ++++++--------
crates/gpui3/src/text_system/font_features.rs | 162 +++++++++++++++++++++
crates/gpui3/src/text_system/line_wrapper.rs | 4
11 files changed, 377 insertions(+), 182 deletions(-)
@@ -3243,6 +3243,7 @@ dependencies = [
"async-task",
"backtrace",
"bindgen 0.65.1",
+ "bitflags 2.4.0",
"block",
"bytemuck",
"cbindgen",
@@ -58,6 +58,7 @@ slotmap = "1.0.6"
bytemuck = { version = "1.14.0", features = ["derive"] }
schemars.workspace = true
plane-split = "0.18.0"
+bitflags = "2.4.0"
[dev-dependencies]
backtrace = "0.3"
@@ -13,6 +13,7 @@ use std::{
marker::PhantomData,
sync::{Arc, Weak},
};
+use util::ResultExt;
#[derive(Clone)]
pub struct App(Arc<Mutex<AppContext>>);
@@ -173,7 +174,9 @@ impl AppContext {
.collect::<Vec<_>>();
for dirty_window_id in dirty_window_ids {
- self.update_window(dirty_window_id, |cx| cx.draw());
+ self.update_window(dirty_window_id, |cx| cx.draw())
+ .unwrap() // We know we have the window.
+ .log_err();
}
}
@@ -77,7 +77,7 @@ impl<T> Flatten<T> for Result<T> {
}
}
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, Hash)]
pub struct SharedString(ArcCow<'static, str>);
impl Default for SharedString {
@@ -6,8 +6,8 @@ mod mac;
mod test;
use crate::{
- AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, GlyphId,
- LineLayout, Pixels, Point, Result, RunStyle, Scene, SharedString, Size,
+ AnyWindowHandle, Bounds, FontFeatures, FontId, FontStyle, FontWeight, GlyphId, LineLayout,
+ Pixels, Point, Result, RunStyle, Scene, SharedString, Size,
};
use anyhow::anyhow;
use async_task::Runnable;
@@ -25,7 +25,6 @@ use std::{
str::FromStr,
sync::Arc,
};
-pub use time::UtcOffset;
use uuid::Uuid;
pub use events::*;
@@ -34,6 +33,7 @@ pub use keystroke::*;
pub use mac::*;
#[cfg(any(test, feature = "test"))]
pub use test::*;
+pub use time::UtcOffset;
#[cfg(target_os = "macos")]
pub(crate) fn current_platform() -> Arc<dyn Platform> {
@@ -154,19 +154,12 @@ pub trait PlatformDispatcher: Send + Sync {
}
pub trait PlatformTextSystem: Send + Sync {
- fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()>;
- fn all_families(&self) -> Vec<String>;
- fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>>;
- fn select_font(
- &self,
- font_ids: &[FontId],
- weight: FontWeight,
- style: FontStyle,
- ) -> anyhow::Result<FontId>;
+ fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()>;
+ fn all_font_families(&self) -> Vec<String>;
+ fn select_font(&self, descriptor: FontDescriptor) -> Result<FontId>;
fn font_metrics(&self, font_id: FontId) -> FontMetrics;
- fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId)
- -> anyhow::Result<Bounds<f32>>;
- fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>>;
+ fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>>;
+ fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>>;
fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
fn rasterize_glyph(
&self,
@@ -404,3 +397,24 @@ impl ClipboardItem {
hasher.finish()
}
}
+
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub struct FontDescriptor {
+ family: SharedString,
+ features: FontFeatures,
+ weight: FontWeight,
+ style: FontStyle,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct FontMetrics {
+ pub units_per_em: u32,
+ pub ascent: f32,
+ pub descent: f32,
+ pub line_gap: f32,
+ pub underline_position: f32,
+ pub underline_thickness: f32,
+ pub cap_height: f32,
+ pub x_height: f32,
+ pub bounding_box: Bounds<f32>,
+}
@@ -1,7 +1,5 @@
#![allow(unused, non_upper_case_globals)]
-use std::ptr;
-
use crate::FontFeatures;
use cocoa::appkit::CGFloat;
use core_foundation::{base::TCFType, number::CFNumber};
@@ -13,6 +11,7 @@ use core_text::{
},
};
use font_kit::font::Font;
+use std::ptr;
const kCaseSensitiveLayoutOffSelector: i32 = 1;
const kCaseSensitiveLayoutOnSelector: i32 = 0;
@@ -108,243 +107,243 @@ 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(
font,
- features.calt,
+ features.calt(),
kContextualAlternatesType,
kContextualAlternatesOnSelector,
kContextualAlternatesOffSelector,
);
toggle_open_type_feature(
font,
- features.case,
+ features.case(),
kCaseSensitiveLayoutType,
kCaseSensitiveLayoutOnSelector,
kCaseSensitiveLayoutOffSelector,
);
toggle_open_type_feature(
font,
- features.cpsp,
+ features.cpsp(),
kCaseSensitiveLayoutType,
kCaseSensitiveSpacingOnSelector,
kCaseSensitiveSpacingOffSelector,
);
toggle_open_type_feature(
font,
- features.frac,
+ features.frac(),
kFractionsType,
kDiagonalFractionsSelector,
kNoFractionsSelector,
);
toggle_open_type_feature(
font,
- features.liga,
+ features.liga(),
kLigaturesType,
kCommonLigaturesOnSelector,
kCommonLigaturesOffSelector,
);
toggle_open_type_feature(
font,
- features.onum,
+ features.onum(),
kNumberCaseType,
kLowerCaseNumbersSelector,
2,
);
toggle_open_type_feature(
font,
- features.ordn,
+ features.ordn(),
kVerticalPositionType,
kOrdinalsSelector,
kNormalPositionSelector,
);
toggle_open_type_feature(
font,
- features.pnum,
+ features.pnum(),
kNumberSpacingType,
kProportionalNumbersSelector,
4,
);
toggle_open_type_feature(
font,
- features.ss01,
+ features.ss01(),
kStylisticAlternativesType,
kStylisticAltOneOnSelector,
kStylisticAltOneOffSelector,
);
toggle_open_type_feature(
font,
- features.ss02,
+ features.ss02(),
kStylisticAlternativesType,
kStylisticAltTwoOnSelector,
kStylisticAltTwoOffSelector,
);
toggle_open_type_feature(
font,
- features.ss03,
+ features.ss03(),
kStylisticAlternativesType,
kStylisticAltThreeOnSelector,
kStylisticAltThreeOffSelector,
);
toggle_open_type_feature(
font,
- features.ss04,
+ features.ss04(),
kStylisticAlternativesType,
kStylisticAltFourOnSelector,
kStylisticAltFourOffSelector,
);
toggle_open_type_feature(
font,
- features.ss05,
+ features.ss05(),
kStylisticAlternativesType,
kStylisticAltFiveOnSelector,
kStylisticAltFiveOffSelector,
);
toggle_open_type_feature(
font,
- features.ss06,
+ features.ss06(),
kStylisticAlternativesType,
kStylisticAltSixOnSelector,
kStylisticAltSixOffSelector,
);
toggle_open_type_feature(
font,
- features.ss07,
+ features.ss07(),
kStylisticAlternativesType,
kStylisticAltSevenOnSelector,
kStylisticAltSevenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss08,
+ features.ss08(),
kStylisticAlternativesType,
kStylisticAltEightOnSelector,
kStylisticAltEightOffSelector,
);
toggle_open_type_feature(
font,
- features.ss09,
+ features.ss09(),
kStylisticAlternativesType,
kStylisticAltNineOnSelector,
kStylisticAltNineOffSelector,
);
toggle_open_type_feature(
font,
- features.ss10,
+ features.ss10(),
kStylisticAlternativesType,
kStylisticAltTenOnSelector,
kStylisticAltTenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss11,
+ features.ss11(),
kStylisticAlternativesType,
kStylisticAltElevenOnSelector,
kStylisticAltElevenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss12,
+ features.ss12(),
kStylisticAlternativesType,
kStylisticAltTwelveOnSelector,
kStylisticAltTwelveOffSelector,
);
toggle_open_type_feature(
font,
- features.ss13,
+ features.ss13(),
kStylisticAlternativesType,
kStylisticAltThirteenOnSelector,
kStylisticAltThirteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss14,
+ features.ss14(),
kStylisticAlternativesType,
kStylisticAltFourteenOnSelector,
kStylisticAltFourteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss15,
+ features.ss15(),
kStylisticAlternativesType,
kStylisticAltFifteenOnSelector,
kStylisticAltFifteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss16,
+ features.ss16(),
kStylisticAlternativesType,
kStylisticAltSixteenOnSelector,
kStylisticAltSixteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss17,
+ features.ss17(),
kStylisticAlternativesType,
kStylisticAltSeventeenOnSelector,
kStylisticAltSeventeenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss18,
+ features.ss18(),
kStylisticAlternativesType,
kStylisticAltEighteenOnSelector,
kStylisticAltEighteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss19,
+ features.ss19(),
kStylisticAlternativesType,
kStylisticAltNineteenOnSelector,
kStylisticAltNineteenOffSelector,
);
toggle_open_type_feature(
font,
- features.ss20,
+ features.ss20(),
kStylisticAlternativesType,
kStylisticAltTwentyOnSelector,
kStylisticAltTwentyOffSelector,
);
toggle_open_type_feature(
font,
- features.subs,
+ features.subs(),
kVerticalPositionType,
kInferiorsSelector,
kNormalPositionSelector,
);
toggle_open_type_feature(
font,
- features.sups,
+ features.sups(),
kVerticalPositionType,
kSuperiorsSelector,
kNormalPositionSelector,
);
toggle_open_type_feature(
font,
- features.swsh,
+ features.swsh(),
kContextualAlternatesType,
kSwashAlternatesOnSelector,
kSwashAlternatesOffSelector,
);
toggle_open_type_feature(
font,
- features.titl,
+ features.titl(),
kStyleOptionsType,
kTitlingCapsSelector,
kNoStyleOptionsSelector,
);
toggle_open_type_feature(
font,
- features.tnum,
+ features.tnum(),
kNumberSpacingType,
kMonospacedNumbersSelector,
4,
);
toggle_open_type_feature(
font,
- features.zero,
+ features.zero(),
kTypographicExtrasType,
kSlashedZeroOnSelector,
kSlashedZeroOffSelector,
@@ -1,7 +1,5 @@
use super::ns_string;
-use crate::{
- platform, point, px, size, Bounds, Pixels, PlatformScreen, PlatformScreenHandle, ScreenId,
-};
+use crate::{point, px, size, Bounds, Pixels, PlatformScreen, PlatformScreenHandle, ScreenId};
use cocoa::{
appkit::NSScreen,
base::{id, nil},
@@ -1,7 +1,7 @@
use crate::{
- point, px, size, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, Glyph,
- GlyphId, LineLayout, Pixels, PlatformTextSystem, Point, RasterizationOptions, Run, RunStyle,
- Size,
+ platform::FontDescriptor, point, px, size, Bounds, FontFeatures, FontId, FontMetrics,
+ FontStyle, FontWeight, Glyph, GlyphId, LineLayout, Pixels, PlatformTextSystem, Point,
+ RasterizationOptions, Result, Run, RunStyle, SharedString, Size,
};
use cocoa::appkit::{CGFloat, CGPoint};
use collections::HashMap;
@@ -31,6 +31,7 @@ use pathfinder_geometry::{
transform2d::Transform2F,
vector::{Vector2F, Vector2I},
};
+use smallvec::SmallVec;
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, sync::Arc};
use super::open_type;
@@ -44,7 +45,9 @@ struct TextSystemState {
memory_source: MemSource,
system_source: SystemSource,
fonts: Vec<font_kit::font::Font>,
+ font_selections: HashMap<FontDescriptor, FontId>,
font_ids_by_postscript_name: HashMap<String, FontId>,
+ font_ids_by_family_name: HashMap<SharedString, SmallVec<[FontId; 4]>>,
postscript_names_by_font_id: HashMap<FontId, String>,
}
@@ -54,8 +57,10 @@ impl MacTextSystem {
memory_source: MemSource::empty(),
system_source: SystemSource::new(),
fonts: Vec::new(),
- font_ids_by_postscript_name: Default::default(),
- postscript_names_by_font_id: Default::default(),
+ font_selections: HashMap::default(),
+ font_ids_by_postscript_name: HashMap::default(),
+ font_ids_by_family_name: HashMap::default(),
+ postscript_names_by_font_id: HashMap::default(),
}))
}
}
@@ -67,11 +72,11 @@ impl Default for MacTextSystem {
}
impl PlatformTextSystem for MacTextSystem {
- fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()> {
+ fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()> {
self.0.write().add_fonts(fonts)
}
- fn all_families(&self) -> Vec<String> {
+ fn all_font_families(&self) -> Vec<String> {
self.0
.read()
.system_source
@@ -79,32 +84,49 @@ impl PlatformTextSystem for MacTextSystem {
.expect("core text should never return an error")
}
- fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>> {
- self.0.write().load_family(name, features)
- }
-
- fn select_font(
- &self,
- font_ids: &[FontId],
- weight: FontWeight,
- style: FontStyle,
- ) -> anyhow::Result<FontId> {
- self.0.read().select_font(font_ids, weight, style)
+ fn select_font(&self, descriptor: FontDescriptor) -> Result<FontId> {
+ let lock = self.0.upgradable_read();
+ if let Some(font_id) = lock.font_selections.get(&descriptor) {
+ Ok(*font_id)
+ } else {
+ let mut lock = parking_lot::RwLockUpgradableReadGuard::upgrade(lock);
+ let candidates =
+ if let Some(font_ids) = lock.font_ids_by_family_name.get(&descriptor.family) {
+ font_ids.as_slice()
+ } else {
+ let font_ids = lock.load_family(&descriptor.family, descriptor.features)?;
+ lock.font_ids_by_family_name
+ .insert(descriptor.family.clone(), font_ids);
+ lock.font_ids_by_family_name[&descriptor.family].as_ref()
+ };
+
+ let candidate_properties = candidates
+ .iter()
+ .map(|font_id| lock.fonts[font_id.0].properties())
+ .collect::<SmallVec<[_; 4]>>();
+
+ let ix = font_kit::matching::find_best_match(
+ &candidate_properties,
+ &font_kit::properties::Properties {
+ style: descriptor.style.into(),
+ weight: descriptor.weight.into(),
+ stretch: Default::default(),
+ },
+ )?;
+
+ Ok(candidates[ix])
+ }
}
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
self.0.read().font_metrics(font_id)
}
- fn typographic_bounds(
- &self,
- font_id: FontId,
- glyph_id: GlyphId,
- ) -> anyhow::Result<Bounds<f32>> {
+ fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
self.0.read().typographic_bounds(font_id, glyph_id)
}
- fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
+ fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
self.0.read().advance(font_id, glyph_id)
}
@@ -147,7 +169,7 @@ impl PlatformTextSystem for MacTextSystem {
}
impl TextSystemState {
- fn add_fonts(&mut self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()> {
+ fn add_fonts(&mut self, fonts: &[Arc<Vec<u8>>]) -> Result<()> {
self.memory_source.add_fonts(
fonts
.iter()
@@ -156,13 +178,16 @@ impl TextSystemState {
Ok(())
}
- fn load_family(&mut self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>> {
- let mut font_ids = Vec::new();
-
+ fn load_family(
+ &mut self,
+ name: &SharedString,
+ features: FontFeatures,
+ ) -> Result<SmallVec<[FontId; 4]>> {
+ let mut font_ids = SmallVec::new();
let family = self
.memory_source
- .select_family_by_name(name)
- .or_else(|_| self.system_source.select_family_by_name(name))?;
+ .select_family_by_name(name.as_ref())
+ .or_else(|_| self.system_source.select_family_by_name(name.as_ref()))?;
for font in family.fonts() {
let mut font = font.load()?;
open_type::apply_features(&mut font, features);
@@ -178,42 +203,53 @@ impl TextSystemState {
Ok(font_ids)
}
- fn select_font(
- &self,
- font_ids: &[FontId],
- weight: FontWeight,
- style: FontStyle,
- ) -> anyhow::Result<FontId> {
- let candidates = font_ids
- .iter()
- .map(|font_id| self.fonts[font_id.0].properties())
- .collect::<Vec<_>>();
- let idx = font_kit::matching::find_best_match(
- &candidates,
- &font_kit::properties::Properties {
- style: style.into(),
- weight: weight.into(),
- stretch: Default::default(),
- },
- )?;
- Ok(font_ids[idx])
- }
+ // fn select_font(
+ // &mut self,
+ // family: &SharedString,
+ // weight: FontWeight,
+ // style: FontStyle,
+ // features: FontFeatures,
+ // ) -> Result<FontId> {
+ // let candidates = if let Some(font_ids) = self.font_ids_by_family_name.get(family) {
+ // font_ids
+ // } else {
+ // let font_ids = if let Some(font_ids) = self.font_ids_by_family_name.get(family) {
+ // font_ids.as_slice()
+ // } else {
+ // self.font_ids_by_family_name
+ // .insert(family.clone())
+ // .or_insert(font_ids).as_slice()
+ // };
+
+ // };
+
+ // let font_properties = candidates
+ // .iter()
+ // .map(|font_id| self.fonts[font_id.0].properties())
+ // .collect::<SmallVec<[_; 4]>>();
+
+ // // let idx = font_kit::matching::find_best_match(
+ // // &candidates,
+ // // &font_kit::properties::Properties {
+ // // style: style.into(),
+ // // weight: weight.into(),
+ // // stretch: Default::default(),
+ // // },
+ // // )?;
+ // // Ok(font_ids[idx])
+ // }
fn font_metrics(&self, font_id: FontId) -> FontMetrics {
self.fonts[font_id.0].metrics().into()
}
- fn typographic_bounds(
- &self,
- font_id: FontId,
- glyph_id: GlyphId,
- ) -> anyhow::Result<Bounds<f32>> {
+ fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
Ok(self.fonts[font_id.0]
.typographic_bounds(glyph_id.into())?
.into())
}
- fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
+ fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
Ok(self.fonts[font_id.0].advance(glyph_id.into())?.into())
}
@@ -659,7 +695,7 @@ impl From<FontStyle> for FontkitStyle {
// }
// #[test]
-// fn test_glyph_offsets() -> anyhow::Result<()> {
+// fn test_glyph_offsets() -> crate::Result<()> {
// let fonts = FontSystem::new();
// let zapfino = fonts.load_family("Zapfino", &Default::default())?;
// let zapfino_regular = RunStyle {
@@ -1,11 +1,9 @@
-mod font_cache;
+mod font_features;
mod line_wrapper;
mod text_layout_cache;
-pub use font_cache::*;
+pub use font_features::*;
use line_wrapper::*;
-use schemars::JsonSchema;
-use serde_derive::{Deserialize, Serialize};
pub use text_layout_cache::*;
use crate::{Hsla, Pixels, PlatformTextSystem, Point, Result, Size, UnderlineStyle};
@@ -19,8 +17,13 @@ use std::{
sync::Arc,
};
+#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
+pub struct FontId(pub usize);
+
+#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
+pub struct FontFamilyId(pub usize);
+
pub struct TextSystem {
- font_cache: Arc<FontCache>,
text_layout_cache: Arc<TextLayoutCache>,
platform_text_system: Arc<dyn PlatformTextSystem>,
wrapper_pool: Mutex<HashMap<(FontId, Pixels), Vec<LineWrapper>>>,
@@ -29,7 +32,7 @@ pub struct TextSystem {
impl TextSystem {
pub fn new(platform_text_system: Arc<dyn PlatformTextSystem>) -> Self {
TextSystem {
- font_cache: Arc::new(FontCache::new(platform_text_system.clone())),
+ // font_cache: Arc::new(FontCache::new(platform_text_system.clone())),
text_layout_cache: Arc::new(TextLayoutCache::new(platform_text_system.clone())),
platform_text_system,
wrapper_pool: Mutex::new(HashMap::default()),
@@ -37,7 +40,8 @@ impl TextSystem {
}
pub fn font_family_name(&self, family_id: FontFamilyId) -> Result<Arc<str>> {
- self.font_cache.family_name(family_id)
+ todo!()
+ // self.font_cache.family_name(family_id)
}
pub fn load_font_family(
@@ -45,16 +49,19 @@ impl TextSystem {
names: &[&str],
features: &FontFeatures,
) -> Result<FontFamilyId> {
- self.font_cache.load_family(names, features)
+ todo!()
+ // self.font_cache.load_family(names, features)
}
/// Returns an arbitrary font family that is available on the system.
pub fn known_existing_font_family(&self) -> FontFamilyId {
- self.font_cache.known_existing_family()
+ todo!()
+ // self.font_cache.known_existing_family()
}
pub fn default_font(&self, family_id: FontFamilyId) -> FontId {
- self.font_cache.default_font(family_id)
+ todo!()
+ // self.font_cache.default_font(family_id)
}
pub fn select_font(
@@ -63,55 +70,67 @@ impl TextSystem {
weight: FontWeight,
style: FontStyle,
) -> Result<FontId> {
- self.font_cache.select_font(family_id, weight, style)
+ todo!()
+ // self.font_cache.select_font(family_id, weight, style)
}
- pub fn read_font_metric<F, T>(&self, font_id: FontId, f: F) -> T
- where
- F: FnOnce(&FontMetrics) -> T,
- T: 'static,
- {
- self.font_cache.read_metric(font_id, f)
- }
+ // pub fn read_font_metric<F, T>(&self, font_id: FontId, f: F) -> T
+ // where
+ // F: FnOnce(&FontMetrics) -> T,
+ // T: 'static,
+ // {
+ // todo!()
+ // // self.font_cache.read_metric(font_id, f)
+ // }
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Size<Pixels> {
- self.font_cache.bounding_box(font_id, font_size)
+ todo!()
+ // self.font_cache.bounding_box(font_id, font_size)
}
pub fn em_width(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.em_width(font_id, font_size)
+ todo!()
+ // self.font_cache.em_width(font_id, font_size)
}
pub fn em_advance(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.em_advance(font_id, font_size)
+ todo!()
+ // self.font_cache.em_advance(font_id, font_size)
}
pub fn line_height(&self, font_size: Pixels) -> Pixels {
- self.font_cache.line_height(font_size)
+ todo!()
+ // self.font_cache.line_height(font_size)
}
pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.cap_height(font_id, font_size)
+ todo!()
+ // self.font_cache.cap_height(font_id, font_size)
}
pub fn x_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.x_height(font_id, font_size)
+ todo!()
+ // self.font_cache.x_height(font_id, font_size)
}
pub fn ascent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.ascent(font_id, font_size)
+ todo!()
+ // self.font_cache.ascent(font_id, font_size)
}
pub fn descent(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.descent(font_id, font_size)
+ todo!()
+ // self.font_cache.descent(font_id, font_size)
}
pub fn em_size(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.em_size(font_id, font_size)
+ todo!()
+ // self.font_cache.em_size(font_id, font_size)
}
pub fn baseline_offset(&self, font_id: FontId, font_size: Pixels) -> Pixels {
- self.font_cache.baseline_offset(font_id, font_size)
+ todo!()
+ // self.font_cache.baseline_offset(font_id, font_size)
}
pub fn layout_str<'a>(
@@ -235,44 +254,6 @@ impl Display for FontStyle {
}
}
-#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
-pub struct FontFeatures {
- 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, PartialEq, Eq)]
pub struct RunStyle {
pub color: Hsla,
@@ -0,0 +1,162 @@
+use schemars::{
+ schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
+ JsonSchema,
+};
+
+macro_rules! create_definitions {
+ ($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
+ #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
+ pub struct FontFeatures {
+ enabled: u64,
+ disabled: u64,
+ }
+
+ impl FontFeatures {
+ $(
+ pub fn $name(&self) -> Option<bool> {
+ if (self.enabled & (1 << $idx)) != 0 {
+ Some(true)
+ } else if (self.disabled & (1 << $idx)) != 0 {
+ Some(false)
+ } else {
+ None
+ }
+ }
+ )*
+ }
+
+ impl std::fmt::Debug for FontFeatures {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut debug = f.debug_struct("FontFeatures");
+ $(
+ if let Some(value) = self.$name() {
+ debug.field(stringify!($name), &value);
+ };
+ )*
+ debug.finish()
+ }
+ }
+
+ impl<'de> serde::Deserialize<'de> for FontFeatures {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ use serde::de::{MapAccess, Visitor};
+ use std::fmt;
+
+ struct FontFeaturesVisitor;
+
+ impl<'de> Visitor<'de> for FontFeaturesVisitor {
+ type Value = FontFeatures;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("a map of font features")
+ }
+
+ 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;
+
+ while let Some((key, value)) = access.next_entry::<String, Option<bool>>()? {
+ let idx = match key.as_str() {
+ $(stringify!($name) => $idx,)*
+ _ => continue,
+ };
+ match value {
+ Some(true) => enabled |= 1 << idx,
+ Some(false) => disabled |= 1 << idx,
+ None => {}
+ };
+ }
+ Ok(FontFeatures { enabled, disabled })
+ }
+ }
+
+ let features = deserializer.deserialize_map(FontFeaturesVisitor)?;
+ Ok(features)
+ }
+ }
+
+ impl serde::Serialize for FontFeatures {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeMap;
+
+ let mut map = serializer.serialize_map(None)?;
+
+ $(
+ let feature = stringify!($name);
+ if let Some(value) = self.$name() {
+ map.serialize_entry(feature, &value)?;
+ }
+ )*
+
+ map.end()
+ }
+ }
+
+ impl JsonSchema for FontFeatures {
+ fn schema_name() -> String {
+ "FontFeatures".into()
+ }
+
+ fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
+ let mut schema = SchemaObject::default();
+ let properties = &mut schema.object().properties;
+ let feature_schema = Schema::Object(SchemaObject {
+ instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Boolean))),
+ ..Default::default()
+ });
+
+ $(
+ properties.insert(stringify!($name).to_owned(), feature_schema.clone());
+ )*
+
+ schema.into()
+ }
+ }
+ };
+}
+
+create_definitions!(
+ (calt, 0),
+ (case, 1),
+ (cpsp, 2),
+ (frac, 3),
+ (liga, 4),
+ (onum, 5),
+ (ordn, 6),
+ (pnum, 7),
+ (ss01, 8),
+ (ss02, 9),
+ (ss03, 10),
+ (ss04, 11),
+ (ss05, 12),
+ (ss06, 13),
+ (ss07, 14),
+ (ss08, 15),
+ (ss09, 16),
+ (ss10, 17),
+ (ss11, 18),
+ (ss12, 19),
+ (ss13, 20),
+ (ss14, 21),
+ (ss15, 22),
+ (ss16, 23),
+ (ss17, 24),
+ (ss18, 25),
+ (ss19, 26),
+ (ss20, 27),
+ (subs, 28),
+ (sups, 29),
+ (swsh, 30),
+ (titl, 31),
+ (tnum, 32),
+ (zero, 33)
+);
@@ -215,7 +215,7 @@ impl Boundary {
#[cfg(test)]
mod tests {
use super::*;
- use crate::{App, FontWeight};
+ use crate::{App, FontFeatures, FontWeight};
#[test]
fn test_wrap_line() {
@@ -291,7 +291,7 @@ mod tests {
let text_system = cx.text_system().clone();
let family = text_system
- .load_font_family(&["Helvetica"], &Default::default())
+ .load_font_family(&["Helvetica"], &FontFeatures::default())
.unwrap();
let font_id = text_system
.select_font(family, Default::default(), Default::default())