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:
parent
e3b3fa58fc
commit
9de24a75ed
114
src/font/fontloader_and_rusttype.rs
Normal file
114
src/font/fontloader_and_rusttype.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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 _,
|
||||
)
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user