Skip to content
Open
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
91 changes: 19 additions & 72 deletions src/hb/ot/contextual.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::{coverage_binary_cached, coverage_index, covered, glyph_class};
use super::{coverage_index, covered, glyph_class};
use crate::hb::buffer::GlyphInfo;
use crate::hb::ot::{ClassDefInfo, CoverageInfo};
use crate::hb::ot::ClassDefInfo;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{
apply_lookup, match_always, match_backtrack, match_glyph, match_input, match_lookahead,
may_skip_t, skipping_iterator_t, Apply, BinaryCache, ChainContextFormat2Cache,
may_skip_t, skipping_iterator_t, Apply, ApplyState, ChainContextFormat2Cache,
ContextFormat2Cache, SubtableExternalCache, SubtableExternalCacheMode, WouldApply,
WouldApplyContext,
};
Expand Down Expand Up @@ -47,9 +47,8 @@ impl WouldApply for SequenceContextFormat1<'_> {
}

impl Apply for SequenceContextFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage().ok()?.get(glyph)? as usize;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let index = state.first_coverage_index as usize;
let set = self.seq_rule_sets().get(index)?.ok()?;
apply_context_rules(ctx, &set.seq_rules(), match_glyph)
}
Expand Down Expand Up @@ -85,44 +84,24 @@ impl WouldApply for SequenceContextFormat2<'_> {
}

impl Apply for SequenceContextFormat2<'_> {
fn apply_with_external_cache(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let SubtableExternalCache::ContextFormat2Cache(cache) = external_cache else {
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let SubtableExternalCache::ContextFormat2Cache(cache) = state.external_cache else {
return None;
};
let offset_data = self.offset_data();
coverage_binary_cached(
|gid| cache.coverage.index(&offset_data, gid),
glyph,
&cache.coverage_cache,
)?;
let input_class = |gid| cache.input.class(&offset_data, gid);
let index = input_class(glyph) as usize;
let index = input_class(state.first_glyph) as usize;
let set = self.class_seq_rule_sets().get(index)?.ok()?;
apply_context_rules(ctx, &set.class_seq_rules(), |info, value| {
input_class(info.as_glyph()) == value
})
}

fn apply_cached(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let SubtableExternalCache::ContextFormat2Cache(cache) = external_cache else {
fn apply_cached(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let SubtableExternalCache::ContextFormat2Cache(cache) = state.external_cache else {
return None;
};
let offset_data = self.offset_data();
coverage_binary_cached(
|gid| cache.coverage.index(&offset_data, gid),
glyph,
&cache.coverage_cache,
)?;
let input_class = |gid| cache.input.class(&offset_data, gid);
let index = get_class_cached(&input_class, &mut ctx.buffer.info[ctx.buffer.idx]) as usize;
let set = self.class_seq_rule_sets().get(index)?.ok()?;
Expand All @@ -142,9 +121,6 @@ impl Apply for SequenceContextFormat2<'_> {
fn external_cache_create(&self, _mode: SubtableExternalCacheMode) -> SubtableExternalCache {
let data = self.offset_data();
SubtableExternalCache::ContextFormat2Cache(ContextFormat2Cache {
coverage_cache: BinaryCache::new(),
coverage: CoverageInfo::new(&data, self.coverage_offset().to_u32() as u16)
.unwrap_or_default(),
input: ClassDefInfo::new(&data, self.class_def_offset().to_u32() as u16)
.unwrap_or_default(),
})
Expand All @@ -163,10 +139,8 @@ impl WouldApply for SequenceContextFormat3<'_> {
}

impl Apply for SequenceContextFormat3<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
fn apply(&self, ctx: &mut hb_ot_apply_context_t, _state: &ApplyState) -> Option<()> {
let input_coverages = self.coverages();
input_coverages.get(0).ok()?.get(glyph)?;
let input = |info: &mut GlyphInfo, index: u16| {
input_coverages
.get(index as usize + 1)
Expand Down Expand Up @@ -230,9 +204,8 @@ impl WouldApply for ChainedSequenceContextFormat1<'_> {
}

impl Apply for ChainedSequenceContextFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage().ok()?.get(glyph)? as usize;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let index = state.first_coverage_index as usize;
let set = self.chained_seq_rule_sets().get(index)?.ok()?;
apply_chain_context_rules(
ctx,
Expand Down Expand Up @@ -344,22 +317,12 @@ fn match_class_cached2<'a>(
}

impl Apply for ChainedSequenceContextFormat2<'_> {
fn apply_with_external_cache(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let SubtableExternalCache::ChainContextFormat2Cache(cache) = external_cache else {
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let SubtableExternalCache::ChainContextFormat2Cache(cache) = state.external_cache else {
return None;
};
let offset_data = self.offset_data();
coverage_binary_cached(
|gid| cache.coverage.index(&offset_data, gid),
glyph,
&cache.coverage_cache,
)?;
let index = cache.input.class(&offset_data, glyph) as usize;
let index = cache.input.class(&offset_data, state.first_glyph) as usize;
let set = self.chained_class_seq_rule_sets().get(index)?.ok()?;
apply_chain_context_rules(
ctx,
Expand All @@ -371,21 +334,11 @@ impl Apply for ChainedSequenceContextFormat2<'_> {
),
)
}
fn apply_cached(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let SubtableExternalCache::ChainContextFormat2Cache(cache) = external_cache else {
fn apply_cached(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let SubtableExternalCache::ChainContextFormat2Cache(cache) = state.external_cache else {
return None;
};
let offset_data = self.offset_data();
coverage_binary_cached(
|gid| cache.coverage.index(&offset_data, gid),
glyph,
&cache.coverage_cache,
)?;
let input_class = |gid| cache.input.class(&offset_data, gid);
let lookahead_class = |gid| cache.lookahead.class(&offset_data, gid);
let index = get_class_cached2(&input_class, &mut ctx.buffer.info[ctx.buffer.idx]) as usize;
Expand Down Expand Up @@ -413,9 +366,6 @@ impl Apply for ChainedSequenceContextFormat2<'_> {
fn external_cache_create(&self, _mode: SubtableExternalCacheMode) -> SubtableExternalCache {
let data = self.offset_data();
SubtableExternalCache::ChainContextFormat2Cache(ChainContextFormat2Cache {
coverage_cache: BinaryCache::new(),
coverage: CoverageInfo::new(&data, self.coverage_offset().to_u32() as u16)
.unwrap_or_default(),
backtrack: ClassDefInfo::new(&data, self.backtrack_class_def_offset().to_u32() as u16)
.unwrap_or_default(),
input: ClassDefInfo::new(&data, self.input_class_def_offset().to_u32() as u16)
Expand Down Expand Up @@ -446,11 +396,8 @@ impl WouldApply for ChainedSequenceContextFormat3<'_> {
}

impl Apply for ChainedSequenceContextFormat3<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();

fn apply(&self, ctx: &mut hb_ot_apply_context_t, _state: &ApplyState) -> Option<()> {
let input_coverages = self.input_coverages();
input_coverages.get(0).ok()?.get(glyph)?;

let backtrack_coverages = self.backtrack_coverages();
let lookahead_coverages = self.lookahead_coverages();
Expand Down
11 changes: 4 additions & 7 deletions src/hb/ot/gpos/cursive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ use crate::hb::buffer::HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
use crate::hb::ot_layout_common::lookup_flags;
use crate::hb::ot_layout_gpos_table::attach_type;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{skipping_iterator_t, Apply};
use crate::hb::ot_layout_gsubgpos::{skipping_iterator_t, Apply, ApplyState};
use crate::{Direction, GlyphPosition};
use read_fonts::tables::gpos::CursivePosFormat1;

impl Apply for CursivePosFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let this = ctx.buffer.cur(0).as_glyph();

let coverage = self.coverage().ok()?;
let index_this = coverage.get(this)? as usize;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let index_this = state.first_coverage_index as usize;
let records = self.entry_exit_record();
let offset_data = self.offset_data();
let entry_this = records.get(index_this)?.entry_anchor(offset_data)?.ok()?;
Expand All @@ -28,7 +25,7 @@ impl Apply for CursivePosFormat1<'_> {

let i = iter.index();
let prev = iter.buffer.info[i].as_glyph();
let index_prev = coverage.get(prev)? as usize;
let index_prev = state.coverage.index(&self.offset_data(), prev)? as usize;
let Some(exit_prev) = records
.get(index_prev)
.and_then(|rec| rec.exit_anchor(offset_data).transpose().ok().flatten())
Expand Down
17 changes: 7 additions & 10 deletions src/hb/ot/gpos/mark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::hb::buffer::{hb_buffer_t, HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT}
use crate::hb::ot_layout_common::lookup_flags;
use crate::hb::ot_layout_gpos_table::attach_type;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{match_t, skipping_iterator_t, Apply, MatchSource};
use crate::hb::ot_layout_gsubgpos::{match_t, skipping_iterator_t, Apply, ApplyState, MatchSource};
use read_fonts::tables::gpos::{
AnchorTable, MarkArray, MarkBasePosFormat1, MarkLigPosFormat1, MarkMarkPosFormat1,
};
Expand Down Expand Up @@ -49,9 +49,8 @@ impl MarkArrayExt for MarkArray<'_> {
}

impl Apply for MarkBasePosFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let mark_glyph = ctx.buffer.cur(0).as_glyph();
let mark_index = self.mark_coverage().ok()?.get(mark_glyph)?;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let mark_index = state.first_coverage_index;

let base_coverage = self.base_coverage().ok()?;
let last_base_until = ctx.last_base_until;
Expand Down Expand Up @@ -142,9 +141,8 @@ fn accept(buffer: &hb_buffer_t, idx: usize) -> bool {
}

impl Apply for MarkMarkPosFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let mark1_glyph = ctx.buffer.cur(0).as_glyph();
let mark1_index = self.mark1_coverage().ok()?.get(mark1_glyph)?;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let mark1_index = state.first_coverage_index;
let lookup_props = ctx.lookup_props;
// Now we search backwards for a suitable mark glyph until a non-mark glyph
let mut iter = skipping_iterator_t::new(ctx, false);
Expand Down Expand Up @@ -205,9 +203,8 @@ impl Apply for MarkMarkPosFormat1<'_> {
}

impl Apply for MarkLigPosFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let mark_glyph = ctx.buffer.cur(0).as_glyph();
let mark_index = self.mark_coverage().ok()?.get(mark_glyph)? as usize;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let mark_index = state.first_coverage_index as usize;

// Due to borrowing rules, we have this piece of code before creating the
// iterator, unlike in harfbuzz.
Expand Down
71 changes: 9 additions & 62 deletions src/hb/ot/gpos/pair.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
use crate::hb::ot::{coverage_index, coverage_index_cached, ClassDefInfo, CoverageInfo};
use crate::hb::ot::ClassDefInfo;
use crate::hb::ot::{glyph_class, glyph_class_cached};
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{
skipping_iterator_t, Apply, PairPosFormat1Cache, PairPosFormat1SmallCache, PairPosFormat2Cache,
PairPosFormat2SmallCache, SubtableExternalCache, SubtableExternalCacheMode,
skipping_iterator_t, Apply, ApplyState, PairPosFormat2Cache, PairPosFormat2SmallCache,
SubtableExternalCache, SubtableExternalCacheMode,
};
use alloc::boxed::Box;
use read_fonts::tables::gpos::{PairPosFormat1, PairPosFormat2};

impl Apply for PairPosFormat1<'_> {
fn apply_with_external_cache(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let first_glyph = ctx.buffer.cur(0).as_glyph();

let first_glyph_coverage_index = match external_cache {
SubtableExternalCache::PairPosFormat1Cache(cache) => coverage_index_cached(
|gid| self.coverage().ok()?.get(gid),
first_glyph,
&cache.coverage,
)?,
SubtableExternalCache::PairPosFormat1SmallCache(cache) => {
cache.coverage.index(&self.offset_data(), first_glyph)?
}
_ => coverage_index(self.coverage(), first_glyph)?,
};
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let first_glyph_coverage_index = state.first_coverage_index;

let mut iter = skipping_iterator_t::new(ctx, false);
iter.reset(iter.buffer.idx);
Expand Down Expand Up @@ -120,46 +104,11 @@ impl Apply for PairPosFormat1<'_> {
}
None
}

fn external_cache_create(&self, mode: SubtableExternalCacheMode) -> SubtableExternalCache {
match mode {
SubtableExternalCacheMode::Full => {
SubtableExternalCache::PairPosFormat1Cache(Box::new(PairPosFormat1Cache::new()))
}
SubtableExternalCacheMode::Small => {
if let Some(coverage) =
CoverageInfo::new(&self.offset_data(), self.coverage_offset().to_u32() as u16)
{
SubtableExternalCache::PairPosFormat1SmallCache(PairPosFormat1SmallCache {
coverage,
})
} else {
SubtableExternalCache::None
}
}
SubtableExternalCacheMode::None => SubtableExternalCache::None,
}
}
}

impl Apply for PairPosFormat2<'_> {
fn apply_with_external_cache(
&self,
ctx: &mut hb_ot_apply_context_t,
external_cache: &SubtableExternalCache,
) -> Option<()> {
let first_glyph = ctx.buffer.cur(0).as_glyph();
match external_cache {
SubtableExternalCache::PairPosFormat2Cache(cache) => coverage_index_cached(
|gid| self.coverage().ok()?.get(gid),
first_glyph,
&cache.coverage,
)?,
SubtableExternalCache::PairPosFormat2SmallCache(cache) => {
cache.coverage.index(&self.offset_data(), first_glyph)?
}
_ => coverage_index(self.coverage(), first_glyph)?,
};
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let first_glyph = state.first_glyph;
let mut iter = skipping_iterator_t::new(ctx, false);
iter.reset(iter.buffer.idx);

Expand Down Expand Up @@ -204,7 +153,7 @@ impl Apply for PairPosFormat2<'_> {
}
};
let data = self.offset_data();
let (class1, class2) = match external_cache {
let (class1, class2) = match state.external_cache {
SubtableExternalCache::PairPosFormat2Cache(cache) => (
glyph_class_cached(
|gid| glyph_class(self.class_def1(), gid),
Expand Down Expand Up @@ -256,12 +205,10 @@ impl Apply for PairPosFormat2<'_> {
}
SubtableExternalCacheMode::Small => {
let data = self.offset_data();
let coverage = CoverageInfo::new(&data, self.coverage_offset().to_u32() as u16);
let class1 = ClassDefInfo::new(&data, self.class_def1_offset().to_u32() as u16);
let class2 = ClassDefInfo::new(&data, self.class_def2_offset().to_u32() as u16);
if let Some((coverage, (first, second))) = coverage.zip(class1.zip(class2)) {
if let Some((first, second)) = class1.zip(class2) {
SubtableExternalCache::PairPosFormat2SmallCache(PairPosFormat2SmallCache {
coverage,
first,
second,
})
Expand Down
11 changes: 4 additions & 7 deletions src/hb/ot/gpos/single.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use crate::hb::ot_layout_gsubgpos::Apply;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, ApplyState};
use read_fonts::tables::gpos::{SinglePosFormat1, SinglePosFormat2};

impl Apply for SinglePosFormat1<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
self.coverage().ok()?.get(glyph)?;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, _state: &ApplyState) -> Option<()> {
let format = self.value_format();
let offset = self.shape().value_record_byte_range().start;
super::apply_value(ctx, ctx.buffer.idx, &self.offset_data(), offset, format);
Expand All @@ -15,9 +13,8 @@ impl Apply for SinglePosFormat1<'_> {
}

impl Apply for SinglePosFormat2<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage().ok()?.get(glyph)? as usize;
fn apply(&self, ctx: &mut hb_ot_apply_context_t, state: &ApplyState) -> Option<()> {
let index = state.first_coverage_index as usize;
let format = self.value_format();
let offset =
self.shape().value_records_byte_range().start + (format.record_byte_len() * index);
Expand Down
Loading