Skip to content

Commit

Permalink
Try to load font by path (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
l4l authored Jan 30, 2022
1 parent e43f9a1 commit 7d5afc9
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 22 deletions.
10 changes: 9 additions & 1 deletion src/config/params.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use raqote::SolidSource;

use super::{Color, Config};
Expand Down Expand Up @@ -126,7 +128,13 @@ fn default_font_color() -> SolidSource {
}

fn font_by_name(name: String) -> Font {
Font::font_by_name(name.as_str()).unwrap_or_else(|e| panic!("cannot find font {}: {}", name, e))
let path = Path::new(name.as_str());
if path.is_absolute() && path.exists() {
Font::font_by_path(path)
} else {
Font::font_by_name(name.as_str())
}
.unwrap_or_else(|e| panic!("cannot find font {}: {}", name, e))
}

fn color_to_solid_source(x: Color) -> SolidSource {
Expand Down
4 changes: 4 additions & 0 deletions src/font.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use anyhow::Result;
use raqote::{AntialiasMode, DrawOptions, DrawTarget, Point, SolidSource};

Expand Down Expand Up @@ -28,6 +30,8 @@ pub trait FontBackend: Sized {

fn font_by_name(name: &str) -> Result<Self>;

fn font_by_path(path: &Path) -> Result<Self>;

fn draw(
&self,
dt: &mut DrawTarget,
Expand Down
42 changes: 21 additions & 21 deletions src/font/fdue.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cell::RefCell;
use std::collections::BinaryHeap;
use std::path::Path;

use anyhow::Context;
use fontdue::layout::{CoordinateSystem, Layout, LayoutSettings, TextStyle, VerticalAlign};
Expand All @@ -10,35 +11,27 @@ use rust_fontconfig::{FcFontCache, FcFontPath, FcPattern};

use super::{FontBackend, FontColor, Result};

static FONTCONFIG: Lazy<FontConfig> = Lazy::new(FontConfig::new);
static FONTCONFIG_CACHE: Lazy<FcFontCache> = Lazy::new(FcFontCache::build);
const BUF_SIZE: usize = 256 * 256;

pub struct Font {
inner: fontdue::Font,
}

// Because Font is re-created on every `draw` call method we cached dynamic allocations
struct FontConfig {
cache: FcFontCache,
// Layout in fontdue uses allocations, so we're reusing it for reduce memory allocations
layout: RefCell<Layout>,
// Move buffer to heap, because it is very big for stack; only one allocation happens
buffer: RefCell<Vec<u32>>,
}

impl FontConfig {
fn new() -> Self {
impl Font {
fn with_font(inner: fontdue::Font) -> Self {
Self {
cache: FcFontCache::build(),
inner,
layout: RefCell::new(Layout::new(CoordinateSystem::PositiveYDown)),
buffer: RefCell::new(vec![0; BUF_SIZE]),
}
}
}

//SAFETY: We do not use multiple threads, so it never happens that the & is posted to another thread
unsafe impl Sync for FontConfig {}

#[derive(Eq)]
struct FuzzyResult<'a> {
text: &'a str,
Expand Down Expand Up @@ -75,14 +68,13 @@ impl Font {
)
.map_err(|e| anyhow::anyhow!("{}", e))?;

Ok(Font { inner })
Ok(Font::with_font(inner))
}

fn try_find_best_font(name: &str) -> Vec<String> {
const COUNT_MATCHES: usize = 5;

FONTCONFIG
.cache
FONTCONFIG_CACHE
.list()
.keys()
.filter_map(|font| {
Expand All @@ -103,17 +95,15 @@ impl Font {

impl FontBackend for Font {
fn default() -> Self {
FONTCONFIG
.cache
FONTCONFIG_CACHE
.query(&FcPattern::default())
.map(Font::from_fc_path)
.unwrap()
.unwrap()
}

fn font_by_name(name: &str) -> Result<Self> {
FONTCONFIG
.cache
FONTCONFIG_CACHE
.query(&FcPattern {
name: Some(name.to_string()),
..Default::default()
Expand All @@ -130,6 +120,16 @@ impl FontBackend for Font {
})?
}

fn font_by_path(path: &Path) -> Result<Self> {
Font::from_fc_path(&FcFontPath {
path: path
.to_str()
.ok_or_else(|| anyhow::anyhow!("Invalid path"))?
.to_owned(),
font_index: 0,
})
}

fn draw(
&self,
dt: &mut DrawTarget,
Expand All @@ -139,8 +139,8 @@ impl FontBackend for Font {
color: FontColor,
opts: &DrawOptions,
) {
let mut buf = FONTCONFIG.buffer.borrow_mut();
let mut layout = FONTCONFIG.layout.borrow_mut();
let mut buf = self.buffer.borrow_mut();
let mut layout = self.layout.borrow_mut();

layout.reset(&LayoutSettings {
x: start_pos.x,
Expand Down
6 changes: 6 additions & 0 deletions src/font/fontkit.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use font_kit::family_name::FamilyName;
pub use font_kit::loaders::freetype::Font;
use font_kit::properties::Properties;
Expand All @@ -22,6 +24,10 @@ impl FontBackend for Font {
.map_err(Into::into)
}

fn font_by_path(path: &Path) -> Result<Self> {
Font::from_path(path, 0).map_err(Into::into)
}

fn draw(
&self,
dt: &mut DrawTarget,
Expand Down

0 comments on commit 7d5afc9

Please sign in to comment.