Add the ability to load application fonts by path

The viewer command line tool also gains the ability to specify them via `--app-font=/path/to/font.ttf` , which can be specified multiple times.
This commit is contained in:
Simon Hausmann 2021-02-17 14:16:02 +01:00
parent 09ea6572e4
commit 45fe6c3e8d
7 changed files with 84 additions and 0 deletions

View file

@ -178,6 +178,15 @@ pub fn register_application_font_from_memory(
sixtyfps_rendering_backend_default::backend().register_application_font_from_memory(data)
}
/// This function can be used to register a custom TrueType font with SixtyFPS,
/// for use with the `font-family` property. The provided path must refer to a valid TrueType
/// font.
pub fn register_application_font_from_path<P: AsRef<std::path::Path>>(
path: P,
) -> Result<(), Box<dyn std::error::Error>> {
sixtyfps_rendering_backend_default::backend().register_application_font_from_path(path.as_ref())
}
// FIXME: this should not be in this namespace
// but the name is `sixtyfps::StateInfo` in builtin.60
#[doc(hidden)]

View file

@ -11,6 +11,8 @@ LICENSE END */
The backend is the abstraction for crates that need to do the actual drawing and event loop
*/
use std::path::Path;
use crate::window::ComponentWindow;
/// Interface implemented by backends
@ -30,6 +32,14 @@ pub trait Backend: Send + Sync {
data: &'static [u8],
) -> Result<(), Box<dyn std::error::Error>>;
/// This function can be used to register a custom TrueType font with SixtyFPS,
/// for use with the `font-family` property. The provided path must refer to a valid TrueType
/// font.
fn register_application_font_from_path(
&'static self,
path: &Path,
) -> Result<(), Box<dyn std::error::Error>>;
fn set_clipboard_text(&'static self, text: String);
fn clipboard_text(&'static self) -> Option<String>;
}

View file

@ -213,3 +213,9 @@ pub async fn load(
pub fn run_event_loop() {
sixtyfps_rendering_backend_default::backend().run_event_loop();
}
pub fn register_application_font_from_path<P: AsRef<std::path::Path>>(
path: P,
) -> Result<(), Box<dyn std::error::Error>> {
sixtyfps_rendering_backend_default::backend().register_application_font_from_path(path.as_ref())
}

View file

@ -33,6 +33,17 @@ pub fn register_application_font_from_memory(
Ok(())
}
pub fn register_application_font_from_path(
path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
// Should use FontDb::load_font_file but that requires the `fs` feature, for which I can't figure
// out how to exclude it from the wasm build. It's inclusion implies mmap, which doesn't compile
// with wasm.
let data = std::fs::read(path)?;
APPLICATION_FONTS.with(|fontdb| fontdb.borrow_mut().load_font_data(data));
Ok(())
}
pub(crate) fn try_load_app_font(
canvas: &CanvasRc,
request: &FontRequest,

View file

@ -1438,6 +1438,13 @@ impl sixtyfps_corelib::backend::Backend for Backend {
self::register_application_font_from_memory(data)
}
fn register_application_font_from_path(
&'static self,
path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
self::register_application_font_from_path(path)
}
fn set_clipboard_text(&'static self, text: String) {
use copypasta::ClipboardProvider;
CLIPBOARD.with(|clipboard| clipboard.borrow_mut().set_contents(text).ok());

View file

@ -98,6 +98,17 @@ pub const HAS_NATIVE_STYLE: bool = cfg!(not(no_qt));
/// False if the backend was compiled without Qt so it wouldn't do anything
pub const IS_AVAILABLE: bool = cfg!(not(no_qt));
#[cfg(unix)]
fn path_to_bytes<'a>(path: &'a std::path::Path) -> &'a [u8] {
use std::os::unix::ffi::OsStrExt;
path.as_os_str().as_bytes()
}
#[cfg(not(unix))]
fn path_to_bytes<'a>(path: &'a std::path::Path) -> &'a [u8] {
path.to_string_lossy().to_string().as_bytes()
}
pub struct Backend;
impl sixtyfps_corelib::backend::Backend for Backend {
fn create_window(&'static self) -> ComponentWindow {
@ -138,6 +149,22 @@ impl sixtyfps_corelib::backend::Backend for Backend {
Ok(())
}
fn register_application_font_from_path(
&'static self,
_path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
#[cfg(not(no_qt))]
{
use cpp::cpp;
let encoded_path: qttypes::QByteArray = path_to_bytes(_path).into();
cpp! {unsafe [encoded_path as "QByteArray"] {
ensure_initialized();
QFontDatabase::addApplicationFont(QFile::decodeName(encoded_path));
} }
};
Ok(())
}
fn set_clipboard_text(&'static self, _text: String) {
#[cfg(not(no_qt))]
{

View file

@ -20,12 +20,26 @@ struct Cli {
/// The style name (empty, or 'qt')
#[structopt(long, name = "style name", default_value)]
style: String,
/// An optional application font
#[structopt(long, name = "application font")]
app_font: Option<Vec<String>>,
}
fn main() -> std::io::Result<()> {
let args = Cli::from_args();
let source = std::fs::read_to_string(&args.path)?;
args.app_font.map(|fonts| {
fonts.iter().for_each(|font_path| {
if let Err(app_font_err) =
sixtyfps_interpreter::register_application_font_from_path(&font_path)
{
eprintln!("Error loading app font {}: {}", font_path, app_font_err);
}
});
});
let mut compiler_config = sixtyfps_compilerlib::CompilerConfiguration::new(
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
);