desktop: Load device fonts from system

This commit is contained in:
Tom Schuster 2023-12-27 23:10:46 +01:00 committed by Nathan Adams
parent 7e4ac986f2
commit 2a2bcbbfbc
4 changed files with 71 additions and 12 deletions

View File

@ -49,12 +49,16 @@ impl App {
.build(&event_loop)?;
let window = Rc::new(window);
let mut gui = GuiController::new(window.clone(), &event_loop, &opt)?;
let mut font_database = fontdb::Database::default();
font_database.load_system_fonts();
let mut gui = GuiController::new(window.clone(), &event_loop, &opt, &font_database)?;
let mut player = PlayerController::new(
event_loop.create_proxy(),
window.clone(),
gui.descriptors().clone(),
font_database,
);
if let Some(movie_url) = movie_url {

View File

@ -1,6 +1,7 @@
use anyhow::{Context, Error};
use arboard::Clipboard;
use chrono::{DateTime, Utc};
use fontdb::Family;
use rfd::{
AsyncFileDialog, FileHandle, MessageButtons, MessageDialog, MessageDialogResult, MessageLevel,
};
@ -120,12 +121,17 @@ pub struct DesktopUiBackend {
language: LanguageIdentifier,
preferred_cursor: MouseCursor,
open_url_mode: OpenURLMode,
font_database: Rc<fontdb::Database>,
/// Is a dialog currently open
dialog_open: bool,
}
impl DesktopUiBackend {
pub fn new(window: Rc<Window>, open_url_mode: OpenURLMode) -> Result<Self, Error> {
pub fn new(
window: Rc<Window>,
open_url_mode: OpenURLMode,
font_database: Rc<fontdb::Database>,
) -> Result<Self, Error> {
let preferred_language = get_locale();
let language = preferred_language
.and_then(|l| l.parse().ok())
@ -138,6 +144,7 @@ impl DesktopUiBackend {
preferred_cursor: MouseCursor::Arrow,
open_url_mode,
dialog_open: false,
font_database,
})
}
@ -249,11 +256,52 @@ impl UiBackend for DesktopUiBackend {
fn load_device_font(
&self,
_name: &str,
_is_bold: bool,
_is_italic: bool,
_register: &mut dyn FnMut(FontDefinition),
name: &str,
is_bold: bool,
is_italic: bool,
register: &mut dyn FnMut(FontDefinition),
) {
let query = fontdb::Query {
families: &[Family::Name(name)],
weight: if is_bold {
fontdb::Weight::BOLD
} else {
fontdb::Weight::NORMAL
},
style: if is_italic {
fontdb::Style::Italic
} else {
fontdb::Style::Normal
},
..Default::default()
};
// It'd be nice if we can get the full list of candidates... Feature request?
if let Some(id) = self.font_database.query(&query) {
if let Some(face) = self.font_database.face(id) {
tracing::info!("Loading device font \"{}\" for \"{name}\" (italic: {is_italic}, bold: {is_bold})", face.post_script_name);
match &face.source {
fontdb::Source::File(path) => match std::fs::read(path) {
Ok(bytes) => register(FontDefinition::FontFile {
name: name.to_owned(),
is_bold,
is_italic,
data: bytes,
}),
Err(e) => error!("Couldn't read font file at {path:?}: {e}"),
},
fontdb::Source::Binary(bin) | fontdb::Source::SharedFile(_, bin) => {
register(FontDefinition::FontFile {
name: name.to_owned(),
is_bold,
is_italic,
data: bin.as_ref().as_ref().to_vec(),
})
}
};
}
}
}
// Unused on desktop

View File

@ -45,6 +45,7 @@ impl GuiController {
window: Rc<Window>,
event_loop: &EventLoop<RuffleEvent>,
opt: &Opt,
font_database: &Database,
) -> anyhow::Result<Self> {
let backend: wgpu::Backends = opt.graphics.into();
if wgpu::Backends::SECONDARY.contains(backend) {
@ -104,7 +105,8 @@ impl GuiController {
let egui_renderer = egui_wgpu::Renderer::new(&descriptors.device, surface_format, None, 1);
let event_loop = event_loop.create_proxy();
let gui = RuffleGui::new(event_loop, opt.movie_url.clone(), PlayerOptions::from(opt));
let system_fonts = load_system_fonts(gui.locale.to_owned()).unwrap_or_default();
let system_fonts =
load_system_fonts(font_database, gui.locale.to_owned()).unwrap_or_default();
egui_ctx.set_fonts(system_fonts);
egui_extras::install_image_loaders(&egui_ctx);
@ -330,10 +332,10 @@ impl GuiController {
}
// try to load known unicode supporting fonts to draw cjk characters in egui
fn load_system_fonts(locale: LanguageIdentifier) -> anyhow::Result<egui::FontDefinitions> {
let mut font_database = Database::default();
font_database.load_system_fonts();
fn load_system_fonts(
font_database: &Database,
locale: LanguageIdentifier,
) -> anyhow::Result<egui::FontDefinitions> {
let mut families = Vec::new();
if let Some(windows_font) = match locale.language.as_str() {
"ja" => Some(Family::Name("MS UI Gothic")),

View File

@ -97,6 +97,7 @@ impl ActivePlayer {
window: Rc<Window>,
descriptors: Arc<Descriptors>,
movie_view: MovieView,
font_database: Rc<fontdb::Database>,
) -> Self {
let mut builder = PlayerBuilder::new();
@ -152,7 +153,7 @@ impl ActivePlayer {
window: window.clone(),
}))
.with_ui(
DesktopUiBackend::new(window.clone(), opt.open_url_mode)
DesktopUiBackend::new(window.clone(), opt.open_url_mode, font_database)
.expect("Couldn't create ui backend"),
)
.with_autoplay(true)
@ -207,6 +208,7 @@ pub struct PlayerController {
event_loop: EventLoopProxy<RuffleEvent>,
window: Rc<Window>,
descriptors: Arc<Descriptors>,
font_database: Rc<fontdb::Database>,
}
impl PlayerController {
@ -214,12 +216,14 @@ impl PlayerController {
event_loop: EventLoopProxy<RuffleEvent>,
window: Rc<Window>,
descriptors: Arc<Descriptors>,
font_database: fontdb::Database,
) -> Self {
Self {
player: None,
event_loop,
window,
descriptors,
font_database: Rc::new(font_database),
}
}
@ -231,6 +235,7 @@ impl PlayerController {
self.window.clone(),
self.descriptors.clone(),
movie_view,
self.font_database.clone(),
));
}