Skip to main content

raster_fonts/
lib.rs

1//! De-/Serializable runtime representation of bitmap font metadata.
2//! 
3//! # Usage
4//! ## RON
5//! ```
6//! # fn test() -> Result<(), ron::Error> {
7//! // Requires Cargo feature `serde-deserialize` and the `ron` crate:
8//! const FONT_METADATA: &'static str = include_str!("../font-metadata.ron");
9//! let font: raster_fonts::BitmapFont = ron::from_str(FONT_METADATA)?;
10//! # Ok(())
11//! # }
12//! # test().unwrap();
13//! ```
14//! 
15//! ## JSON
16//! ```
17//! # fn test() -> Result<(), serde_json::Error> {
18//! // Requires Cargo feature `serde-deserialize` and the `serde_json` crate:
19//! const FONT_METADATA: &'static str = include_str!("../font-metadata.json");
20//! let font: raster_fonts::BitmapFont = serde_json::from_str(FONT_METADATA)?;
21//! # Ok(())
22//! # }
23//! # test().unwrap();
24//! ```
25//! 
26//! ## RKYV
27//! ```
28//! // `rkyv` requires the data to be aligned for zero-copy deserialization,
29//! // which in turn requires some trickery to achieve in a `const` context:
30//! const FONT_METADATA: &'static [u8] = {
31//!     #[repr(C)]
32//!     struct Aligned<T: ?Sized> {
33//!         _align: [usize; 0],
34//!         bytes: T,
35//!     }
36//! 
37//!     const ALIGNED: &'static Aligned<[u8]> = &Aligned {
38//!         _align: [],
39//!         bytes: *include_bytes!("../font-metadata.rkyv"),
40//!     };
41//!     
42//!     &ALIGNED.bytes
43//! };
44//! 
45//! // Using the unsafe API for maximum performance:
46//! use raster_fonts::BitmapFont;
47//! let archived_font = unsafe { rkyv::archived_root::<BitmapFont>(FONT_METADATA) };
48//! // Optionally, unpack the archived metadata before use:
49//! use rkyv::Deserialize;
50//! let deserialized_font: BitmapFont = archived_font.deserialize(&mut rkyv::Infallible).unwrap();
51//! ```
52
53#![cfg_attr(docs_rs, feature(doc_cfg))]
54#![deny(missing_docs)]
55#![warn(clippy::pedantic)]
56
57use std::collections::HashMap;
58use std::num::NonZeroU8;
59
60/// Coordinates and size of a rendered glyph in a packed bitmap.
61#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
62#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
63#[cfg_attr(feature = "rkyv", derive(rkyv::Archive))]
64#[cfg_attr(feature = "rkyv-serialize", derive(rkyv::Serialize))]
65#[cfg_attr(feature = "rkyv-deserialize", derive(rkyv::Deserialize))]
66pub struct SourceRect {
67    /// Horizontal position in the bitmap in pixels.
68    pub x: u16,
69    /// Vertical position in the bitmap in pixels.
70    pub y: u16,
71    /// Horizontal extent in pixels.
72    pub width: NonZeroU8,
73    /// Vertical extent in pixels.
74    pub height: NonZeroU8,
75}
76
77/// [`SourceRect`] and horizontal metrics of a glyph required for text layout.
78#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
79#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
80#[cfg_attr(feature = "rkyv", derive(rkyv::Archive))]
81#[cfg_attr(feature = "rkyv-serialize", derive(rkyv::Serialize))]
82#[cfg_attr(feature = "rkyv-deserialize", derive(rkyv::Deserialize))]
83pub struct BitmapGlyph {
84    /// The bounding box of the rendered glyph in the bitmap.
85    /// 
86    /// None for whitespace characters.
87    pub bitmap_source: Option<SourceRect>,
88    /// The horizontal offset that the origin of the next glyph should be from the origin of this glyph.
89    pub advance_width: f32,
90    /// The horizontal offset between the origin of this glyph and the leftmost point of the glyph.
91    pub left_side_bearing: f32,
92    /// The vertical offset between the origin of this glyph and the baseline. Typhically positive.
93    pub ascent: f32,
94}
95
96/// Runtime representation of all metadata for a single bitmap font.
97/// 
98/// Does not own or even reference the bitmap itself.
99#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
100#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
101#[cfg_attr(feature = "rkyv", derive(rkyv::Archive))]
102#[cfg_attr(feature = "rkyv-serialize", derive(rkyv::Serialize))]
103#[cfg_attr(feature = "rkyv-deserialize", derive(rkyv::Deserialize))]
104pub struct BitmapFont {
105    /// Map of unicode codepoints to glyphs in the font.
106    pub glyphs: HashMap<char, BitmapGlyph>,
107    /// Additional kerning to apply as well as that given by [`BitmapGlyph`] metrics to a pair of glyphs.
108    pub kerning_table: Option<HashMap<(char, char), f32>>,
109    /// The highest point that any glyph in the font extends above the baseline. Typically positive.
110    pub ascent: f32,
111    /// The lowest point that any glyph in the font extends below the baseline. Typically negative.
112    pub descent: f32,
113    /// The gap to leave between the descent of one line and the ascent of the next.
114    /// 
115    /// This is of course only a guideline given by the font's designers.
116    pub line_gap: f32,
117    /// The distance from the true pixel bounding box of any given glyph to the bounding box given by [`BitmapGlyph.bitmap_source`](BitmapGlyph).
118    pub padding: u32,
119}