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)?; .build(&event_loop)?;
let window = Rc::new(window); 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( let mut player = PlayerController::new(
event_loop.create_proxy(), event_loop.create_proxy(),
window.clone(), window.clone(),
gui.descriptors().clone(), gui.descriptors().clone(),
font_database,
); );
if let Some(movie_url) = movie_url { if let Some(movie_url) = movie_url {

View File

@ -1,6 +1,7 @@
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use arboard::Clipboard; use arboard::Clipboard;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use fontdb::Family;
use rfd::{ use rfd::{
AsyncFileDialog, FileHandle, MessageButtons, MessageDialog, MessageDialogResult, MessageLevel, AsyncFileDialog, FileHandle, MessageButtons, MessageDialog, MessageDialogResult, MessageLevel,
}; };
@ -120,12 +121,17 @@ pub struct DesktopUiBackend {
language: LanguageIdentifier, language: LanguageIdentifier,
preferred_cursor: MouseCursor, preferred_cursor: MouseCursor,
open_url_mode: OpenURLMode, open_url_mode: OpenURLMode,
font_database: Rc<fontdb::Database>,
/// Is a dialog currently open /// Is a dialog currently open
dialog_open: bool, dialog_open: bool,
} }
impl DesktopUiBackend { 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 preferred_language = get_locale();
let language = preferred_language let language = preferred_language
.and_then(|l| l.parse().ok()) .and_then(|l| l.parse().ok())
@ -138,6 +144,7 @@ impl DesktopUiBackend {
preferred_cursor: MouseCursor::Arrow, preferred_cursor: MouseCursor::Arrow,
open_url_mode, open_url_mode,
dialog_open: false, dialog_open: false,
font_database,
}) })
} }
@ -249,11 +256,52 @@ impl UiBackend for DesktopUiBackend {
fn load_device_font( fn load_device_font(
&self, &self,
_name: &str, name: &str,
_is_bold: bool, is_bold: bool,
_is_italic: bool, is_italic: bool,
_register: &mut dyn FnMut(FontDefinition), 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 // Unused on desktop

View File

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

View File

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