From ec00fe37fa8a8b6e2db1f780f66918c6e60b5b18 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 2 Jan 2020 15:13:32 -0800 Subject: [PATCH] progress toward better text shaping maybe... --- Cargo.lock | 113 +++++++++++++++++--------------- Cargo.toml | 3 +- src/renderer/caching_shaper.rs | 14 +++- src/renderer/cursor_renderer.rs | 2 +- src/renderer/fonts.rs | 78 +++++++++++++++------- src/renderer/mod.rs | 15 +++-- 6 files changed, 137 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b88070..09b2c09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,25 +332,11 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "core-graphics" version = "0.17.3" @@ -362,24 +348,13 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "core-graphics" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "core-text" -version = "15.0.0" +version = "13.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -453,19 +428,9 @@ dependencies = [ [[package]] name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dirs-sys" -version = "0.3.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -577,14 +542,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "font-kit" -version = "0.5.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-text 15.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-text 13.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.20.7 (registry+https://github.com/rust-lang/crates.io-index)", "float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -593,6 +558,7 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lyon_path 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -816,6 +782,27 @@ dependencies = [ "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "harfbuzz" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "harfbuzz-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "harfbuzz-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-text 13.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.6.3" @@ -1060,11 +1047,12 @@ dependencies = [ "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.20.7 (registry+https://github.com/rust-lang/crates.io-index)", - "font-kit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "msgbox 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "neovim-lib 0.6.0 (git+https://github.com/daa84/neovim-lib)", "rmpv 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "skribo 0.0.1 (git+https://github.com/linebender/skribo)", "skulpin 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1569,6 +1557,19 @@ dependencies = [ "skia-bindings 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "skribo" +version = "0.0.1" +source = "git+https://github.com/linebender/skribo#03c63ac17bb93e29f82e959dac94027935a21159" +dependencies = [ + "euclid 0.20.7 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "harfbuzz-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "skulpin" version = "0.4.0" @@ -1698,6 +1699,14 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-normalization" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-segmentation" version = "1.6.0" @@ -1976,20 +1985,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" "checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" -"checksum core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59e78b2e0aaf43f08e7ae0d6bc96895ef72ff0921c7d4ff4762201b2dba376dd" -"checksum core-text 15.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "131b3fd1f8bd5db9f2b398fa4fdb6008c64afc04d447c306ac2c7e98fba2a61d" +"checksum core-text 13.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db84654ad95211c082cf9795f6f83dc17d0ae6c985ac1b906369dc7384ed346d" "checksum core-video-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc065219542086f72d1e9f7aadbbab0989e980263695d129d502082d063a9d0" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum curl 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06aa71e9208a54def20792d877bc663d6aae0732b9852e612c4a933177c31283" "checksum curl-sys 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f659f3ffac9582d6177bb86d1d2aa649f4eb9d0d4de9d03ccc08b402832ea340" "checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" -"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e93ca78226c51902d7aa8c12c988338aadd9e85ed9c6be8aaac39192ff3605" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" @@ -2002,7 +2007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" "checksum float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" -"checksum font-kit 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09b6e2b877097ffd0abac6597fea26fccb5ed7eb9da0a4094f11ccc8aba64efb" +"checksum font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b7ff8d2a0a660875d01689807925a45c5843bf90a1ef97ec52ef86ab0cafba" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "11926b2b410b469d0e9399eca4cbbe237a9ef02176c485803b29216307e8e028" @@ -2022,6 +2027,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70409d6405db8b1591602fcd0cbe8af52cd9976dd39194442b4c149ba343f86d" "checksum gtk 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d695d6be4110618a97c19cd068e8a00e53e33b87e3c65cdc5397667498b1bc24" "checksum gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d9554cf5b3a85a13fb39258c65b04b262989c1d7a758f8f555b77a478621a91" +"checksum harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46f7426266a5ece3e49eae6f48e602c0f8c39917354a847eac9c06437dcde8da" +"checksum harfbuzz-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cf14b85a0c906ef4ef3ff87d0fba25ee45b724404a1a3100dc25eeb4f37ff43b" "checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" @@ -2109,6 +2116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum skia-bindings 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2eee489fbdc6fe3004f95e4457d7f3bd184b7902982cca0a2d8d01b7438328b" "checksum skia-safe 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e86d7ad9a51df1fcc8a4942907c65c81573bcfe6bcaea8baedcb008167dc6650" +"checksum skribo 0.0.1 (git+https://github.com/linebender/skribo)" = "" "checksum skulpin 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76dcf1de07238986bbd32692b98fbb859bdc42b1840ffcd49570c57335c201c5" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" @@ -2123,6 +2131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Cargo.toml b/Cargo.toml index e9a63b3..690ac6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2018" [dependencies] euclid = "0.20.7" -font-kit = "0.5.0" +font-kit = "0.4.0" +skribo = { git = "https://github.com/linebender/skribo" } lru = "0.4.3" skulpin = "0.4" derive-new = "0.5" diff --git a/src/renderer/caching_shaper.rs b/src/renderer/caching_shaper.rs index 490f376..2fa952b 100644 --- a/src/renderer/caching_shaper.rs +++ b/src/renderer/caching_shaper.rs @@ -1,9 +1,17 @@ use lru::LruCache; use skulpin::skia_safe::{Shaper, TextBlob, Font, Point}; +#[derive(new, Clone, Hash, PartialEq, Eq)] +struct ShapeKey { + pub text: String, + pub scale: u16, + pub bold: bool, + pub italic: bool +} + pub struct CachingShaper { shaper: Shaper, - cache: LruCache<(String, u16), TextBlob> + cache: LruCache } impl CachingShaper { @@ -19,8 +27,8 @@ impl CachingShaper { blob } - pub fn shape_cached(&mut self, text: String, scale: u16, font: &Font) -> &TextBlob { - let key = (text.clone(), scale); + pub fn shape_cached(&mut self, text: String, scale: u16, bold: bool, italic: bool, font: &Font) -> &TextBlob { + let key = ShapeKey::new(text.clone(), scale, bold, italic); if !self.cache.contains(&key) { self.cache.put(key.clone(), self.shape(&text, &font)); } diff --git a/src/renderer/cursor_renderer.rs b/src/renderer/cursor_renderer.rs index e3af384..6a9b14b 100644 --- a/src/renderer/cursor_renderer.rs +++ b/src/renderer/cursor_renderer.rs @@ -140,7 +140,7 @@ impl CursorRenderer { canvas.save(); canvas.clip_path(&path, None, Some(false)); canvas.draw_text_blob( - shaper.shape_cached(character.to_string(), 1, &fonts_lookup.size(1).normal), + shaper.shape_cached(character.to_string(), 1, false, false, &fonts_lookup.size(1).normal), destination, &paint); canvas.restore(); } diff --git a/src/renderer/fonts.rs b/src/renderer/fonts.rs index b5b06e0..1d71cbe 100644 --- a/src/renderer/fonts.rs +++ b/src/renderer/fonts.rs @@ -1,7 +1,14 @@ use std::collections::HashMap; -use skulpin::skia_safe::{Typeface, Font, FontStyle, Paint}; +use skulpin::skia_safe::{GlyphId, Typeface, Font, FontStyle, Paint, Point}; +use font_kit::source::SystemSource; +use skribo::{ + layout, layout_run, make_layout, FontCollection, FontFamily, FontRef, Layout, LayoutSession, + TextStyle, +}; use crate::editor::Style; +const standard_character_string: &'static str = "XXXX"; + pub struct Fonts { pub name: String, pub size: f32, @@ -13,21 +20,32 @@ pub struct Fonts { impl Fonts { fn new(name: &str, size: f32) -> Fonts { + let normal = Font::from_typeface( + Typeface::new(name, FontStyle::normal()).expect("Could not load normal font file"), + size); + let mut bold = Font::from_typeface( + Typeface::new(name, FontStyle::bold()).expect("Could not load bold font file"), + size); + if bold.is_embolden() { + dbg!("Disabled embolden for normal bold"); + bold.set_embolden(false); + } + + let italic = Font::from_typeface( + Typeface::new(name, FontStyle::italic()).expect("Could not load italic font file"), + size); + let mut bold_italic = Font::from_typeface( + Typeface::new(name, FontStyle::bold_italic()).expect("Could not load bold italic font file"), + size); + + if bold_italic.is_embolden() { + dbg!("Disabled embolden for italic bold"); + bold_italic.set_embolden(false); + } + Fonts { - name: name.to_string(), - size, - normal: Font::from_typeface( - Typeface::new(name, FontStyle::normal()).expect("Could not load normal font file"), - size), - bold: Font::from_typeface( - Typeface::new(name, FontStyle::bold()).expect("Could not load bold font file"), - size), - italic: Font::from_typeface( - Typeface::new(name, FontStyle::italic()).expect("Could not load italic font file"), - size), - bold_italic: Font::from_typeface( - Typeface::new(name, FontStyle::bold_italic()).expect("Could not load bold italic font file"), - size) + name: name.to_string(), size, + normal, bold, italic, bold_italic } } @@ -70,18 +88,30 @@ impl FontLookup { }) } - pub fn font_base_dimensions(&mut self, paint: &Paint) -> (f32, f32) { + pub fn font_base_dimensions(&mut self) -> (f32, f32) { let base_fonts = self.size(1); - - let (_, metrics) = base_fonts.normal.metrics(); - let font_width = if metrics.avg_char_width > 0.0 { - metrics.avg_char_width - } else { - let (_, bounds) = base_fonts.normal.measure_str("x", Some(&paint)); - bounds.width() - }; + let normal_font = &base_fonts.normal; + let (_, metrics) = normal_font.metrics(); let font_height = metrics.descent - metrics.ascent; + let source = SystemSource::new(); + let font_name = self.name.clone(); + let font_size = self.base_size; + let font = source + .select_family_by_name(&font_name) + .expect("Failed to load by postscript name") + .fonts()[0] + .load() + .unwrap(); + let font_ref = FontRef::new(font); + let style = TextStyle { size: font_size }; + let layout = layout_run(&style, &font_ref, standard_character_string); + let font_width = layout.advance.x / standard_character_string.len() as f32; + // let glyph_offsets: Vec = layout.glyphs.iter().map(|glyph| glyph.offset.x).collect(); + // let glyph_advances: Vec = glyph_offsets.windows(2).map(|pair| pair[1] - pair[0]).collect(); + // dbg!(&glyph_advances); + // let font_width = glyph_advances.iter().cloned().fold(0.0, f32::max); + (font_width, font_height) } } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 3f3c1b3..a1de97f 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -13,8 +13,8 @@ use cursor_renderer::CursorRenderer; use fonts::FontLookup; use crate::editor::{Editor, Style, Colors}; -const FONT_NAME: &str = "Delugia Nerd Font"; -const FONT_SIZE: f32 = 14.0; +const DEFAULT_FONT_NAME: &str = "Delugia Nerd Font"; +const DEFAULT_FONT_SIZE: f32 = 14.0; #[derive(new)] pub struct DrawResult { @@ -43,8 +43,8 @@ impl Renderer { let shaper = CachingShaper::new(); - let mut fonts_lookup = FontLookup::new(FONT_NAME, FONT_SIZE); - let (font_width, font_height) = fonts_lookup.font_base_dimensions(&paint); + let mut fonts_lookup = FontLookup::new(DEFAULT_FONT_NAME, DEFAULT_FONT_SIZE); + let (font_width, font_height) = fonts_lookup.font_base_dimensions(); let cursor_renderer = CursorRenderer::new(); Renderer { editor, surface, paint, fonts_lookup, shaper, font_width, font_height, cursor_renderer } @@ -52,7 +52,7 @@ impl Renderer { fn set_font(&mut self, name: &str, size: f32) { self.fonts_lookup = FontLookup::new(name, size); - let (font_width, font_height) = self.fonts_lookup.font_base_dimensions(&self.paint); + let (font_width, font_height) = self.fonts_lookup.font_base_dimensions(); self.font_width = font_width; self.font_height = font_height; self.shaper.clear(); @@ -100,7 +100,8 @@ impl Renderer { self.paint.set_color(style.foreground(&default_colors).to_color()); let text = text.trim_end(); if text.len() > 0 { - let blob = self.shaper.shape_cached(text.to_string(), size, self.fonts_lookup.size(size).get(&style)); + let font = self.fonts_lookup.size(size).get(&style); + let blob = self.shaper.shape_cached(text.to_string(), size, style.bold, style.italic, font); canvas.draw_text_blob(blob, (x, y), &self.paint); } @@ -123,7 +124,7 @@ impl Renderer { font_name.clone().map(|new_name| new_name != self.fonts_lookup.name).unwrap_or(false) || font_size.map(|new_size| new_size != self.fonts_lookup.base_size).unwrap_or(false); if font_changed { - self.set_font(&font_name.unwrap(), font_size.unwrap()); + self.set_font(&font_name.unwrap_or(DEFAULT_FONT_NAME.to_string()), font_size.unwrap_or(DEFAULT_FONT_SIZE)); } if should_clear {