diff --git a/Cargo.lock b/Cargo.lock index d13d45beeb..934599122b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1917,6 +1917,27 @@ dependencies = [ "bindgen 0.64.0", ] +[[package]] +name = "cosmic-text" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75acbfb314aeb4f5210d379af45ed1ec2c98c7f1790bf57b8a4c562ac0c51b71" +dependencies = [ + "fontdb 0.15.0", + "libm", + "log", + "rangemap", + "rustc-hash", + "rustybuzz 0.11.0", + "self_cell", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + [[package]] name = "cpal" version = "0.15.2" @@ -2875,6 +2896,21 @@ dependencies = [ "yeslogic-fontconfig-sys", ] +[[package]] +name = "font-types" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd7f3ea17572640b606b35df42cfb6ecdf003704b062580e59918692190b73d" + +[[package]] +name = "fontconfig-parser" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" +dependencies = [ + "roxmltree 0.19.0", +] + [[package]] name = "fontdb" version = "0.5.4" @@ -2882,10 +2918,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e58903f4f8d5b58c7d300908e4ebe5289c1bfdf5587964330f12023b8ff17fd1" dependencies = [ "log", - "memmap2", + "memmap2 0.2.3", "ttf-parser 0.12.3", ] +[[package]] +name = "fontdb" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2 0.8.0", + "slotmap", + "tinyvec", + "ttf-parser 0.19.2", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -3385,6 +3435,7 @@ dependencies = [ "core-foundation", "core-graphics 0.22.3", "core-text", + "cosmic-text", "ctor", "derive_more", "dhat", @@ -4278,9 +4329,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmimalloc-sys" @@ -4614,6 +4665,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -6397,6 +6457,12 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rangemap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -6453,6 +6519,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be9e29cb19c8fe84169fcb07f8f11e66bc9e6e0280efd4715c54818296f8a4a8" +[[package]] +name = "read-fonts" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1362980db95801b70031dd592dc052a44b1810ca9da8fbcf7b25983f3174ed0" +dependencies = [ + "font-types", +] + [[package]] name = "recent_projects" version = "0.1.0" @@ -6791,6 +6866,12 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "roxmltree" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" + [[package]] name = "rpc" version = "0.1.0" @@ -7041,6 +7122,23 @@ dependencies = [ "unicode-script", ] +[[package]] +name = "rustybuzz" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "libm", + "smallvec", + "ttf-parser 0.20.0", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + [[package]] name = "ryu" version = "1.0.15" @@ -7297,6 +7395,12 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" + [[package]] name = "semantic_index" version = "0.1.0" @@ -8248,6 +8352,17 @@ dependencies = [ "siphasher 0.2.3", ] +[[package]] +name = "swash" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06ff4664af8923625604261c645f5c4cc610cc83c84bec74b50d76237089de7" +dependencies = [ + "read-fonts", + "yazi", + "zeno", +] + [[package]] name = "syn" version = "1.0.109" @@ -8286,6 +8401,15 @@ dependencies = [ "libc", ] +[[package]] +name = "sys-locale" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +dependencies = [ + "libc", +] + [[package]] name = "sysinfo" version = "0.29.10" @@ -9393,6 +9517,18 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" +[[package]] +name = "ttf-parser" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" + +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + [[package]] name = "tungstenite" version = "0.16.0" @@ -9495,6 +9631,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -9504,6 +9646,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unicode-script" version = "0.5.5" @@ -9579,14 +9727,14 @@ dependencies = [ "base64 0.13.1", "data-url", "flate2", - "fontdb", + "fontdb 0.5.4", "kurbo", "log", - "memmap2", + "memmap2 0.2.3", "pico-args", "rctree", - "roxmltree", - "rustybuzz", + "roxmltree 0.14.1", + "rustybuzz 0.3.0", "simplecss", "siphasher 0.2.3", "svgtypes", @@ -10564,6 +10712,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yazi" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" + [[package]] name = "yeslogic-fontconfig-sys" version = "3.2.0" @@ -10733,6 +10887,12 @@ dependencies = [ "serde", ] +[[package]] +name = "zeno" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" + [[package]] name = "zeroize" version = "1.6.0" diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 2b00049ec6..1bf95cfc33 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -102,3 +102,4 @@ as-raw-xcb-connection = "1" blade-graphics = { git = "https://github.com/kvark/blade", rev = "26bc5e8b9ef67b4f2970eb95888db733eace98f3" } blade-macros = { git = "https://github.com/kvark/blade", rev = "26bc5e8b9ef67b4f2970eb95888db733eace98f3" } bytemuck = "1" +cosmic-text = "0.10.0" \ No newline at end of file diff --git a/crates/gpui/src/platform/linux/text_system.rs b/crates/gpui/src/platform/linux/text_system.rs index 885a6b1736..574f65381d 100644 --- a/crates/gpui/src/platform/linux/text_system.rs +++ b/crates/gpui/src/platform/linux/text_system.rs @@ -1,40 +1,49 @@ //todo!(linux) remove #[allow(unused)] +use crate::{point, size, FontStyle, FontWeight, Point, ShapedGlyph}; use crate::{ - Bounds, DevicePixels, Font, FontId, FontMetrics, FontRun, GlyphId, LineLayout, Pixels, - PlatformTextSystem, RenderGlyphParams, SharedString, Size, + Bounds, DevicePixels, Font, FontFeatures, FontId, FontMetrics, FontRun, GlyphId, LineLayout, + Pixels, PlatformTextSystem, RenderGlyphParams, SharedString, Size, }; +use anyhow::Ok; use anyhow::Result; +use anyhow::{anyhow, Context}; use collections::HashMap; -use font_kit::{font::Font as FontKitFont, source::SystemSource, sources::mem::MemSource}; -use parking_lot::RwLock; +use cosmic_text::fontdb::Query; +use cosmic_text::{ + Attrs, AttrsList, BufferLine, CacheKey, Family, Font as CosmicTextFont, FontSystem, SwashCache, +}; +use parking_lot::{RwLock, RwLockUpgradableReadGuard}; +use pathfinder_geometry::rect::RectF; +use pathfinder_geometry::rect::RectI; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; use smallvec::SmallVec; -use std::borrow::Cow; +use std::{borrow::Cow, sync::Arc}; pub(crate) struct LinuxTextSystem(RwLock); struct LinuxTextSystemState { - memory_source: MemSource, - system_source: SystemSource, - fonts: Vec, + swash_cache: SwashCache, + font_system: FontSystem, + fonts: Vec>, font_selections: HashMap, - font_ids_by_postscript_name: HashMap, font_ids_by_family_name: HashMap>, postscript_names_by_font_id: HashMap, } -// todo!(linux): Double check this -unsafe impl Send for LinuxTextSystemState {} -unsafe impl Sync for LinuxTextSystemState {} - impl LinuxTextSystem { pub(crate) fn new() -> Self { + let mut font_system = FontSystem::new(); + + // todo!(linux) make font loading non-blocking + font_system.db_mut().load_system_fonts(); + Self(RwLock::new(LinuxTextSystemState { - memory_source: MemSource::empty(), - system_source: SystemSource::new(), + font_system, + swash_cache: SwashCache::new(), fonts: Vec::new(), font_selections: HashMap::default(), - font_ids_by_postscript_name: HashMap::default(), + // font_ids_by_postscript_name: HashMap::default(), font_ids_by_family_name: HashMap::default(), postscript_names_by_font_id: HashMap::default(), })) @@ -49,14 +58,20 @@ impl Default for LinuxTextSystem { #[allow(unused)] impl PlatformTextSystem for LinuxTextSystem { - // todo!(linux) fn add_fonts(&self, fonts: Vec>) -> Result<()> { - Ok(()) + self.0.write().add_fonts(fonts) } - // todo!(linux) + // todo!(linux) ensure that this integrates with platform font loading + // do we need to do more than call load_system_fonts()? fn all_font_names(&self) -> Vec { - Vec::new() + self.0 + .read() + .font_system + .db() + .faces() + .map(|face| face.post_script_name.clone()) + .collect() } // todo!(linux) @@ -64,51 +79,112 @@ impl PlatformTextSystem for LinuxTextSystem { Vec::new() } - // todo!(linux) - fn font_id(&self, descriptor: &Font) -> Result { - Ok(FontId(0)) + fn font_id(&self, font: &Font) -> Result { + // todo!(linux): Do we need to use CosmicText's Font APIs? Can we consolidate this to use font_kit? + let lock = self.0.upgradable_read(); + if let Some(font_id) = lock.font_selections.get(font) { + Ok(*font_id) + } else { + let mut lock = RwLockUpgradableReadGuard::upgrade(lock); + let candidates = if let Some(font_ids) = lock.font_ids_by_family_name.get(&font.family) + { + font_ids.as_slice() + } else { + let font_ids = lock.load_family(&font.family, font.features)?; + lock.font_ids_by_family_name + .insert(font.family.clone(), font_ids); + lock.font_ids_by_family_name[&font.family].as_ref() + }; + + let id = lock + .font_system + .db() + .query(&Query { + families: &[Family::Name(&font.family)], + weight: font.weight.into(), + style: font.style.into(), + stretch: Default::default(), + }) + .context("no font")?; + + let font_id = if let Some(font_id) = lock.fonts.iter().position(|font| font.id() == id) + { + FontId(font_id) + } else { + // Font isn't in fonts so add it there, this is because we query all the fonts in the db + // and maybe we haven't loaded it yet + let font_id = FontId(lock.fonts.len()); + let font = lock.font_system.get_font(id).unwrap(); + lock.fonts.push(font); + font_id + }; + + lock.font_selections.insert(font.clone(), font_id); + Ok(font_id) + } } - // todo!(linux) fn font_metrics(&self, font_id: FontId) -> FontMetrics { - unimplemented!() + let metrics = self.0.read().fonts[font_id.0].as_swash().metrics(&[]); + + FontMetrics { + units_per_em: metrics.units_per_em as u32, + ascent: metrics.ascent, + descent: -metrics.descent, // todo!(linux) confirm this is correct + line_gap: metrics.leading, + underline_position: metrics.underline_offset, + underline_thickness: metrics.stroke_size, + cap_height: metrics.cap_height, + x_height: metrics.x_height, + // todo!(linux): Compute this correctly + bounding_box: Bounds { + origin: point(0.0, 0.0), + size: size(metrics.max_width, metrics.ascent + metrics.descent), + }, + } } - // todo!(linux) fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { - unimplemented!() + let lock = self.0.read(); + let metrics = lock.fonts[font_id.0].as_swash().metrics(&[]); + let glyph_metrics = lock.fonts[font_id.0].as_swash().glyph_metrics(&[]); + let glyph_id = glyph_id.0 as u16; + // todo!(linux): Compute this correctly + // see https://github.com/servo/font-kit/blob/master/src/loaders/freetype.rs#L614-L620 + Ok(Bounds { + origin: point(0.0, 0.0), + size: size( + glyph_metrics.advance_width(glyph_id), + glyph_metrics.advance_height(glyph_id), + ), + }) } - // todo!(linux) fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { - unimplemented!() + self.0.read().advance(font_id, glyph_id) } - // todo!(linux) fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { - None + self.0.read().glyph_for_char(font_id, ch) } - // todo!(linux) fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result> { - unimplemented!() + self.0.write().raster_bounds(params) } - // todo!(linux) fn rasterize_glyph( &self, params: &RenderGlyphParams, raster_bounds: Bounds, ) -> Result<(Size, Vec)> { - unimplemented!() + self.0.write().rasterize_glyph(params, raster_bounds) } - // todo!(linux) fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout { - LineLayout::default() //TODO + self.0.write().layout_line(text, font_size, runs) } - // todo!(linux) + // todo!(linux) Confirm that this has been superseded by the LineWrapper fn wrap_line( &self, text: &str, @@ -119,3 +195,245 @@ impl PlatformTextSystem for LinuxTextSystem { unimplemented!() } } + +impl LinuxTextSystemState { + fn add_fonts(&mut self, fonts: Vec>) -> Result<()> { + let db = self.font_system.db_mut(); + for bytes in fonts { + match bytes { + Cow::Borrowed(embedded_font) => { + db.load_font_data(embedded_font.to_vec()); + } + Cow::Owned(bytes) => { + db.load_font_data(bytes); + } + } + } + Ok(()) + } + + fn load_family( + &mut self, + name: &SharedString, + _features: FontFeatures, + ) -> Result> { + let mut font_ids = SmallVec::new(); + let family = self + .font_system + .get_font_matches(Attrs::new().family(cosmic_text::Family::Name(name))); + for font in family.as_ref() { + let font = self.font_system.get_font(*font).unwrap(); + if font.as_swash().charmap().map('m') == 0 { + self.font_system.db_mut().remove_face(font.id()); + continue; + }; + + let font_id = FontId(self.fonts.len()); + font_ids.push(font_id); + self.fonts.push(font); + } + Ok(font_ids) + } + + fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result> { + let width = self.fonts[font_id.0] + .as_swash() + .glyph_metrics(&[]) + .advance_width(glyph_id.0 as u16); + let height = self.fonts[font_id.0] + .as_swash() + .glyph_metrics(&[]) + .advance_height(glyph_id.0 as u16); + Ok(Size { width, height }) + } + + fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { + let glyph_id = self.fonts[font_id.0].as_swash().charmap().map(ch); + if glyph_id == 0 { + None + } else { + Some(GlyphId(glyph_id.into())) + } + } + + fn is_emoji(&self, font_id: FontId) -> bool { + // todo!(linux): implement this correctly + self.postscript_names_by_font_id + .get(&font_id) + .map_or(false, |postscript_name| { + postscript_name == "AppleColorEmoji" + }) + } + + // todo!(linux) both raster functions have problems because I am not sure this is the correct mapping from cosmic text to gpui system + fn raster_bounds(&mut self, params: &RenderGlyphParams) -> Result> { + let font = &self.fonts[params.font_id.0]; + let font_system = &mut self.font_system; + let image = self + .swash_cache + .get_image( + font_system, + CacheKey::new( + font.id(), + params.glyph_id.0 as u16, + params.font_size.into(), + (0.0, 0.0), + ) + .0, + ) + .clone() + .unwrap(); + Ok(Bounds { + origin: point(image.placement.left.into(), (-image.placement.top).into()), + size: size(image.placement.width.into(), image.placement.height.into()), + }) + } + + fn rasterize_glyph( + &mut self, + params: &RenderGlyphParams, + glyph_bounds: Bounds, + ) -> Result<(Size, Vec)> { + if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 { + Err(anyhow!("glyph bounds are empty")) + } else { + // todo!(linux) handle subpixel variants + let bitmap_size = glyph_bounds.size; + let font = &self.fonts[params.font_id.0]; + let font_system = &mut self.font_system; + let image = self + .swash_cache + .get_image( + font_system, + CacheKey::new( + font.id(), + params.glyph_id.0 as u16, + params.font_size.into(), + (0.0, 0.0), + ) + .0, + ) + .clone() + .unwrap(); + + Ok((bitmap_size, image.data)) + } + } + + // todo!(linux) This is all a quick first pass, maybe we should be using cosmic_text::Buffer + fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout { + let mut attrs_list = AttrsList::new(Attrs::new()); + let mut offs = 0; + for run in font_runs { + // todo!(linux) We need to check we are doing utf properly + let font = &self.fonts[run.font_id.0]; + let font = self.font_system.db().face(font.id()).unwrap(); + attrs_list.add_span( + offs..run.len, + Attrs::new() + .family(Family::Name(&font.families.first().unwrap().0)) + .stretch(font.stretch) + .style(font.style) + .weight(font.weight), + ); + offs += run.len; + } + let mut line = BufferLine::new(text, attrs_list, cosmic_text::Shaping::Advanced); + let layout = line.layout( + &mut self.font_system, + font_size.0, + f32::MAX, // todo!(linux) we don't have a width cause this should technically not be wrapped I believe + cosmic_text::Wrap::None, + ); + let mut runs = Vec::new(); + // todo!(linux) what I think can happen is layout returns possibly multiple lines which means we should be probably working with it higher up in the text rendering + let layout = layout.first().unwrap(); + for glyph in &layout.glyphs { + let font_id = glyph.font_id; + let font_id = FontId( + self.fonts + .iter() + .position(|font| font.id() == font_id) + .unwrap(), + ); + let mut glyphs = SmallVec::new(); + // todo!(linux) this is definitely wrong, each glyph in glyphs from cosmic-text is a cluster with one glyph, ShapedRun takes a run of glyphs with the same font and direction + glyphs.push(ShapedGlyph { + id: GlyphId(glyph.glyph_id as u32), + position: point((glyph.x).into(), glyph.y.into()), + index: glyph.start, + is_emoji: self.is_emoji(font_id), + }); + runs.push(crate::ShapedRun { font_id, glyphs }); + } + LineLayout { + font_size, + width: layout.w.into(), + ascent: layout.max_ascent.into(), + descent: layout.max_descent.into(), + runs, + len: text.len(), + } + } +} + +impl From for Bounds { + fn from(rect: RectF) -> Self { + Bounds { + origin: point(rect.origin_x(), rect.origin_y()), + size: size(rect.width(), rect.height()), + } + } +} + +impl From for Bounds { + fn from(rect: RectI) -> Self { + Bounds { + origin: point(DevicePixels(rect.origin_x()), DevicePixels(rect.origin_y())), + size: size(DevicePixels(rect.width()), DevicePixels(rect.height())), + } + } +} + +impl From for Size { + fn from(value: Vector2I) -> Self { + size(value.x().into(), value.y().into()) + } +} + +impl From for Bounds { + fn from(rect: RectI) -> Self { + Bounds { + origin: point(rect.origin_x(), rect.origin_y()), + size: size(rect.width(), rect.height()), + } + } +} + +impl From> for Vector2I { + fn from(size: Point) -> Self { + Vector2I::new(size.x as i32, size.y as i32) + } +} + +impl From for Size { + fn from(vec: Vector2F) -> Self { + size(vec.x(), vec.y()) + } +} + +impl From for cosmic_text::Weight { + fn from(value: FontWeight) -> Self { + cosmic_text::Weight(value.0 as u16) + } +} + +impl From for cosmic_text::Style { + fn from(style: FontStyle) -> Self { + match style { + FontStyle::Normal => cosmic_text::Style::Normal, + FontStyle::Italic => cosmic_text::Style::Italic, + FontStyle::Oblique => cosmic_text::Style::Oblique, + } + } +} diff --git a/crates/gpui/src/style.rs b/crates/gpui/src/style.rs index c7054b98c5..71dccaf170 100644 --- a/crates/gpui/src/style.rs +++ b/crates/gpui/src/style.rs @@ -208,8 +208,12 @@ impl Default for TextStyle { fn default() -> Self { TextStyle { color: black(), - // Helvetica is a web safe font, so it should be available - font_family: "Helvetica".into(), + // todo!(linux) make this configurable or choose better default + font_family: if cfg!(target_os = "linux") { + "FreeMono".into() + } else { + "Helvetica".into() + }, font_features: FontFeatures::default(), font_size: rems(1.).into(), line_height: phi(), diff --git a/crates/gpui/src/text_system.rs b/crates/gpui/src/text_system.rs index 43d7b2bb1b..7e2a76a9dd 100644 --- a/crates/gpui/src/text_system.rs +++ b/crates/gpui/src/text_system.rs @@ -725,6 +725,7 @@ pub struct FontMetrics { pub(crate) x_height: f32, /// The outer limits of the area that the font covers. + /// Corresponds to the xMin / xMax / yMin / yMax values in the OpenType `head` table pub(crate) bounding_box: Bounds, }