Support non-static list of fallbacks
This commit is contained in:
parent
9a4d80d116
commit
ae0fb9b561
2 changed files with 49 additions and 3 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use core::mem;
|
||||||
|
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use fontdb::Family;
|
use fontdb::Family;
|
||||||
|
|
@ -27,13 +29,13 @@ mod platform;
|
||||||
|
|
||||||
pub trait Fallback {
|
pub trait Fallback {
|
||||||
/// Fallbacks to use after any script specific fallbacks
|
/// Fallbacks to use after any script specific fallbacks
|
||||||
fn common_fallback(&self) -> &'static [&'static str];
|
fn common_fallback(&self) -> &[&'static str];
|
||||||
|
|
||||||
/// Fallbacks to never use
|
/// Fallbacks to never use
|
||||||
fn forbidden_fallback(&self) -> &'static [&'static str];
|
fn forbidden_fallback(&self) -> &[&'static str];
|
||||||
|
|
||||||
/// Fallbacks to use per script
|
/// Fallbacks to use per script
|
||||||
fn script_fallback(&self, script: Script, locale: &str) -> &'static [&'static str];
|
fn script_fallback(&self, script: Script, locale: &str) -> &[&'static str];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use platform::PlatformFallback;
|
pub use platform::PlatformFallback;
|
||||||
|
|
@ -279,12 +281,22 @@ impl Iterator for FontFallbackIter<'_> {
|
||||||
.font_system
|
.font_system
|
||||||
.fallbacks
|
.fallbacks
|
||||||
.script_fallback(script, self.font_system.locale());
|
.script_fallback(script, self.font_system.locale());
|
||||||
|
self.font_system.scratch_fallbacks.clear();
|
||||||
|
self.font_system
|
||||||
|
.scratch_fallbacks
|
||||||
|
.extend_from_slice(script_families);
|
||||||
|
let mut script_families = mem::take(&mut self.font_system.scratch_fallbacks);
|
||||||
|
|
||||||
while self.script_i.1 < script_families.len() {
|
while self.script_i.1 < script_families.len() {
|
||||||
let script_family = script_families[self.script_i.1];
|
let script_family = script_families[self.script_i.1];
|
||||||
self.script_i.1 += 1;
|
self.script_i.1 += 1;
|
||||||
for m_key in font_match_keys_iter(false) {
|
for m_key in font_match_keys_iter(false) {
|
||||||
if self.face_contains_family(m_key.id, script_family) {
|
if self.face_contains_family(m_key.id, script_family) {
|
||||||
if let Some(font) = self.font_system.get_font(m_key.id) {
|
if let Some(font) = self.font_system.get_font(m_key.id) {
|
||||||
|
mem::swap(
|
||||||
|
&mut script_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
return Some(font);
|
return Some(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -296,28 +308,50 @@ impl Iterator for FontFallbackIter<'_> {
|
||||||
self.font_system.locale(),
|
self.font_system.locale(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
mem::swap(
|
||||||
|
&mut script_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
|
|
||||||
self.script_i.0 += 1;
|
self.script_i.0 += 1;
|
||||||
self.script_i.1 = 0;
|
self.script_i.1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let common_families = self.font_system.fallbacks.common_fallback();
|
let common_families = self.font_system.fallbacks.common_fallback();
|
||||||
|
self.font_system.scratch_fallbacks.clear();
|
||||||
|
self.font_system
|
||||||
|
.scratch_fallbacks
|
||||||
|
.extend_from_slice(common_families);
|
||||||
|
let mut common_families = mem::take(&mut self.font_system.scratch_fallbacks);
|
||||||
while self.common_i < common_families.len() {
|
while self.common_i < common_families.len() {
|
||||||
let common_family = common_families[self.common_i];
|
let common_family = common_families[self.common_i];
|
||||||
self.common_i += 1;
|
self.common_i += 1;
|
||||||
for m_key in font_match_keys_iter(false) {
|
for m_key in font_match_keys_iter(false) {
|
||||||
if self.face_contains_family(m_key.id, common_family) {
|
if self.face_contains_family(m_key.id, common_family) {
|
||||||
if let Some(font) = self.font_system.get_font(m_key.id) {
|
if let Some(font) = self.font_system.get_font(m_key.id) {
|
||||||
|
mem::swap(
|
||||||
|
&mut common_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
return Some(font);
|
return Some(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::debug!("failed to find family '{}'", common_family);
|
log::debug!("failed to find family '{}'", common_family);
|
||||||
}
|
}
|
||||||
|
mem::swap(
|
||||||
|
&mut common_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
|
|
||||||
//TODO: do we need to do this?
|
//TODO: do we need to do this?
|
||||||
//TODO: do not evaluate fonts more than once!
|
//TODO: do not evaluate fonts more than once!
|
||||||
let forbidden_families = self.font_system.fallbacks.forbidden_fallback();
|
let forbidden_families = self.font_system.fallbacks.forbidden_fallback();
|
||||||
|
self.font_system.scratch_fallbacks.clear();
|
||||||
|
self.font_system
|
||||||
|
.scratch_fallbacks
|
||||||
|
.extend_from_slice(forbidden_families);
|
||||||
|
let mut forbidden_families = mem::take(&mut self.font_system.scratch_fallbacks);
|
||||||
while self.other_i < self.font_match_keys.len() {
|
while self.other_i < self.font_match_keys.len() {
|
||||||
let id = self.font_match_keys[self.other_i].id;
|
let id = self.font_match_keys[self.other_i].id;
|
||||||
self.other_i += 1;
|
self.other_i += 1;
|
||||||
|
|
@ -326,10 +360,18 @@ impl Iterator for FontFallbackIter<'_> {
|
||||||
.all(|family_name| !self.face_contains_family(id, family_name))
|
.all(|family_name| !self.face_contains_family(id, family_name))
|
||||||
{
|
{
|
||||||
if let Some(font) = self.font_system.get_font(id) {
|
if let Some(font) = self.font_system.get_font(id) {
|
||||||
|
mem::swap(
|
||||||
|
&mut forbidden_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
return Some(font);
|
return Some(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mem::swap(
|
||||||
|
&mut forbidden_families,
|
||||||
|
&mut self.font_system.scratch_fallbacks,
|
||||||
|
);
|
||||||
|
|
||||||
self.end = true;
|
self.end = true;
|
||||||
None
|
None
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,9 @@ pub struct FontSystem {
|
||||||
|
|
||||||
/// List of fallbacks
|
/// List of fallbacks
|
||||||
pub(crate) fallbacks: Box<dyn Fallback>,
|
pub(crate) fallbacks: Box<dyn Fallback>,
|
||||||
|
|
||||||
|
/// Scratch buffer for fallback list
|
||||||
|
pub(crate) scratch_fallbacks: Vec<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for FontSystem {
|
impl fmt::Debug for FontSystem {
|
||||||
|
|
@ -213,6 +216,7 @@ impl FontSystem {
|
||||||
shape_run_cache: crate::ShapeRunCache::default(),
|
shape_run_cache: crate::ShapeRunCache::default(),
|
||||||
shape_buffer: ShapeBuffer::default(),
|
shape_buffer: ShapeBuffer::default(),
|
||||||
fallbacks: Box::new(fallbacks),
|
fallbacks: Box::new(fallbacks),
|
||||||
|
scratch_fallbacks: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue