Skip to content

Commit

Permalink
Use fontations for shape planning (#8)
Browse files Browse the repository at this point in the history
Replaces the ttf-parser code for script, langsys and feature lookup.

GSUB/GPOS is now fully fontations.
  • Loading branch information
dfrg authored Sep 11, 2024
1 parent cdb55cc commit 2fb01f7
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 90 deletions.
62 changes: 13 additions & 49 deletions src/hb/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ use core_maths::CoreFloat;

use crate::hb::paint_extents::hb_paint_extents_context_t;
use ttf_parser::gdef::GlyphClass;
use ttf_parser::opentype_layout::LayoutTable;
use ttf_parser::{GlyphId, RgbaColor};

use super::buffer::GlyphPropsFlags;
use super::fonta;
use super::ot_layout::TableIndex;
use super::ot_layout_common::{PositioningTable, SubstitutionTable};
use crate::Variation;

/// A font face handle.
Expand All @@ -21,22 +19,6 @@ pub struct hb_font_t<'a> {
pub(crate) units_per_em: u16,
pixels_per_em: Option<(u16, u16)>,
pub(crate) points_per_em: Option<f32>,
pub(crate) gsub: Option<SubstitutionTable<'a>>,
pub(crate) gpos: Option<PositioningTable<'a>>,
}

impl<'a> AsRef<ttf_parser::Face<'a>> for hb_font_t<'a> {
#[inline]
fn as_ref(&self) -> &ttf_parser::Face<'a> {
&self.ttfp_face
}
}

impl<'a> AsMut<ttf_parser::Face<'a>> for hb_font_t<'a> {
#[inline]
fn as_mut(&mut self) -> &mut ttf_parser::Face<'a> {
&mut self.ttfp_face
}
}

impl<'a> core::ops::Deref for hb_font_t<'a> {
Expand All @@ -48,13 +30,6 @@ impl<'a> core::ops::Deref for hb_font_t<'a> {
}
}

impl<'a> core::ops::DerefMut for hb_font_t<'a> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ttfp_face
}
}

impl<'a> hb_font_t<'a> {
/// Creates a new `Face` from data.
///
Expand All @@ -67,28 +42,10 @@ impl<'a> hb_font_t<'a> {
units_per_em: face.units_per_em(),
pixels_per_em: None,
points_per_em: None,
gsub: face.tables().gsub.map(SubstitutionTable::new),
gpos: face.tables().gpos.map(PositioningTable::new),
ttfp_face: face,
})
}

/// Creates a new [`Face`] from [`ttf_parser::Face`].
///
/// Data will be referenced, not owned.
pub fn from_face(face: ttf_parser::Face<'a>) -> Self {
let font = fonta::Font::new(face.raw_face().data, 0).unwrap();
hb_font_t {
font,
units_per_em: face.units_per_em(),
pixels_per_em: None,
points_per_em: None,
gsub: face.tables().gsub.map(SubstitutionTable::new),
gpos: face.tables().gpos.map(PositioningTable::new),
ttfp_face: face,
}
}

// TODO: remove
/// Returns face’s units per EM.
#[inline]
Expand Down Expand Up @@ -124,7 +81,7 @@ impl<'a> hb_font_t<'a> {
/// Sets font variations.
pub fn set_variations(&mut self, variations: &[Variation]) {
for variation in variations {
self.set_variation(variation.tag, variation.value);
self.ttfp_face.set_variation(variation.tag, variation.value);
}
self.font.set_coords(self.ttfp_face.variation_coordinates());
}
Expand Down Expand Up @@ -338,17 +295,24 @@ impl<'a> hb_font_t<'a> {
}
}

pub(crate) fn layout_table(&self, table_index: TableIndex) -> Option<&LayoutTable<'a>> {
pub(crate) fn layout_table(
&self,
table_index: TableIndex,
) -> Option<fonta::ot::LayoutTable<'a>> {
match table_index {
TableIndex::GSUB => self.gsub.as_ref().map(|table| &table.inner),
TableIndex::GPOS => self.gpos.as_ref().map(|table| &table.inner),
TableIndex::GSUB => Some(fonta::ot::LayoutTable::Gsub(
self.font.ot.gsub.as_ref()?.table.clone(),
)),
TableIndex::GPOS => Some(fonta::ot::LayoutTable::Gpos(
self.font.ot.gpos.as_ref()?.table.clone(),
)),
}
}

pub(crate) fn layout_tables(
&self,
) -> impl Iterator<Item = (TableIndex, &LayoutTable<'a>)> + '_ {
TableIndex::iter().filter_map(move |idx| self.layout_table(idx).map(|table| (idx, table)))
) -> impl Iterator<Item = (TableIndex, fonta::ot::LayoutTable<'a>)> + '_ {
TableIndex::iter().filter_map(move |idx| Some((idx, self.layout_table(idx)?)))
}
}

Expand Down
12 changes: 5 additions & 7 deletions src/hb/fonta/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,12 @@ impl<'a> Font<'a> {
pub(crate) fn set_coords(&mut self, coords: &[NormalizedCoordinate]) {
self.coords.clear();
if !coords.is_empty() && !coords.iter().all(|coord| coord.get() == 0) {
self.coords.extend(
coords
.iter()
.map(|coord| NormalizedCoord::from_bits(coord.get())),
);
let ivs = self.ivs.take().or_else(|| self.ot.item_variation_store());
if ivs.is_some() {
self.coords.extend(
coords
.iter()
.map(|coord| NormalizedCoord::from_bits(coord.get())),
);
}
self.ivs = ivs;
} else {
self.ivs = None;
Expand Down
Loading

0 comments on commit 2fb01f7

Please sign in to comment.