pub struct FontChain<'a> { /* private fields */ }Expand description
The glyph source a backend draws from: a primary BitmapFont plus an ordered list of
fallback fonts.
This is the only character-to-glyph path the bundled pixel backends have. A single font is a
chain of one (FontChain::from(font)), so SoftwareBackendBuilder::font and
GlBackendBuilder::font both take an impl Into<FontChain<'static>> and there is no second,
chain-blind route that could quietly ignore a font’s declared repertoire.
resolve tries the primary font first, then each fallback in order, and only
if every font misses substitutes the solid block ('█') from the first font in the chain that
has one. This lets a caller layer, say, an ASCII or partial-coverage primary font with one or
more broader fallback fonts, so a char missing from the primary doesn’t automatically become a
solid block if some other font in the chain actually has it.
This type ships no bundled fallback font data: every font in the chain, primary or fallback, is supplied by the caller. Bundling a ready-to-use Latin-1/Extended or sub-cell (quadrant/sextant/braille) fallback font is a natural follow-up now that this mechanism is reachable end to end, but is out of scope here.
A fallback font only extends the chain’s repertoire if it declares coverage for the
characters it is meant to answer for. A BitmapFont::new font is always resolved through
the built-in CP437 table, so stacking several CP437 fonts in a chain never reaches past CP437:
every font in the chain answers the identical question. To actually extend coverage (e.g.
quadrants, sextants, braille, none of which CP437 has a mapping for), build the fallback font
with BitmapFont::with_charset and an explicit table covering those codepoints. Until a
chain does, retroglyph_core::symbols‘s quantize_quadrant/quantize_sextant glyphs render
as a solid block on the pixel backends; see those functions’ docs.
§Examples
use retroglyph_window::font::{BitmapFont, FontChain};
static ASCII: [u8; 128 * 16] = [0; 128 * 16];
static QUADRANTS: [u8; 3 * 16] = [0; 3 * 16];
const QUADRANT_CHARSET: [(char, u8); 3] = [('▘', 0), ('▝', 1), ('▖', 2)];
const PRIMARY: BitmapFont = BitmapFont::new(&ASCII, 8, 16, 128);
const SUBCELL: BitmapFont = BitmapFont::with_charset(&QUADRANTS, 8, 16, 3, &QUADRANT_CHARSET);
static FALLBACKS: [BitmapFont; 1] = [SUBCELL];
let chain = FontChain::new(PRIMARY, &FALLBACKS);
let quadrant = chain.resolve('▘').expect("covered by the fallback font");
assert_eq!(quadrant.font_index(), 1);
assert!(!quadrant.is_notdef());Implementations§
Source§impl<'a> FontChain<'a>
impl<'a> FontChain<'a>
Sourcepub const fn new(primary: BitmapFont, fallbacks: &'a [BitmapFont]) -> Self
pub const fn new(primary: BitmapFont, fallbacks: &'a [BitmapFont]) -> Self
Constructs a chain from a primary font and an ordered list of fallback fonts.
Sourcepub fn fonts(&self) -> impl Iterator<Item = &BitmapFont>
pub fn fonts(&self) -> impl Iterator<Item = &BitmapFont>
The fonts in resolution order: the primary font first, then each fallback.
The position of a font in this iterator is its ResolvedGlyph::font_index.
Sourcepub const fn font_count(&self) -> usize
pub const fn font_count(&self) -> usize
The number of fonts in the chain (always at least one).
Sourcepub fn glyph_size(&self) -> Option<(u8, u8)>
pub fn glyph_size(&self) -> Option<(u8, u8)>
The glyph cell size ((width, height) in unscaled pixels) shared by every font in the
chain, or None if the fonts disagree.
A grid has one cell size, so a chain whose fonts don’t agree on theirs has no single answer for how big a cell is; backends reject such a chain at build time rather than picking one font’s size and letting the others overflow or under-fill their cells.
Sourcepub fn resolve(&self, ch: char) -> Option<ResolvedGlyph>
pub fn resolve(&self, ch: char) -> Option<ResolvedGlyph>
Resolves ch to a drawable glyph, trying the primary font first, then each fallback font
in order.
If no font covers ch, this substitutes the solid block ('█') from the first font in
the chain that covers it, flagged as ResolvedGlyph::is_notdef. None means the
chain cannot draw ch at all, not even a substitute box, and the caller should draw
nothing: a chain of narrow with_charset fonts (say, braille only) legitimately has no
solid block to fall back to.
A returned glyph is always in range for its font, so ResolvedGlyph::rows and
BitmapFont::glyph_pixels cannot panic on it.
Trait Implementations§
Source§impl From<BitmapFont> for FontChain<'static>
impl From<BitmapFont> for FontChain<'static>
Source§fn from(font: BitmapFont) -> Self
fn from(font: BitmapFont) -> Self
Source§impl<'a> PartialEq for FontChain<'a>
impl<'a> PartialEq for FontChain<'a>
impl<'a> Copy for FontChain<'a>
impl<'a> Eq for FontChain<'a>
impl<'a> StructuralPartialEq for FontChain<'a>
Auto Trait Implementations§
impl<'a> Freeze for FontChain<'a>
impl<'a> RefUnwindSafe for FontChain<'a>
impl<'a> Send for FontChain<'a>
impl<'a> Sync for FontChain<'a>
impl<'a> Unpin for FontChain<'a>
impl<'a> UnsafeUnpin for FontChain<'a>
impl<'a> UnwindSafe for FontChain<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<C> WithAlpha for Cwhere
C: Copy,
impl<C> WithAlpha for Cwhere
C: Copy,
§fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
self with alpha, storing alpha before the color in memory
(see [AlphaFirst]).§fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
self with alpha, storing alpha after the color in memory
(see [AlphaLast]).