From 5040c44f670ab1ce51faf3ae588002f7b4c0ffca Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Sun, 21 Feb 2016 19:44:54 -0800 Subject: [PATCH] Implement very basic glyph rasterization There are several assumptions made at this point and very little (no) error handling done. --- Cargo.lock | 58 +++++++++++++++++++++++---------- Cargo.toml | 4 +-- src/list_fonts.rs | 19 +++++++++++ src/main.rs | 1 + src/text.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 src/text.rs diff --git a/Cargo.lock b/Cargo.lock index 5afbf7ed..6cb37f09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,11 +2,16 @@ name = "alacritty" version = "0.1.0" dependencies = [ - "freetype 0.1.0 (git+https://github.com/servo/rust-freetype.git)", + "freetype-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-fontconfig 0.2.0 (git+https://github.com/jwilm/rust-fontconfig)", ] +[[package]] +name = "bitflags" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "expat-sys" version = "2.1.2" @@ -17,18 +22,45 @@ dependencies = [ ] [[package]] -name = "freetype" -version = "0.1.0" -source = "git+https://github.com/servo/rust-freetype.git#d564ff90a3c69d987f5c015d7ec034cfaee21aff" +name = "freetype-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "freetype-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "freetype-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libz-sys" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "make-cmd" version = "0.1.0" @@ -42,27 +74,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "servo-fontconfig" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/jwilm/rust-fontconfig#419135e5e1106ec0973dd4923bd9c70d8e438cc8" dependencies = [ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-fontconfig-sys 2.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-fontconfig-sys 2.11.3 (git+https://github.com/jwilm/libfontconfig)", ] [[package]] name = "servo-fontconfig-sys" version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/jwilm/libfontconfig#1d7544dc1ff6a7d0f3a9e6a27b5373a89afa8c38" dependencies = [ "expat-sys 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-freetype-sys" -version = "2.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ + "freetype-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index d2aa21e5..ff4a0a7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["Joe Wilm "] [dependencies] -servo-fontconfig = "0.2" -freetype = { git = "https://github.com/servo/rust-freetype.git" } +servo-fontconfig = { git = "https://github.com/jwilm/rust-fontconfig" } +freetype-rs = "0.5.0" libc = "*" diff --git a/src/list_fonts.rs b/src/list_fonts.rs index c418bc02..c7cd60ca 100644 --- a/src/list_fonts.rs +++ b/src/list_fonts.rs @@ -69,12 +69,31 @@ pub struct Variant { index: usize, } +impl Variant { + #[inline] + pub fn filepath(&self) -> &::std::path::Path { + self.file.as_path() + } +} + #[derive(Debug)] pub struct Family { name: String, variants: Vec, } +impl Family { + #[inline] + pub fn name(&self) -> &str { + &self.name[..] + } + + #[inline] + pub fn variants(&self) -> &[Variant] { + &self.variants[..] + } +} + static FILE: &'static [u8] = b"file\0"; static FAMILY: &'static [u8] = b"family\0"; static INDEX: &'static [u8] = b"index\0"; diff --git a/src/main.rs b/src/main.rs index 66be9b34..7356bd36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate freetype; extern crate libc; mod list_fonts; +mod text; fn main() { println!("Hello, world!"); diff --git a/src/text.rs b/src/text.rs new file mode 100644 index 00000000..5694e2ce --- /dev/null +++ b/src/text.rs @@ -0,0 +1,81 @@ +use list_fonts::get_font_families; + +use freetype::Library; +use freetype::Face; +use freetype; + +/// Rasterizes glyphs for a single font face. +pub struct Rasterizer { + face: Face<'static>, + library: Library, +} + +#[inline] +fn to_freetype_26_6(f: f32) -> isize { + ((1i32 << 6) as f32 * f) as isize +} + +impl Rasterizer { + pub fn new() -> Rasterizer { + let library = Library::init().unwrap(); + + let family = get_font_families().into_iter() + .filter(|f| f.name() == "Inconsolata-dz") + .nth(0).unwrap(); // TODO + + let variant = family.variants().first().unwrap(); + let path = variant.filepath(); + + Rasterizer { + face: library.new_face(path, 0).expect("Create font face"), + library: library, + } + } + + pub fn get_glyph(&self, size: f32, c: char) -> RasterizedGlyph { + // TODO DPI + self.face.set_char_size(to_freetype_26_6(size), 0, 96, 0).unwrap(); + self.face.load_char(c as usize, freetype::face::RENDER).unwrap(); + let glyph = self.face.glyph(); + + RasterizedGlyph { + top: glyph.bitmap_top() as usize, + left: glyph.bitmap_left() as usize, + width: glyph.bitmap().width() as usize, + height: glyph.bitmap().rows() as usize, + buf: glyph.bitmap().buffer().to_vec(), + } + } +} + +#[derive(Debug)] +struct RasterizedGlyph { + width: usize, + height: usize, + top: usize, + left: usize, + buf: Vec, +} + + +#[cfg(test)] +mod tests { + use super::Rasterizer; + + #[test] + fn create_rasterizer_and_render_glyph() { + let rasterizer = Rasterizer::new(); + let glyph = rasterizer.get_glyph(24., 'U'); + + println!("glyph: {:?}", glyph); + + for j in 0..glyph.height { + for i in 0..glyph.width { + let val = glyph.buf[j * glyph.width + i]; + print!("{}", if val < 122 { " " } else { "%"}); + } + + print!("\n"); + } + } +}