1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-24 07:46:59 +03:00

fonts: FontConfiguration::resolve_font

Can now create a LoadedFont that ties together the new abstractions.
It's not yet sufficient to use in wezterm though.
This commit is contained in:
Wez Furlong 2019-12-09 12:46:58 -08:00
parent cd07a31d84
commit c91345cbd6
4 changed files with 150 additions and 7 deletions

View File

@ -1,4 +1,4 @@
use failure::{bail, format_err, Error};
use failure::{bail, format_err, Error, Fallible};
use log::{debug, error};
use serde_derive::*;
mod ftfont;
@ -35,13 +35,15 @@ pub mod fontloader_and_freetype;
pub mod fontkit;
use crate::font::loader::{FontLocator, FontLocatorSelection};
use crate::font::rasterizer::{FontRasterizer, FontRasterizerSelection};
use crate::font::shaper::{FontShaper, FontShaperSelection};
use super::config::{configuration, ConfigHandle, TextStyle};
use term::CellAttributes;
pub struct LoadedFont {
rasterizer: Box<dyn rasterizer::FontRasterizer>,
shaper: Box<dyn shaper::FontShaper>,
rasterizers: Vec<Box<dyn FontRasterizer>>,
shaper: Box<dyn FontShaper>,
}
type FontPtr = Rc<RefCell<Box<dyn NamedFont>>>;
@ -176,6 +178,30 @@ impl FontConfiguration {
}
}
pub fn resolve_font(&self, style: &TextStyle) -> Fallible<Rc<LoadedFont>> {
let mut fonts = self.new_fonts.borrow_mut();
if let Some(entry) = fonts.get(style) {
return Ok(Rc::clone(entry));
}
let attributes = style.font_with_fallback();
let handles = self.loader.load_fonts(&attributes)?;
let mut rasterizers = vec![];
for handle in &handles {
rasterizers.push(FontRasterizerSelection::get_default().new_rasterizer(&handle)?);
}
let shaper = FontShaperSelection::get_default().new_shaper(&handles)?;
let loaded = Rc::new(LoadedFont {
rasterizers,
shaper,
});
fonts.insert(style.clone(), Rc::clone(&loaded));
Ok(loaded)
}
/// Given a text style, load (with caching) the font that best
/// matches according to the fontconfig pattern.
pub fn cached_font(&self, style: &TextStyle) -> Result<Rc<RefCell<Box<dyn NamedFont>>>, Error> {

View File

@ -1,3 +1,4 @@
use crate::font::loader::FontDataHandle;
use crate::font::rasterizer::FontRasterizer;
use crate::font::{ftwrap, RasterizedGlyph};
use ::freetype::FT_GlyphSlotRec_;
@ -8,6 +9,7 @@ use std::slice;
pub struct FreeTypeRasterizer {
face: RefCell<ftwrap::Face>,
lib: ftwrap::Library,
has_color: bool,
}
@ -263,12 +265,14 @@ impl FreeTypeRasterizer {
}
}
pub fn with_face(face: ftwrap::Face) -> Fallible<Self> {
pub fn from_locator(handle: &FontDataHandle) -> Fallible<Self> {
let lib = ftwrap::Library::new()?;
let face = lib.face_from_locator(handle)?;
let has_color = unsafe {
(((*face.face).face_flags as u32) & (ftwrap::FT_FACE_FLAG_COLOR as u32)) != 0
};
Ok(Self {
lib,
face: RefCell::new(face),
has_color,
})

View File

@ -1,5 +1,8 @@
use crate::font::loader::FontDataHandle;
use crate::font::system::RasterizedGlyph;
use failure::Fallible;
use failure::{bail, format_err, Error, Fallible};
use serde_derive::*;
use std::sync::Mutex;
pub mod freetype;
@ -8,3 +11,59 @@ pub mod freetype;
pub trait FontRasterizer {
fn rasterize_glyph(&self, glyph_pos: u32, size: f64, dpi: u32) -> Fallible<RasterizedGlyph>;
}
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum FontRasterizerSelection {
FreeType,
FontKit,
}
lazy_static::lazy_static! {
static ref DEFAULT_RASTER: Mutex<FontRasterizerSelection> = Mutex::new(Default::default());
}
impl Default for FontRasterizerSelection {
fn default() -> Self {
FontRasterizerSelection::FreeType
}
}
impl FontRasterizerSelection {
pub fn set_default(self) {
let mut def = DEFAULT_RASTER.lock().unwrap();
*def = self;
}
pub fn get_default() -> Self {
let def = DEFAULT_RASTER.lock().unwrap();
*def
}
pub fn variants() -> Vec<&'static str> {
vec!["FreeType", "FontKit"]
}
pub fn new_rasterizer(self, handle: &FontDataHandle) -> Fallible<Box<dyn FontRasterizer>> {
match self {
Self::FreeType => Ok(Box::new(freetype::FreeTypeRasterizer::from_locator(
handle,
)?)),
Self::FontKit => bail!("FontKit rasterizer not implemented yet"),
}
}
}
impl std::str::FromStr for FontRasterizerSelection {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"freetype" => Ok(Self::FreeType),
"fontkit" => Ok(Self::FontKit),
_ => Err(format_err!(
"{} is not a valid FontRasterizerSelection variant, possible values are {:?}",
s,
Self::variants()
)),
}
}
}

View File

@ -1,5 +1,8 @@
use crate::font::loader::FontDataHandle;
use crate::font::system::GlyphInfo;
use failure::Fallible;
use failure::{format_err, Error, Fallible};
use serde_derive::*;
use std::sync::Mutex;
pub mod harfbuzz;
@ -7,3 +10,54 @@ pub trait FontShaper {
/// Shape text and return a vector of GlyphInfo
fn shape(&self, text: &str, size: f64, dpi: u32) -> Fallible<Vec<GlyphInfo>>;
}
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum FontShaperSelection {
Harfbuzz,
}
lazy_static::lazy_static! {
static ref DEFAULT_SHAPER: Mutex<FontShaperSelection> = Mutex::new(Default::default());
}
impl Default for FontShaperSelection {
fn default() -> Self {
FontShaperSelection::Harfbuzz
}
}
impl FontShaperSelection {
pub fn set_default(self) {
let mut def = DEFAULT_SHAPER.lock().unwrap();
*def = self;
}
pub fn get_default() -> Self {
let def = DEFAULT_SHAPER.lock().unwrap();
*def
}
pub fn variants() -> Vec<&'static str> {
vec!["Harfbuzz"]
}
pub fn new_shaper(self, handles: &[FontDataHandle]) -> Fallible<Box<dyn FontShaper>> {
match self {
Self::Harfbuzz => Ok(Box::new(harfbuzz::HarfbuzzShaper::new(handles)?)),
}
}
}
impl std::str::FromStr for FontShaperSelection {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"harfbuzz" => Ok(Self::Harfbuzz),
_ => Err(format_err!(
"{} is not a valid FontShaperSelection variant, possible values are {:?}",
s,
Self::variants()
)),
}
}
}