summaryrefslogtreecommitdiff
path: root/src/font/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/font/mod.rs')
-rw-r--r--src/font/mod.rs249
1 files changed, 0 insertions, 249 deletions
diff --git a/src/font/mod.rs b/src/font/mod.rs
deleted file mode 100644
index 2353e51c..00000000
--- a/src/font/mod.rs
+++ /dev/null
@@ -1,249 +0,0 @@
-//! Font handling.
-
-mod book;
-mod variant;
-
-pub use self::book::{Coverage, FontBook, FontFlags, FontInfo};
-pub use self::variant::{FontStretch, FontStyle, FontVariant, FontWeight};
-
-use std::fmt::{self, Debug, Formatter};
-use std::hash::{Hash, Hasher};
-use std::sync::Arc;
-
-use ttf_parser::GlyphId;
-
-use self::book::find_name;
-use crate::eval::Cast;
-use crate::geom::Em;
-use crate::util::Bytes;
-
-/// An OpenType font.
-///
-/// Values of this type are cheap to clone and hash.
-#[derive(Clone)]
-pub struct Font(Arc<Repr>);
-
-/// The internal representation of a font.
-struct Repr {
- /// The raw font data, possibly shared with other fonts from the same
- /// collection. The vector's allocation must not move, because `ttf` points
- /// into it using unsafe code.
- data: Bytes,
- /// The font's index in the buffer.
- index: u32,
- /// Metadata about the font.
- info: FontInfo,
- /// The font's metrics.
- metrics: FontMetrics,
- /// The underlying ttf-parser face.
- ttf: ttf_parser::Face<'static>,
- /// The underlying rustybuzz face.
- rusty: rustybuzz::Face<'static>,
-}
-
-impl Font {
- /// Parse a font from data and collection index.
- pub fn new(data: Bytes, index: u32) -> Option<Self> {
- // Safety:
- // - The slices's location is stable in memory:
- // - We don't move the underlying vector
- // - Nobody else can move it since we have a strong ref to the `Arc`.
- // - The internal 'static lifetime is not leaked because its rewritten
- // to the self-lifetime in `ttf()`.
- let slice: &'static [u8] =
- unsafe { std::slice::from_raw_parts(data.as_ptr(), data.len()) };
-
- let ttf = ttf_parser::Face::parse(slice, index).ok()?;
- let rusty = rustybuzz::Face::from_slice(slice, index)?;
- let metrics = FontMetrics::from_ttf(&ttf);
- let info = FontInfo::from_ttf(&ttf)?;
-
- Some(Self(Arc::new(Repr { data, index, info, metrics, ttf, rusty })))
- }
-
- /// Parse all fonts in the given data.
- pub fn iter(data: Bytes) -> impl Iterator<Item = Self> {
- let count = ttf_parser::fonts_in_collection(&data).unwrap_or(1);
- (0..count).filter_map(move |index| Self::new(data.clone(), index))
- }
-
- /// The underlying buffer.
- pub fn data(&self) -> &Bytes {
- &self.0.data
- }
-
- /// The font's index in the buffer.
- pub fn index(&self) -> u32 {
- self.0.index
- }
-
- /// The font's metadata.
- pub fn info(&self) -> &FontInfo {
- &self.0.info
- }
-
- /// The font's metrics.
- pub fn metrics(&self) -> &FontMetrics {
- &self.0.metrics
- }
-
- /// The number of font units per one em.
- pub fn units_per_em(&self) -> f64 {
- self.0.metrics.units_per_em
- }
-
- /// Convert from font units to an em length.
- pub fn to_em(&self, units: impl Into<f64>) -> Em {
- Em::from_units(units, self.units_per_em())
- }
-
- /// Look up the horizontal advance width of a glyph.
- pub fn advance(&self, glyph: u16) -> Option<Em> {
- self.0
- .ttf
- .glyph_hor_advance(GlyphId(glyph))
- .map(|units| self.to_em(units))
- }
-
- /// Lookup a name by id.
- pub fn find_name(&self, id: u16) -> Option<String> {
- find_name(&self.0.ttf, id)
- }
-
- /// A reference to the underlying `ttf-parser` face.
- pub fn ttf(&self) -> &ttf_parser::Face<'_> {
- // We can't implement Deref because that would leak the
- // internal 'static lifetime.
- &self.0.ttf
- }
-
- /// A reference to the underlying `rustybuzz` face.
- pub fn rusty(&self) -> &rustybuzz::Face<'_> {
- // We can't implement Deref because that would leak the
- // internal 'static lifetime.
- &self.0.rusty
- }
-}
-
-impl Hash for Font {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.0.data.hash(state);
- self.0.index.hash(state);
- }
-}
-
-impl Debug for Font {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Font({})", self.info().family)
- }
-}
-
-impl Eq for Font {}
-
-impl PartialEq for Font {
- fn eq(&self, other: &Self) -> bool {
- self.0.data == other.0.data && self.0.index == other.0.index
- }
-}
-
-/// Metrics of a font.
-#[derive(Debug, Copy, Clone)]
-pub struct FontMetrics {
- /// How many font units represent one em unit.
- pub units_per_em: f64,
- /// The distance from the baseline to the typographic ascender.
- pub ascender: Em,
- /// The approximate height of uppercase letters.
- pub cap_height: Em,
- /// The approximate height of non-ascending lowercase letters.
- pub x_height: Em,
- /// The distance from the baseline to the typographic descender.
- pub descender: Em,
- /// Recommended metrics for a strikethrough line.
- pub strikethrough: LineMetrics,
- /// Recommended metrics for an underline.
- pub underline: LineMetrics,
- /// Recommended metrics for an overline.
- pub overline: LineMetrics,
-}
-
-impl FontMetrics {
- /// Extract the font's metrics.
- pub fn from_ttf(ttf: &ttf_parser::Face) -> Self {
- let units_per_em = f64::from(ttf.units_per_em());
- let to_em = |units| Em::from_units(units, units_per_em);
-
- let ascender = to_em(ttf.typographic_ascender().unwrap_or(ttf.ascender()));
- let cap_height = ttf.capital_height().filter(|&h| h > 0).map_or(ascender, to_em);
- let x_height = ttf.x_height().filter(|&h| h > 0).map_or(ascender, to_em);
- let descender = to_em(ttf.typographic_descender().unwrap_or(ttf.descender()));
- let strikeout = ttf.strikeout_metrics();
- let underline = ttf.underline_metrics();
-
- let strikethrough = LineMetrics {
- position: strikeout.map_or(Em::new(0.25), |s| to_em(s.position)),
- thickness: strikeout
- .or(underline)
- .map_or(Em::new(0.06), |s| to_em(s.thickness)),
- };
-
- let underline = LineMetrics {
- position: underline.map_or(Em::new(-0.2), |s| to_em(s.position)),
- thickness: underline
- .or(strikeout)
- .map_or(Em::new(0.06), |s| to_em(s.thickness)),
- };
-
- let overline = LineMetrics {
- position: cap_height + Em::new(0.1),
- thickness: underline.thickness,
- };
-
- Self {
- units_per_em,
- ascender,
- cap_height,
- x_height,
- descender,
- strikethrough,
- underline,
- overline,
- }
- }
-
- /// Look up a vertical metric.
- pub fn vertical(&self, metric: VerticalFontMetric) -> Em {
- match metric {
- VerticalFontMetric::Ascender => self.ascender,
- VerticalFontMetric::CapHeight => self.cap_height,
- VerticalFontMetric::XHeight => self.x_height,
- VerticalFontMetric::Baseline => Em::zero(),
- VerticalFontMetric::Descender => self.descender,
- }
- }
-}
-
-/// Metrics for a decorative line.
-#[derive(Debug, Copy, Clone)]
-pub struct LineMetrics {
- /// The vertical offset of the line from the baseline. Positive goes
- /// upwards, negative downwards.
- pub position: Em,
- /// The thickness of the line.
- pub thickness: Em,
-}
-
-/// Identifies a vertical metric of a font.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
-pub enum VerticalFontMetric {
- /// The font's ascender, which typically exceeds the height of all glyphs.
- Ascender,
- /// The approximate height of uppercase letters.
- CapHeight,
- /// The approximate height of non-ascending lowercase letters.
- XHeight,
- /// The baseline on which the letters rest.
- Baseline,
- /// The font's ascender, which typically exceeds the depth of all glyphs.
- Descender,
-}