1
1
mirror of https://github.com/wez/wezterm.git synced 2025-01-04 19:54:56 +03:00

split rusttype font from fontloader

This commit is contained in:
Wez Furlong 2019-02-18 13:13:36 -08:00
parent e3b3fa58fc
commit 9de24a75ed
5 changed files with 146 additions and 126 deletions

View File

@ -0,0 +1,114 @@
//! Systems using rust native loader and rasterizer
#[cfg(unix)]
use super::hbwrap as harfbuzz;
use config::{Config, TextStyle};
use failure::Error;
use font::rtype::RustTypeFontImpl;
use font::{FallbackIdx, Font, FontMetrics, FontSystem, GlyphInfo, NamedFont, RasterizedGlyph};
use font_loader::system_fonts;
use rusttype::{
point, Codepoint, Font as RTFont, FontCollection, PositionedGlyph, Rect, Scale, ScaledGlyph,
VMetrics,
};
use unicode_normalization::UnicodeNormalization;
struct NamedFontImpl<'a> {
fonts: Vec<RustTypeFontImpl<'a>>,
}
pub type FontSystemImpl = RustTypeFonts;
pub struct RustTypeFonts {}
impl RustTypeFonts {
pub fn new() -> Self {
Self {}
}
}
impl FontSystem for RustTypeFonts {
fn load_font(&self, config: &Config, style: &TextStyle) -> Result<Box<NamedFont>, Error> {
let mut fonts = Vec::new();
for font_attr in &style.font {
let mut font_props = system_fonts::FontPropertyBuilder::new()
.family(&font_attr.family)
.monospace();
font_props = if *font_attr.bold.as_ref().unwrap_or(&false) {
font_props.bold()
} else {
font_props
};
font_props = if *font_attr.italic.as_ref().unwrap_or(&false) {
font_props.italic()
} else {
font_props
};
let font_props = font_props.build();
let (data, idx) = system_fonts::get(&font_props)
.ok_or_else(|| format_err!("no font matching {:?}", font_attr))?;
eprintln!("want idx {} in bytes of len {}", idx, data.len());
fonts.push(RustTypeFontImpl::from_bytes(
data,
idx,
config.font_size as f32 * config.dpi as f32 / 72.0,
)?);
}
Ok(Box::new(NamedFontImpl { fonts }))
}
}
impl<'a> NamedFontImpl<'a> {
pub fn glyph(&mut self, c: char) -> Result<(ScaledGlyph, usize), Error> {
let codepoint = Codepoint(c as u32);
for (idx, font) in self.fonts.iter().enumerate() {
let g = font.font.glyph(codepoint);
if g.id().0 == 0 {
// notdef; continue looking in the fallbacks
continue;
}
return Ok((g.scaled(font.scale), idx));
}
if c != '?' {
return match self.glyph('?') {
Ok((g, idx)) => Ok((g, idx)),
Err(_) => bail!("unable to resolve glyph for char={} or the fallback ?", c),
};
}
bail!("unable to resolve glyph for ?");
}
}
impl<'a> NamedFont for NamedFontImpl<'a> {
fn get_fallback(&mut self, idx: FallbackIdx) -> Result<&Font, Error> {
self.fonts
.get(idx)
.map(|f| {
let f: &Font = f;
f
})
.ok_or_else(|| format_err!("no fallback fonts available (idx={})", idx))
}
fn shape(&mut self, s: &str) -> Result<Vec<GlyphInfo>, Error> {
let mut shaped = Vec::new();
for (cluster, c) in s.nfc().enumerate() {
let (glyph, font_idx) = self.glyph(c)?;
let hmetrics = glyph.h_metrics();
let glyph = glyph.positioned(point(0.0, 0.0));
shaped.push(GlyphInfo {
#[cfg(debug_assertions)]
text: c.to_string(),
cluster: cluster as u32,
num_cells: 1,
font_idx,
glyph_pos: glyph.id().0,
x_advance: hmetrics.advance_width.into(),
x_offset: (-hmetrics.left_side_bearing).into(),
y_advance: 0.0,
y_offset: 0.0, //(-bounds.max.y).into(),
// vmetrics.descent.into(),
})
}
Ok(shaped)
}
}

View File

@ -141,7 +141,7 @@ impl Library {
FT_New_Memory_Face(
self.lib,
data.as_ptr(),
data.len() as i32,
data.len() as _,
face_index,
&mut face as *mut _,
)

View File

@ -27,9 +27,11 @@ pub mod coretext;
use self::coretext::FontSystemImpl;
#[cfg(any(windows, feature = "force-rusttype"))]
pub mod fontloader_and_rusttype;
pub mod rtype;
#[cfg(any(windows, feature = "force-rusttype"))]
use self::rtype::FontSystemImpl;
use self::fontloader_and_rusttype::FontSystemImpl;
use super::config::{Config, TextStyle};
use term::CellAttributes;

View File

@ -12,72 +12,36 @@ use rusttype::{
};
use unicode_normalization::UnicodeNormalization;
struct NamedFontImpl<'a> {
fonts: Vec<FontImpl<'a>>,
}
struct FontImpl<'a> {
pub struct RustTypeFontImpl<'a> {
_collection: FontCollection<'a>,
font: RTFont<'a>,
scale: Scale,
pub(crate) font: RTFont<'a>,
pub(crate) scale: Scale,
vmetrics: VMetrics,
cell_height: f64,
}
pub type FontSystemImpl = RustTypeFonts;
pub struct RustTypeFonts {}
impl RustTypeFonts {
pub fn new() -> Self {
Self {}
}
}
impl FontSystem for RustTypeFonts {
fn load_font(&self, config: &Config, style: &TextStyle) -> Result<Box<NamedFont>, Error> {
let mut fonts = Vec::new();
for font_attr in &style.font {
let mut font_props = system_fonts::FontPropertyBuilder::new()
.family(&font_attr.family)
.monospace();
font_props = if *font_attr.bold.as_ref().unwrap_or(&false) {
font_props.bold()
} else {
font_props
};
font_props = if *font_attr.italic.as_ref().unwrap_or(&false) {
font_props.italic()
} else {
font_props
};
let font_props = font_props.build();
let (data, idx) = system_fonts::get(&font_props)
.ok_or_else(|| format_err!("no font matching {:?}", font_attr))?;
eprintln!("want idx {} in bytes of len {}", idx, data.len());
let collection = FontCollection::from_bytes(data)?;
// Most likely problem is that we matched an OpenType font and rusttype can't
// load it today.
let font = collection.font_at(idx as usize).map_err(|e| {
format_err!(
"{:?}: {} (Note that rusttype only supports TrueType font files!)",
font_attr,
e
)
})?;
eprintln!("made a font for {:?}", font_attr);
let scale = Scale::uniform(config.font_size as f32 * config.dpi as f32 / 72.0);
let vmetrics = font.v_metrics(scale);
eprintln!("vmetrics {:?}", vmetrics);
let cell_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
fonts.push(FontImpl {
_collection: collection,
cell_height,
font,
scale,
vmetrics,
});
}
Ok(Box::new(NamedFontImpl { fonts }))
impl<'a> RustTypeFontImpl<'a> {
pub fn from_bytes(data: Vec<u8>, idx: i32, size: f32) -> Result<Self, Error> {
let collection = FontCollection::from_bytes(data)?;
// Most likely problem is that we matched an OpenType font and rusttype can't
// load it today.
let font = collection.font_at(idx as usize).map_err(|e| {
format_err!(
"{} (Note that rusttype only supports TrueType font files!)",
e
)
})?;
let scale = Scale::uniform(size);
let vmetrics = font.v_metrics(scale);
eprintln!("vmetrics {:?}", vmetrics);
let cell_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
Ok(RustTypeFontImpl {
_collection: collection,
cell_height,
font,
scale,
vmetrics,
})
}
}
@ -91,64 +55,7 @@ fn bounds(g: &PositionedGlyph) -> Rect<i32> {
}
}
impl<'a> NamedFontImpl<'a> {
fn glyph(&mut self, c: char) -> Result<(ScaledGlyph, usize), Error> {
let codepoint = Codepoint(c as u32);
for (idx, font) in self.fonts.iter().enumerate() {
let g = font.font.glyph(codepoint);
if g.id().0 == 0 {
// notdef; continue looking in the fallbacks
continue;
}
return Ok((g.scaled(font.scale), idx));
}
if c != '?' {
return match self.glyph('?') {
Ok((g, idx)) => Ok((g, idx)),
Err(_) => bail!("unable to resolve glyph for char={} or the fallback ?", c),
};
}
bail!("unable to resolve glyph for ?");
}
}
impl<'a> NamedFont for NamedFontImpl<'a> {
fn get_fallback(&mut self, idx: FallbackIdx) -> Result<&Font, Error> {
self.fonts
.get(idx)
.map(|f| {
let f: &Font = f;
f
})
.ok_or_else(|| format_err!("no fallback fonts available (idx={})", idx))
}
fn shape(&mut self, s: &str) -> Result<Vec<GlyphInfo>, Error> {
let mut shaped = Vec::new();
for (cluster, c) in s.nfc().enumerate() {
let (glyph, font_idx) = self.glyph(c)?;
let hmetrics = glyph.h_metrics();
let glyph = glyph.positioned(point(0.0, 0.0));
shaped.push(GlyphInfo {
#[cfg(debug_assertions)]
text: c.to_string(),
cluster: cluster as u32,
num_cells: 1,
font_idx,
glyph_pos: glyph.id().0,
x_advance: hmetrics.advance_width.into(),
x_offset: (-hmetrics.left_side_bearing).into(),
y_advance: 0.0,
y_offset: 0.0, //(-bounds.max.y).into(),
// vmetrics.descent.into(),
})
}
Ok(shaped)
}
}
impl<'a> Font for FontImpl<'a> {
impl<'a> Font for RustTypeFontImpl<'a> {
#[cfg(unix)]
fn harfbuzz_shape(
&self,

View File

@ -26,17 +26,14 @@ extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate clipboard;
extern crate font_loader;
extern crate rusttype;
extern crate term;
extern crate termwiz;
extern crate toml;
extern crate unicode_normalization;
extern crate unicode_width;
#[cfg(any(windows, feature = "force-rusttype"))]
extern crate font_loader;
#[cfg(any(windows, feature = "force-rusttype"))]
extern crate rusttype;
#[macro_use]
pub mod log;