diff options
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | font/src/lib.rs | 38 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/renderer/mod.rs | 83 |
5 files changed, 81 insertions, 49 deletions
@@ -8,6 +8,7 @@ dependencies = [ "clippy 0.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "copypasta 0.0.1", "errno 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "font 0.1.0", "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=af7fe340bd4a2af53ea521defcb4f377cdc588cf)", @@ -273,6 +274,11 @@ dependencies = [ ] [[package]] +name = "fnv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "font" version = "0.1.0" dependencies = [ @@ -1240,6 +1246,7 @@ dependencies = [ "checksum euclid 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7b555729225fcc2aabc1ac951f9346967b35c901f4f03a480c31b6a45824109" "checksum expat-sys 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cef36cd1a8a02d28b91d97347c63247b9e4cb8a8e36df36f8201dc87a1c0859c" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" +"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum freetype-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8c93a141b156862ab58d0206fa44a9b20d899c86c3e6260017ab748029aa42" "checksum freetype-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccfb6d96cac99921f0c2142a91765f6c219868a2c45bdfe7d65a08775f18127" "checksum fs2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bcd414e5a1a979b931bb92f41b7a54106d3f6d2e6c253e9ce943b7cd468251ef" @@ -34,6 +34,7 @@ copypasta = { path = "./copypasta" } xdg = "2.0.0" log = "0.3" clap = "2.20" +fnv = "1.0.5" clippy = { version = "0.0.104", optional = true } diff --git a/font/src/lib.rs b/font/src/lib.rs index bb9b9f3c..c5c0a2c7 100644 --- a/font/src/lib.rs +++ b/font/src/lib.rs @@ -42,8 +42,9 @@ extern crate ffi_util; #[macro_use] extern crate log; +use std::hash::{Hash, Hasher}; use std::fmt; -use std::sync::atomic::{AtomicU32, ATOMIC_U32_INIT, Ordering}; +use std::sync::atomic::{AtomicU16, ATOMIC_U16_INIT, Ordering}; // If target isn't macos, reexport everything from ft #[cfg(not(target_os = "macos"))] @@ -114,7 +115,7 @@ impl fmt::Display for FontDesc { /// Identifier for a Font for use in maps/etc #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub struct FontKey { - token: u32, + token: u16, } impl FontKey { @@ -122,7 +123,7 @@ impl FontKey { /// /// The generated key will be globally unique pub fn next() -> FontKey { - static TOKEN: AtomicU32 = ATOMIC_U32_INIT; + static TOKEN: AtomicU16 = ATOMIC_U16_INIT; FontKey { token: TOKEN.fetch_add(1, Ordering::SeqCst), @@ -130,16 +131,28 @@ impl FontKey { } } -#[derive(Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct GlyphKey { pub c: char, pub font_key: FontKey, pub size: Size, } +impl Hash for GlyphKey { + fn hash<H: Hasher>(&self, state: &mut H) { + unsafe { + // This transmute is fine: + // + // - If GlyphKey ever becomes a different size, this will fail to compile + // - Result is being used for hashing and has no fields (it's a u64) + ::std::mem::transmute::<GlyphKey, u64>(*self) + }.hash(state); + } +} + /// Font size stored as integer #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Size(i32); +pub struct Size(i16); impl Size { /// Scale factor between font "Size" type and point size @@ -150,7 +163,7 @@ impl Size { /// Create a new `Size` from a f32 size in points pub fn new(size: f32) -> Size { - Size((size * Size::factor()) as i32) + Size((size * Size::factor()) as i16) } /// Get the f32 size in points @@ -168,6 +181,19 @@ pub struct RasterizedGlyph { pub buf: Vec<u8>, } +impl Default for RasterizedGlyph { + fn default() -> RasterizedGlyph { + RasterizedGlyph { + c: ' ', + width: 0, + height: 0, + top: 0, + left: 0, + buf: Vec::new(), + } + } +} + struct BufDebugger<'a>(&'a [u8]); impl<'a> fmt::Debug for BufDebugger<'a> { @@ -30,6 +30,7 @@ extern crate clap; extern crate copypasta; extern crate errno; extern crate font; +extern crate fnv; extern crate glutin; #[macro_use] extern crate lazy_static; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index a9833822..fe4ff29f 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::collections::HashMap; +use std::hash::BuildHasherDefault; use std::fs::File; use std::io::{self, Read}; use std::mem::size_of; @@ -20,20 +21,19 @@ use std::ptr; use std::sync::mpsc; use cgmath; +use fnv::FnvHasher; use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey}; use gl::types::*; use gl; -use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op}; use index::{Line, Column, RangeInclusive}; - -use window::{Size, Pixels}; +use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op}; use ansi::{Color, NamedColor}; - use config::{Config, ColorList}; use term::{self, cell, IndexedCell, Cell}; +use window::{Size, Pixels}; -use super::Rgb; +use Rgb; // Shader paths for live reload static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl"); @@ -136,7 +136,7 @@ pub struct Glyph { /// representations of the same code point. pub struct GlyphCache { /// Cache of buffered glyphs - cache: HashMap<GlyphKey, Glyph>, + cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>, /// Rasterizer for loading new glyphs rasterizer: Rasterizer, @@ -215,7 +215,7 @@ impl GlyphCache { }; let mut cache = GlyphCache { - cache: HashMap::new(), + cache: HashMap::default(), rasterizer: rasterizer, font_size: font.size(), font_key: regular, @@ -251,26 +251,24 @@ impl GlyphCache { fn load_and_cache_glyph<L>(&mut self, glyph_key: GlyphKey, loader: &mut L) where L: LoadGlyph { - if let Ok(rasterized) = self.rasterizer.get_glyph(&glyph_key) { - let glyph = loader.load_glyph(&rasterized); - self.cache.insert(glyph_key, glyph); - } + let rasterized = self.rasterizer.get_glyph(&glyph_key) + .unwrap_or_else(|_| Default::default()); + + let glyph = loader.load_glyph(&rasterized); + self.cache.insert(glyph_key, glyph); } - pub fn get<L>(&mut self, glyph_key: &GlyphKey, loader: &mut L) -> Option<&Glyph> + pub fn get<'a, L>(&'a mut self, glyph_key: &GlyphKey, loader: &mut L) -> &'a Glyph where L: LoadGlyph { - // Return glyph if it's already loaded - // hi borrowck - { - if self.cache.contains_key(glyph_key) { - return self.cache.get(glyph_key); - } - } - - // Rasterize and load the glyph - self.load_and_cache_glyph(glyph_key.to_owned(), loader); - self.cache.get(glyph_key) + let rasterizer = &mut self.rasterizer; + self.cache + .entry(*glyph_key) + .or_insert_with(|| { + let rasterized = rasterizer.get_glyph(&glyph_key) + .unwrap_or_else(|_| Default::default()); + loader.load_glyph(&rasterized) + }) } } @@ -817,26 +815,25 @@ impl<'a> RenderApi<'a> { c: cell.c }; - // Add cell to batch if glyph available - glyph_cache.get(&glyph_key, self) - .map(|glyph| self.add_render_item(&cell, glyph)) - .and_then(|_| { - // FIXME This is a super hacky way to do underlined text. During - // a time crunch to release 0.1, this seemed like a really - // easy, clean hack. - if cell.flags.contains(cell::UNDERLINE) { - let glyph_key = GlyphKey { - font_key: font_key, - size: glyph_cache.font_size, - c: '_' - }; - - glyph_cache.get(&glyph_key, self) - } else { - None - } - }) - .map(|underscore| self.add_render_item(&cell, underscore)); + // Add cell to batch + { + let glyph = glyph_cache.get(&glyph_key, self); + self.add_render_item(&cell, glyph); + } + + // FIXME This is a super hacky way to do underlined text. During + // a time crunch to release 0.1, this seemed like a really + // easy, clean hack. + if cell.flags.contains(cell::UNDERLINE) { + let glyph_key = GlyphKey { + font_key: font_key, + size: glyph_cache.font_size, + c: '_' + }; + + let underscore = glyph_cache.get(&glyph_key, self); + self.add_render_item(&cell, underscore); + } } } } |