Skip to content

Commit

Permalink
Merge pull request #101 from Pi-Cla/4.2.1
Browse files Browse the repository at this point in the history
Finish syncing to 4.2.1
  • Loading branch information
RazrFalcon authored Apr 13, 2024
2 parents 332d5d4 + 28b2d6c commit 6781f6f
Show file tree
Hide file tree
Showing 29 changed files with 659 additions and 381 deletions.
4 changes: 2 additions & 2 deletions src/hb/aat_layout_morx_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ pub fn apply(plan: &hb_ot_shape_plan_t, face: &hb_font_t, buffer: &mut hb_buffer
};

if reverse {
_hb_ot_layout_reverse_graphemes(buffer);
buffer.reverse();
}

apply_subtable(&subtable.kind, buffer, face);

if reverse {
_hb_ot_layout_reverse_graphemes(buffer);
buffer.reverse();
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/hb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod face;
mod glyph_set;
mod kerning;
mod machine_cursor;
mod ot;
mod ot_layout;
mod ot_layout_common;
mod ot_layout_gpos_table;
Expand Down
33 changes: 33 additions & 0 deletions src/hb/ot/layout/GSUB/alternate_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::hb::ot_layout_gsubgpos::Apply;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_map::hb_ot_map_t;
use std::convert::TryFrom;
use ttf_parser::gsub::AlternateSet;

impl Apply for AlternateSet<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let len = self.alternates.len();
if len == 0 {
return None;
}

let glyph_mask = ctx.buffer.cur(0).mask;

// Note: This breaks badly if two features enabled this lookup together.
let shift = ctx.lookup_mask.trailing_zeros();
let mut alt_index = (ctx.lookup_mask & glyph_mask) >> shift;

// If alt_index is MAX_VALUE, randomize feature if it is the rand feature.
if alt_index == hb_ot_map_t::MAX_VALUE && ctx.random {
// Maybe we can do better than unsafe-to-break all; but since we are
// changing random state, it would be hard to track that. Good 'nough.
ctx.buffer.unsafe_to_break(Some(0), Some(ctx.buffer.len));
alt_index = ctx.random_number() % u32::from(len) + 1;
}

let idx = u16::try_from(alt_index).ok()?.checked_sub(1)?;
ctx.replace_glyph(self.alternates.get(idx)?);

Some(())
}
}
20 changes: 20 additions & 0 deletions src/hb/ot/layout/GSUB/alternate_subst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
use ttf_parser::gsub::AlternateSubstitution;

// AlternateSubstFormat1::would_apply
impl WouldApply for AlternateSubstitution<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
ctx.glyphs.len() == 1 && self.coverage.get(ctx.glyphs[0]).is_some()
}
}

// AlternateSubstFormat1::apply
impl Apply for AlternateSubstitution<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage.get(glyph)?;
let set = self.alternate_sets.get(index)?;
set.apply(ctx)
}
}
62 changes: 62 additions & 0 deletions src/hb/ot/layout/GSUB/ligature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::hb::ot_layout::MAX_CONTEXT_LENGTH;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{
ligate_input, match_glyph, match_input, Apply, WouldApply, WouldApplyContext,
};
use ttf_parser::gsub::Ligature;

impl WouldApply for Ligature<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
ctx.glyphs.len() == usize::from(self.components.len()) + 1
&& self
.components
.into_iter()
.enumerate()
.all(|(i, comp)| ctx.glyphs[i + 1] == comp)
}
}

impl Apply for Ligature<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
// Special-case to make it in-place and not consider this
// as a "ligated" substitution.
if self.components.is_empty() {
ctx.replace_glyph(self.glyph);
Some(())
} else {
let f = |glyph, num_items| {
let index = self.components.len() - num_items;
let value = self.components.get(index).unwrap();
match_glyph(glyph, value.0)
};

let mut match_end = 0;
let mut match_positions = [0; MAX_CONTEXT_LENGTH];
let mut total_component_count = 0;

if !match_input(
ctx,
self.components.len(),
&f,
&mut match_end,
&mut match_positions,
Some(&mut total_component_count),
) {
ctx.buffer
.unsafe_to_concat(Some(ctx.buffer.idx), Some(match_end));
return None;
}

let count = usize::from(self.components.len()) + 1;
ligate_input(
ctx,
count,
&match_positions,
match_end,
total_component_count,
self.glyph,
);
return Some(());
}
}
}
20 changes: 20 additions & 0 deletions src/hb/ot/layout/GSUB/ligature_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
use ttf_parser::gsub::LigatureSet;

impl WouldApply for LigatureSet<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
self.into_iter().any(|lig| lig.would_apply(ctx))
}
}

impl Apply for LigatureSet<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
for lig in self.into_iter() {
if lig.apply(ctx).is_some() {
return Some(());
}
}
None
}
}
24 changes: 24 additions & 0 deletions src/hb/ot/layout/GSUB/ligature_subst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
use ttf_parser::gsub::LigatureSubstitution;

// LigatureSubstFormat1::would_apply
impl WouldApply for LigatureSubstitution<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
self.coverage
.get(ctx.glyphs[0])
.and_then(|index| self.ligature_sets.get(index))
.map_or(false, |set| set.would_apply(ctx))
}
}

// LigatureSubstFormat1::apply
impl Apply for LigatureSubstitution<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
self.coverage
.get(glyph)
.and_then(|index| self.ligature_sets.get(index))
.and_then(|set| set.apply(ctx))
}
}
9 changes: 9 additions & 0 deletions src/hb/ot/layout/GSUB/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod alternate_set;
mod alternate_subst;
mod ligature;
mod ligature_set;
mod ligature_subst;
mod multi_subst;
mod reverse_chain_single_subst;
mod sequence;
mod single_subst;
20 changes: 20 additions & 0 deletions src/hb/ot/layout/GSUB/multi_subst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
use ttf_parser::gsub::MultipleSubstitution;

// MultipleSubstFormat1::would_apply
impl WouldApply for MultipleSubstitution<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
ctx.glyphs.len() == 1 && self.coverage.get(ctx.glyphs[0]).is_some()
}
}

// MultipleSubstFormat1::apply
impl Apply for MultipleSubstitution<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage.get(glyph)?;
let seq = self.sequences.get(index)?;
seq.apply(ctx)
}
}
69 changes: 69 additions & 0 deletions src/hb/ot/layout/GSUB/reverse_chain_single_subst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::hb::ot_layout::MAX_NESTING_LEVEL;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{
match_backtrack, match_lookahead, Apply, WouldApply, WouldApplyContext,
};
use ttf_parser::gsub::ReverseChainSingleSubstitution;

// ReverseChainSingleSubstFormat1::would_apply
impl WouldApply for ReverseChainSingleSubstitution<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
ctx.glyphs.len() == 1 && self.coverage.get(ctx.glyphs[0]).is_some()
}
}

// ReverseChainSingleSubstFormat1::apply
impl Apply for ReverseChainSingleSubstitution<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
// No chaining to this type.
if ctx.nesting_level_left != MAX_NESTING_LEVEL {
return None;
}

let glyph = ctx.buffer.cur(0).as_glyph();
let index = self.coverage.get(glyph)?;
if index >= self.substitutes.len() {
return None;
}

let subst = self.substitutes.get(index)?;

let f1 = |glyph, num_items| {
let index = self.backtrack_coverages.len() - num_items;
let value = self.backtrack_coverages.get(index).unwrap();
value.contains(glyph)
};

let f2 = |glyph, num_items| {
let index = self.lookahead_coverages.len() - num_items;
let value = self.lookahead_coverages.get(index).unwrap();
value.contains(glyph)
};

let mut start_index = 0;
let mut end_index = 0;

if match_backtrack(ctx, self.backtrack_coverages.len(), &f1, &mut start_index) {
if match_lookahead(
ctx,
self.lookahead_coverages.len(),
&f2,
ctx.buffer.idx + 1,
&mut end_index,
) {
ctx.buffer
.unsafe_to_break_from_outbuffer(Some(start_index), Some(end_index));
ctx.replace_glyph_inplace(subst);

// Note: We DON'T decrease buffer.idx. The main loop does it
// for us. This is useful for preventing surprises if someone
// calls us through a Context lookup.
return Some(());
}
}

ctx.buffer
.unsafe_to_concat_from_outbuffer(Some(start_index), Some(end_index));
return None;
}
}
44 changes: 44 additions & 0 deletions src/hb/ot/layout/GSUB/sequence.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::hb::buffer::GlyphPropsFlags;
use crate::hb::ot_layout::{
_hb_glyph_info_get_lig_id, _hb_glyph_info_is_ligature,
_hb_glyph_info_set_lig_props_for_component,
};
use crate::hb::ot_layout_gsubgpos::Apply;
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use ttf_parser::gsub::Sequence;

impl Apply for Sequence<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
match self.substitutes.len() {
// Spec disallows this, but Uniscribe allows it.
// https://github.com/harfbuzz/harfbuzz/issues/253
0 => ctx.buffer.delete_glyph(),

// Special-case to make it in-place and not consider this
// as a "multiplied" substitution.
1 => ctx.replace_glyph(self.substitutes.get(0)?),

_ => {
let class = if _hb_glyph_info_is_ligature(ctx.buffer.cur(0)) {
GlyphPropsFlags::BASE_GLYPH
} else {
GlyphPropsFlags::empty()
};
let lig_id = _hb_glyph_info_get_lig_id(ctx.buffer.cur(0));

for (i, subst) in self.substitutes.into_iter().enumerate() {
// If is attached to a ligature, don't disturb that.
// https://github.com/harfbuzz/harfbuzz/issues/3069
if lig_id == 0 {
// Index is truncated to 4 bits anway, so we can safely cast to u8.
_hb_glyph_info_set_lig_props_for_component(ctx.buffer.cur_mut(0), i as u8);
}
ctx.output_glyph_for_component(subst, class);
}

ctx.buffer.skip_glyph();
}
}
Some(())
}
}
38 changes: 38 additions & 0 deletions src/hb/ot/layout/GSUB/single_subst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
use ttf_parser::gsub::SingleSubstitution;
use ttf_parser::GlyphId;

// SingleSubstFormat1::would_apply
// SingleSubstFormat2::would_apply
impl WouldApply for SingleSubstitution<'_> {
fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
ctx.glyphs.len() == 1 && self.coverage().get(ctx.glyphs[0]).is_some()
}
}

// SingleSubstFormat1::apply
// SingleSubstFormat2::apply
impl Apply for SingleSubstitution<'_> {
fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
let glyph = ctx.buffer.cur(0).as_glyph();
let subst = match *self {
Self::Format1 { coverage, delta } => {
coverage.get(glyph)?;
// According to the Adobe Annotated OpenType Suite, result is always
// limited to 16bit, so we explicitly want to truncate.
GlyphId((i32::from(glyph.0) + i32::from(delta)) as u16)
}
Self::Format2 {
coverage,
substitutes,
} => {
let index = coverage.get(glyph)?;
substitutes.get(index)?
}
};

ctx.replace_glyph(subst);
Some(())
}
}
Loading

0 comments on commit 6781f6f

Please sign in to comment.