summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--font/src/lib.rs38
-rw-r--r--src/lib.rs1
-rw-r--r--src/renderer/mod.rs83
5 files changed, 81 insertions, 49 deletions
diff --git a/Cargo.lock b/Cargo.lock
index defbfa7e..fb8b75da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index d13ce7fd..ba02b95e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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> {
diff --git a/src/lib.rs b/src/lib.rs
index fe490942..58ebb07b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);
+ }
}
}
}