Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions benches/shaping.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion};
use harfrust::TableProvider;
use std::path::Path;

const BENCHES: &[(&str, &str)] = &[
Expand Down Expand Up @@ -38,9 +39,10 @@ struct ShapePlanCache {
}

impl ShapePlanCache {
fn get(
fn get<'a>(
&mut self,
shaper: &harfrust::Shaper,
shaper: &'a harfrust::Shaper,
font: &impl TableProvider<'a>,
buffer: &harfrust::UnicodeBuffer,
) -> &harfrust::ShapePlan {
let key = harfrust::ShapePlanKey::new(Some(buffer.script()), buffer.direction());
Expand All @@ -49,6 +51,7 @@ impl ShapePlanCache {
} else {
self.plans.push(harfrust::ShapePlan::new(
shaper,
font,
buffer.direction(),
Some(buffer.script()),
None,
Expand Down Expand Up @@ -86,7 +89,7 @@ fn bench(c: &mut Criterion) {
let mut buffer = shared_buffer.take().unwrap();
buffer.push_str(line);
buffer.guess_segment_properties();
let plan = plan_cache.get(&shaper, &buffer);
let plan = plan_cache.get(&shaper, &font, &buffer);
shared_buffer = Some(shaper.shape_with_plan(plan, buffer, &[]).clear());
}
});
Expand Down Expand Up @@ -121,25 +124,20 @@ criterion_group! {
criterion_main!(benches);

struct HrTestState<'a> {
font: &'a harfrust::FontRef<'a>,
data: harfrust::ShaperData,
data: harfrust::ShaperData<'a>,
_instance: Option<harfrust::ShaperInstance>,
}

impl<'a> HrTestState<'a> {
fn new(font: &'a harfrust::FontRef<'a>) -> Self {
let data = harfrust::ShaperData::new(font);
Self {
font,
data,
_instance: None,
}
}

fn shaper(&self) -> harfrust::Shaper<'_> {
self.data
.shaper(self.font)
.instance(self._instance.as_ref())
.build()
self.data.shaper().instance(self._instance.as_ref()).build()
}
}
6 changes: 3 additions & 3 deletions examples/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fn main() {
let data = ShaperData::new(&font);
let instance = ShaperInstance::from_variations(&font, &args.variations);
let shaper = data
.shaper(&font)
.shaper()
.instance(Some(&instance))
.point_size(args.font_ptem)
.build();
Expand Down Expand Up @@ -207,7 +207,7 @@ fn main() {

buffer.guess_segment_properties();

let glyph_buffer = shaper.shape(buffer, &args.features);
let glyph_buffer = shaper.shape(&font, buffer, &args.features);

let mut format_flags = harfrust::SerializeFlags::default();
if args.no_glyph_names {
Expand All @@ -234,7 +234,7 @@ fn main() {
format_flags |= harfrust::SerializeFlags::GLYPH_FLAGS;
}

println!("{}", glyph_buffer.serialize(&shaper, format_flags));
println!("{}", glyph_buffer.serialize(&shaper, &font, format_flags));
}
}

Expand Down
18 changes: 9 additions & 9 deletions src/hb/aat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::hb::tables::TableRanges;
use alloc::vec::Vec;
use read_fonts::{
tables::{ankr::Ankr, feat::Feat, kern::Kern, kerx::Kerx, morx::Morx, trak::Trak},
FontRef, TableProvider,
TableProvider,
};

#[derive(Default)]
Expand All @@ -24,7 +24,7 @@ pub struct AatCache {

impl AatCache {
#[allow(unused)]
pub fn new(font: &FontRef) -> Self {
pub fn new<'a>(font: &impl TableProvider<'a>) -> Self {
let mut cache = Self::default();
let num_glyphs = font
.maxp()
Expand Down Expand Up @@ -81,22 +81,22 @@ pub struct AatTables<'a> {
}

impl<'a> AatTables<'a> {
pub fn new(font: &FontRef<'a>, cache: &'a AatCache, table_ranges: &TableRanges) -> Self {
pub fn new(cache: &'a AatCache, table_ranges: &TableRanges<'a>) -> Self {
let morx = table_ranges
.morx
.resolve_table(font)
.resolve_table()
.map(|table| (table, cache.morx.as_slice()));
let ankr = table_ranges.ankr.resolve_table(font);
let ankr = table_ranges.ankr.resolve_table();
let kern = table_ranges
.kern
.resolve_table(font)
.resolve_table()
.map(|table| (table, cache.kern.as_slice()));
let kerx = table_ranges
.kerx
.resolve_table(font)
.resolve_table()
.map(|table| (table, cache.kerx.as_slice()));
let trak = table_ranges.trak.resolve_table(font);
let feat = table_ranges.feat.resolve_table(font);
let trak = table_ranges.trak.resolve_table();
let feat = table_ranges.feat.resolve_table();
Self {
morx,
ankr,
Expand Down
17 changes: 12 additions & 5 deletions src/hb/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use alloc::{string::String, vec::Vec};
use core::cmp::min;
use core::convert::TryFrom;
use read_fonts::types::{GlyphId, GlyphId16};
use read_fonts::TableProvider;

use super::buffer::glyph_flag::{SAFE_TO_INSERT_TATWEEL, UNSAFE_TO_BREAK, UNSAFE_TO_CONCAT};
use super::face::hb_glyph_extents_t;
Expand Down Expand Up @@ -1912,13 +1913,19 @@ impl GlyphBuffer {
}

/// Converts the glyph buffer content into a string.
pub fn serialize(&self, face: &crate::Shaper, flags: SerializeFlags) -> String {
self.serialize_impl(face, flags).unwrap_or_default()
pub fn serialize<'t>(
&self,
face: &crate::Shaper<'t>,
font: &impl TableProvider<'t>,
flags: SerializeFlags,
) -> String {
self.serialize_impl(face, font, flags).unwrap_or_default()
}

fn serialize_impl(
fn serialize_impl<'t>(
&self,
face: &hb_font_t,
face: &hb_font_t<'t>,
font: &impl TableProvider<'t>,
flags: SerializeFlags,
) -> Result<String, core::fmt::Error> {
use core::fmt::Write;
Expand All @@ -1929,7 +1936,7 @@ impl GlyphBuffer {
let pos = self.glyph_positions();
let mut x = 0;
let mut y = 0;
let names = face.glyph_names();
let names = hb_font_t::glyph_names(font);
for (info, pos) in info.iter().zip(pos) {
s.push(if s.is_empty() { '[' } else { '|' });

Expand Down
5 changes: 2 additions & 3 deletions src/hb/charmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use super::cache::hb_cache_t;
use read_fonts::{
tables::cmap::{Cmap, Cmap14, CmapSubtable, MapVariant},
types::GlyphId,
FontRef,
};

pub type cache_t = hb_cache_t<21, 19, 256, 32>;
Expand All @@ -17,8 +16,8 @@ pub struct Charmap<'a> {
}

impl<'a> Charmap<'a> {
pub fn new(font: &FontRef<'a>, table_ranges: &TableRanges, cache: &'a cache_t) -> Self {
if let Some(cmap) = table_ranges.cmap.resolve_table::<Cmap>(font) {
pub fn new(table_ranges: &TableRanges<'a>, cache: &'a cache_t) -> Self {
if let Some(cmap) = table_ranges.cmap.resolve_table::<Cmap>() {
let data = cmap.offset_data();
let records = cmap.encoding_records();
let subtable = table_ranges
Expand Down
59 changes: 33 additions & 26 deletions src/hb/face.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use read_fonts::types::{F2Dot14, Fixed, GlyphId};
use read_fonts::{FontRef, TableProvider};
use read_fonts::TableProvider;
use smallvec::SmallVec;

use super::aat::AatTables;
Expand All @@ -15,16 +15,16 @@ use crate::hb::tables::TableRanges;
use crate::{script, Feature, GlyphBuffer, NormalizedCoord, ShapePlan, UnicodeBuffer, Variation};

/// Data required for shaping with a single font.
pub struct ShaperData {
table_ranges: TableRanges,
pub struct ShaperData<'a> {
table_ranges: TableRanges<'a>,
ot_cache: OtCache,
aat_cache: AatCache,
cmap_cache: cmap_cache_t,
}

impl ShaperData {
impl<'a> ShaperData<'a> {
/// Creates new cached shaper data for the given font.
pub fn new(font: &FontRef) -> Self {
pub fn new<Font: TableProvider<'a>>(font: &Font) -> Self {
let ot_cache = OtCache::new(font);
let aat_cache = AatCache::new(font);
let table_ranges = TableRanges::new(font);
Expand All @@ -39,10 +39,9 @@ impl ShaperData {

/// Returns a builder for constructing a new shaper with the given
/// font.
pub fn shaper<'a>(&'a self, font: &FontRef<'a>) -> ShaperBuilder<'a> {
pub fn shaper(&'a self) -> ShaperBuilder<'a> {
ShaperBuilder {
data: self,
font: font.clone(),
instance: None,
point_size: None,
}
Expand All @@ -68,7 +67,7 @@ impl ShaperInstance {
/// list of variation settings.
///
/// The setting values are in user space and the order is insignificant.
pub fn from_variations<V>(font: &FontRef, variations: V) -> Self
pub fn from_variations<'a, V>(font: &impl TableProvider<'a>, variations: V) -> Self
where
V: IntoIterator,
V::Item: Into<Variation>,
Expand All @@ -82,15 +81,18 @@ impl ShaperInstance {
/// set of normalized coordinates.
///
/// The sequence of coordinates is expected to be in axis order.
pub fn from_coords(font: &FontRef, coords: impl IntoIterator<Item = NormalizedCoord>) -> Self {
pub fn from_coords<'a>(
font: &impl TableProvider<'a>,
coords: impl IntoIterator<Item = NormalizedCoord>,
) -> Self {
let mut this = Self::default();
this.set_coords(font, coords);
this
}

/// Creates a new shaper instance for the given font using the variation
/// position from the named instance at the specified index.
pub fn from_named_instance(font: &FontRef, index: usize) -> Self {
pub fn from_named_instance<'a>(font: &impl TableProvider<'a>, index: usize) -> Self {
let mut this = Self::default();
this.set_named_instance(font, index);
this
Expand All @@ -102,7 +104,7 @@ impl ShaperInstance {
}

/// Resets the instance for the given font and variation settings.
pub fn set_variations<V>(&mut self, font: &FontRef, variations: V)
pub fn set_variations<'a, V>(&mut self, font: &impl TableProvider<'a>, variations: V)
where
V: IntoIterator,
V::Item: Into<Variation>,
Expand All @@ -125,7 +127,11 @@ impl ShaperInstance {
}

/// Resets the instance for the given font and normalized coordinates.
pub fn set_coords(&mut self, font: &FontRef, coords: impl IntoIterator<Item = F2Dot14>) {
pub fn set_coords<'a>(
&mut self,
font: &impl TableProvider<'a>,
coords: impl IntoIterator<Item = F2Dot14>,
) {
self.coords.clear();
if let Ok(fvar) = font.fvar() {
let count = fvar.axis_count() as usize;
Expand All @@ -138,7 +144,7 @@ impl ShaperInstance {

/// Resets the instance for the given font using the variation
/// position from the named instance at the specified index.
pub fn set_named_instance(&mut self, font: &FontRef, index: usize) {
pub fn set_named_instance<'a>(&mut self, font: &impl TableProvider<'a>, index: usize) {
self.coords.clear();
if let Ok(fvar) = font.fvar() {
if let Ok((axes, instance)) = fvar
Expand All @@ -155,7 +161,7 @@ impl ShaperInstance {
}
}

fn set_feature_variations(&mut self, font: &FontRef) {
fn set_feature_variations<'a>(&mut self, font: &impl TableProvider<'a>) {
self.feature_variations = [None; 2];
if self.coords.is_empty() {
return;
Expand All @@ -179,8 +185,7 @@ impl ShaperInstance {

/// Builder type for constructing a [`Shaper`](crate::Shaper).
pub struct ShaperBuilder<'a> {
data: &'a ShaperData,
font: FontRef<'a>,
data: &'a ShaperData<'a>,
instance: Option<&'a ShaperInstance>,
point_size: Option<f32>,
}
Expand All @@ -204,24 +209,21 @@ impl<'a> ShaperBuilder<'a> {

/// Builds the shaper with the current configuration.
pub fn build(self) -> crate::Shaper<'a> {
let font = self.font;
let units_per_em = self.data.table_ranges.units_per_em;
let charmap = Charmap::new(&font, &self.data.table_ranges, &self.data.cmap_cache);
let glyph_metrics = GlyphMetrics::new(&font, &self.data.table_ranges);
let charmap = Charmap::new(&self.data.table_ranges, &self.data.cmap_cache);
let glyph_metrics = GlyphMetrics::new(&self.data.table_ranges);
let (coords, feature_variations) = self
.instance
.map(|instance| (instance.coords(), instance.feature_variations))
.unwrap_or_default();
let ot_tables = OtTables::new(
&font,
&self.data.ot_cache,
&self.data.table_ranges,
coords,
feature_variations,
);
let aat_tables = AatTables::new(&font, &self.data.aat_cache, &self.data.table_ranges);
let aat_tables = AatTables::new(&self.data.aat_cache, &self.data.table_ranges);
hb_font_t {
font,
units_per_em,
points_per_em: self.point_size,
charmap,
Expand All @@ -235,7 +237,6 @@ impl<'a> ShaperBuilder<'a> {
/// A configured shaper.
#[derive(Clone)]
pub struct hb_font_t<'a> {
pub(crate) font: FontRef<'a>,
pub(crate) units_per_em: u16,
pub(crate) points_per_em: Option<f32>,
charmap: Charmap<'a>,
Expand Down Expand Up @@ -264,9 +265,15 @@ impl<'a> crate::Shaper<'a> {
/// If you plan to shape multiple strings, prefer [`shape_with_plan`](Self::shape_with_plan).
/// This is because [`ShapePlan`](crate::ShapePlan) initialization is pretty slow and should preferably
/// be called once for each shaping configuration.
pub fn shape(&self, buffer: UnicodeBuffer, features: &[Feature]) -> GlyphBuffer {
pub fn shape<'s>(
&'s self,
font: &impl TableProvider<'s>,
buffer: UnicodeBuffer,
features: &[Feature],
) -> GlyphBuffer {
let plan = ShapePlan::new(
self,
font,
buffer.0.direction,
buffer.0.script,
buffer.0.language.as_ref(),
Expand Down Expand Up @@ -381,8 +388,8 @@ impl<'a> crate::Shaper<'a> {
}
}

pub(crate) fn glyph_names(&self) -> GlyphNames<'a> {
GlyphNames::new(&self.font)
pub(crate) fn glyph_names(font: &impl TableProvider<'a>) -> GlyphNames<'a> {
GlyphNames::new(font)
}

pub(crate) fn layout_table(&self, table_index: TableIndex) -> Option<LayoutTable<'a>> {
Expand Down
Loading