Skip to content

Commit 40b07af

Browse files
qxliu76garretrieger
authored andcommitted
[glyph closure] reduce allocations for (Chain)ContextFormat2
don't collect retained classes set into a set
1 parent 3dfbae6 commit 40b07af

2 files changed

Lines changed: 105 additions & 69 deletions

File tree

read-fonts/src/tables/gsub/closure.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -840,37 +840,32 @@ impl GlyphClosure for ContextFormat2<'_> {
840840
let Some(coverage) = self.coverage().transpose()? else {
841841
return Ok(());
842842
};
843-
let cov_active_glyphs = coverage.intersect_set(ctx.parent_active_glyphs());
844-
if cov_active_glyphs.is_empty() {
845-
return Ok(());
846-
}
847843

848844
let Some(input_class_def) = self.input_class_def().transpose()? else {
849845
return Ok(());
850846
};
851-
let coverage_glyph_classes = input_class_def.intersect_classes(&cov_active_glyphs);
852-
if coverage_glyph_classes.is_empty() {
847+
848+
if !coverage.intersects(ctx.parent_active_glyphs()) {
853849
return Ok(());
854850
}
855-
856-
let input_glyph_classes = input_class_def.intersect_classes(ctx.glyphs());
857-
let backtrack_classes = match self {
858-
Self::Plain(_) => IntSet::empty(),
851+
let cov_active_glyphs = coverage.intersect_set(ctx.parent_active_glyphs());
852+
let backtrack_class_def = match self {
853+
Self::Plain(_) => None,
859854
Self::Chain(table) => {
860855
if table.backtrack_class_def_offset().is_null() {
861-
IntSet::empty()
856+
None
862857
} else {
863-
table.backtrack_class_def()?.intersect_classes(ctx.glyphs())
858+
Some(table.backtrack_class_def()?)
864859
}
865860
}
866861
};
867-
let lookahead_classes = match self {
868-
Self::Plain(_) => IntSet::empty(),
862+
let lookahead_class_def = match self {
863+
Self::Plain(_) => None,
869864
Self::Chain(table) => {
870865
if table.lookahead_class_def_offset().is_null() {
871-
IntSet::empty()
866+
None
872867
} else {
873-
table.lookahead_class_def()?.intersect_classes(ctx.glyphs())
868+
Some(table.lookahead_class_def()?)
874869
}
875870
}
876871
};
@@ -880,7 +875,9 @@ impl GlyphClosure for ContextFormat2<'_> {
880875
.rule_sets()
881876
.enumerate()
882877
.filter_map(|(class, rs)| rs.map(|rs| (class as u16, rs)))
883-
.filter(|&(class, _)| coverage_glyph_classes.contains(class))
878+
.filter(|&(class, _)| {
879+
input_class_def.intersects_class_glyphs(&cov_active_glyphs, class)
880+
})
884881
{
885882
if ctx.lookup_limit_exceed() {
886883
return Ok(());
@@ -893,7 +890,12 @@ impl GlyphClosure for ContextFormat2<'_> {
893890
let Some(rule) = rule.transpose()? else {
894891
continue;
895892
};
896-
if !rule.intersects(&input_glyph_classes, &backtrack_classes, &lookahead_classes) {
893+
if !rule.intersects(
894+
ctx.glyphs(),
895+
&input_class_def,
896+
backtrack_class_def.as_ref(),
897+
lookahead_class_def.as_ref(),
898+
) {
897899
continue;
898900
}
899901

@@ -1465,4 +1467,4 @@ mod tests {
14651467
.unwrap();
14661468
assert!(ret.is_empty());
14671469
}
1468-
}
1470+
}

read-fonts/src/tables/layout/closure.rs

Lines changed: 84 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -730,45 +730,75 @@ impl Format2Rule<'_> {
730730

731731
pub(crate) fn intersects(
732732
&self,
733-
input_classes: &IntSet<u16>,
734-
backtrack_classes: &IntSet<u16>,
735-
lookahead_classes: &IntSet<u16>,
733+
glyphs: &IntSet<GlyphId>,
734+
input_class_def: &ClassDef,
735+
backtrack_class_def: Option<&ClassDef>,
736+
lookahead_class_def: Option<&ClassDef>,
736737
) -> bool {
737738
match self {
738-
Self::Plain(table) => table.intersects(input_classes),
739-
Self::Chain(table) => {
740-
table.intersects(input_classes, backtrack_classes, lookahead_classes)
741-
}
739+
Self::Plain(table) => table.intersects(glyphs, input_class_def),
740+
Self::Chain(table) => table.intersects(
741+
glyphs,
742+
input_class_def,
743+
backtrack_class_def,
744+
lookahead_class_def,
745+
),
742746
}
743747
}
744748
}
745749

746750
impl ClassSequenceRule<'_> {
747-
fn intersects(&self, input_classes: &IntSet<u16>) -> bool {
751+
fn intersects(&self, glyphs: &IntSet<GlyphId>, input_class_def: &ClassDef) -> bool {
748752
self.input_sequence()
749753
.iter()
750-
.all(|c| input_classes.contains(c.get()))
754+
.all(|c| input_class_def.intersects_class_glyphs(glyphs, c.get()))
751755
}
752756
}
753757

754758
impl ChainedClassSequenceRule<'_> {
755759
fn intersects(
756760
&self,
757-
input_classes: &IntSet<u16>,
758-
backtrack_classes: &IntSet<u16>,
759-
lookahead_classes: &IntSet<u16>,
761+
glyphs: &IntSet<GlyphId>,
762+
input_class_def: &ClassDef,
763+
backtrack_class_def: Option<&ClassDef>,
764+
lookahead_class_def: Option<&ClassDef>,
760765
) -> bool {
761-
self.input_sequence()
766+
if !self
767+
.input_sequence()
762768
.iter()
763-
.all(|c| input_classes.contains(c.get()))
764-
&& self
769+
.all(|c| input_class_def.intersects_class_glyphs(glyphs, c.get()))
770+
{
771+
return false;
772+
}
773+
774+
if let Some(backtrack_class_def) = backtrack_class_def {
775+
if !self
765776
.backtrack_sequence()
766777
.iter()
767-
.all(|c| backtrack_classes.contains(c.get()))
768-
&& self
778+
.all(|c| backtrack_class_def.intersects_class_glyphs(glyphs, c.get()))
779+
{
780+
return false;
781+
}
782+
} else {
783+
if self.backtrack_glyph_count() != 0 {
784+
return false;
785+
}
786+
}
787+
788+
if let Some(lookahead_class_def) = lookahead_class_def {
789+
if !self
769790
.lookahead_sequence()
770791
.iter()
771-
.all(|c| lookahead_classes.contains(c.get()))
792+
.all(|c| lookahead_class_def.intersects_class_glyphs(glyphs, c.get()))
793+
{
794+
return false;
795+
}
796+
} else {
797+
if self.lookahead_glyph_count() != 0 {
798+
return false;
799+
}
800+
}
801+
true
772802
}
773803
}
774804

@@ -878,49 +908,52 @@ impl Intersect for ContextFormat2<'_> {
878908
let Some(coverage) = self.coverage().transpose()? else {
879909
return Ok(false);
880910
};
881-
let retained_coverage_glyphs = coverage.intersect_set(glyph_set);
882-
if retained_coverage_glyphs.is_empty() {
911+
if !coverage.intersects(glyph_set) {
883912
return Ok(false);
884913
}
914+
let retained_coverage_glyphs = coverage.intersect_set(glyph_set);
885915

886916
let Some(input_class_def) = self.input_class_def().transpose()? else {
887917
return Ok(false);
888918
};
889-
let coverage_glyph_classes = input_class_def.intersect_classes(&retained_coverage_glyphs);
890-
let input_glyph_classes = input_class_def.intersect_classes(glyph_set);
891919

892-
let backtrack_classes = match self {
893-
Self::Plain(_) => IntSet::empty(),
920+
let backtrack_class_def = match self {
921+
Self::Plain(_) => None,
894922
Self::Chain(table) => {
895923
if table.backtrack_class_def_offset().is_null() {
896-
IntSet::empty()
924+
None
897925
} else {
898-
table.backtrack_class_def()?.intersect_classes(glyph_set)
926+
Some(table.backtrack_class_def()?)
899927
}
900928
}
901929
};
902-
let lookahead_classes = match self {
903-
Self::Plain(_) => IntSet::empty(),
930+
let lookahead_class_def = match self {
931+
Self::Plain(_) => None,
904932
Self::Chain(table) => {
905933
if table.lookahead_class_def_offset().is_null() {
906-
IntSet::empty()
934+
None
907935
} else {
908-
table.lookahead_class_def()?.intersect_classes(glyph_set)
936+
Some(table.lookahead_class_def()?)
909937
}
910938
}
911939
};
912940

913941
for rule_set in self.rule_sets().enumerate().filter_map(|(c, rule_set)| {
914-
coverage_glyph_classes
915-
.contains(c as u16)
942+
input_class_def
943+
.intersects_class_glyphs(&retained_coverage_glyphs, c as u16)
916944
.then_some(rule_set)
917945
.flatten()
918946
}) {
919947
for rule in rule_set?.rules() {
920948
let Some(rule) = rule.transpose()? else {
921949
continue;
922950
};
923-
if rule.intersects(&input_glyph_classes, &backtrack_classes, &lookahead_classes) {
951+
if rule.intersects(
952+
glyph_set,
953+
&input_class_def,
954+
backtrack_class_def.as_ref(),
955+
lookahead_class_def.as_ref(),
956+
) {
924957
return Ok(true);
925958
}
926959
}
@@ -934,42 +967,38 @@ impl LookupClosure for ContextFormat2<'_> {
934967
let Some(coverage) = self.coverage().transpose()? else {
935968
return Ok(());
936969
};
937-
let glyph_set = c.glyphs();
938-
let retained_coverage_glyphs = coverage.intersect_set(glyph_set);
939-
if retained_coverage_glyphs.is_empty() {
970+
if !coverage.intersects(c.glyphs()) {
940971
return Ok(());
941972
}
942-
973+
let retained_coverage_glyphs = coverage.intersect_set(c.glyphs());
943974
let Some(input_class_def) = self.input_class_def().transpose()? else {
944975
return Ok(());
945976
};
946-
let coverage_glyph_classes = input_class_def.intersect_classes(&retained_coverage_glyphs);
947-
let input_glyph_classes = input_class_def.intersect_classes(glyph_set);
948977

949-
let backtrack_classes = match self {
950-
Self::Plain(_) => IntSet::empty(),
978+
let backtrack_class_def = match self {
979+
Self::Plain(_) => None,
951980
Self::Chain(table) => {
952981
if table.backtrack_class_def_offset().is_null() {
953-
IntSet::empty()
982+
None
954983
} else {
955-
table.backtrack_class_def()?.intersect_classes(glyph_set)
984+
Some(table.backtrack_class_def()?)
956985
}
957986
}
958987
};
959-
let lookahead_classes = match self {
960-
Self::Plain(_) => IntSet::empty(),
988+
let lookahead_class_def = match self {
989+
Self::Plain(_) => None,
961990
Self::Chain(table) => {
962991
if table.lookahead_class_def_offset().is_null() {
963-
IntSet::empty()
992+
None
964993
} else {
965-
table.lookahead_class_def()?.intersect_classes(glyph_set)
994+
Some(table.lookahead_class_def()?)
966995
}
967996
}
968997
};
969998

970999
for rule_set in self.rule_sets().enumerate().filter_map(|(c, rule_set)| {
971-
coverage_glyph_classes
972-
.contains(c as u16)
1000+
input_class_def
1001+
.intersects_class_glyphs(&retained_coverage_glyphs, c as u16)
9731002
.then_some(rule_set)
9741003
.flatten()
9751004
}) {
@@ -985,7 +1014,12 @@ impl LookupClosure for ContextFormat2<'_> {
9851014
continue;
9861015
};
9871016

988-
if !rule.intersects(&input_glyph_classes, &backtrack_classes, &lookahead_classes) {
1017+
if !rule.intersects(
1018+
c.glyphs(),
1019+
&input_class_def,
1020+
backtrack_class_def.as_ref(),
1021+
lookahead_class_def.as_ref(),
1022+
) {
9891023
continue;
9901024
}
9911025

0 commit comments

Comments
 (0)