Skip to content

Commit 65c15ff

Browse files
committed
Re-write SegmentsThatInteractWith(...) to use extracted node conditions.
Additionally drops a bunch of now uneeded code from DependencyClosure.
1 parent 3c9f85c commit 65c15ff

File tree

6 files changed

+10
-484
lines changed

6 files changed

+10
-484
lines changed

ift/encoder/BUILD

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ cc_library(
6767
"merger.cc",
6868
"merger.h",
6969
"patch_size_cache.h",
70-
"reachability_index.cc",
71-
"reachability_index.h",
7270
"segmentation_context.cc",
7371
"segmentation_context.h",
7472
] + select({
@@ -369,16 +367,3 @@ cc_test(
369367
"@googletest//:gtest_main",
370368
],
371369
)
372-
373-
cc_test(
374-
name = "reachability_index_test",
375-
srcs = ["reachability_index_test.cc"],
376-
data = [
377-
"//ift/common:testdata",
378-
],
379-
deps = [
380-
":segmentation_context",
381-
"//ift/common",
382-
"@googletest//:gtest_main",
383-
],
384-
)

ift/encoder/dependency_closure.cc

Lines changed: 8 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ Status DependencyClosure::InitFontChanged(const SegmentSet& segments) {
5858
// closure, we need to record the context glyphs from these as they are
5959
// potential interaction points.
6060
init_font_context_glyphs_.clear();
61-
init_font_features_ = TRY(graph_.InitFontFeatureSet());
6261
Traversal init_font_traversal = TRY(graph_.ClosureTraversal(
6362
{Node::InitFont()}, &segmentation_info_->FullClosure(),
6463
&segmentation_info_->FullDefinition().codepoints, false));
@@ -69,13 +68,6 @@ Status DependencyClosure::InitFontChanged(const SegmentSet& segments) {
6968
}
7069
}
7170

72-
init_font_reachable_glyphs_ = init_font_traversal.ReachedGlyphs();
73-
init_font_reachable_glyphs_.subtract(segmentation_info_->InitFontGlyphs());
74-
75-
// Note: reachability index must be updated after context_glyphs_, init_font_*
76-
// sets are populated. since it utilizes those to assess traversal accuracy.
77-
TRYV(UpdateReachabilityIndex(segments));
78-
7971
return absl::OkStatus();
8072
}
8173

@@ -87,11 +79,10 @@ Status DependencyClosure::SegmentsMerged(segment_index_t base_segment,
8779
return InitFontChanged(segments);
8880
}
8981

82+
VLOG(1) << "DependencyClosure::SegmentsMerged()";
83+
9084
// Manually update the glyph condition cache.
9185
UpdateNodeConditionsCache(base_segment, segments);
92-
93-
VLOG(1) << "DependencyClosure::SegmentsMerged()";
94-
TRYV(UpdateReachabilityIndex(segments));
9586
return absl::OkStatus();
9687
}
9788

@@ -327,13 +318,6 @@ StatusOr<SegmentSet> DependencyClosure::SegmentsThatInteractWith(
327318

328319
StatusOr<SegmentSet> DependencyClosure::SegmentsThatInteractWith(
329320
const absl::flat_hash_set<dep_graph::Node> nodes) const {
330-
// TODO(garretrieger): we can narrow the set by considering context glyphs per
331-
// activated glyph instead of just the whole set of context glyphs.
332-
333-
flat_hash_set<Node> visited;
334-
SegmentSet visited_segments;
335-
GlyphSet visited_glyphs;
336-
337321
btree_set<Node> to_check;
338322
to_check.insert(nodes.begin(), nodes.end());
339323

@@ -351,127 +335,15 @@ StatusOr<SegmentSet> DependencyClosure::SegmentsThatInteractWith(
351335
to_check.insert(Node::Feature(f));
352336
}
353337

354-
bool init_font_context_added = false;
355-
356-
while (!to_check.empty()) {
357-
Node next = *to_check.begin();
358-
to_check.erase(next);
359-
visited.insert(next);
360-
if (next.IsGlyph()) {
361-
visited_glyphs.insert(next.Id());
362-
}
363-
364-
// node may be reachable from the init font.
365-
if (!init_font_context_added && next.IsGlyph() &&
366-
init_font_reachable_glyphs_.contains(next.Id())) {
367-
ReachabilityInitFontAddToCheck(visited_glyphs, to_check);
368-
init_font_context_added = true;
369-
}
370-
371-
// now check if any segments can reach it.
372-
SegmentSet segments;
373-
if (next.IsGlyph()) {
374-
segments = unconstrained_reachability_.SegmentsForGlyph(next.Id());
375-
} else if (next.IsUnicode()) {
376-
segments = unconstrained_reachability_.SegmentsForCodepoint(next.Id());
377-
} else if (next.IsFeature()) {
378-
segments = unconstrained_reachability_.SegmentsForFeature(next.Id());
379-
} else {
380-
// ignored node type.
381-
continue;
382-
}
383-
384-
if (segments.empty()) {
338+
SegmentSet out;
339+
for (Node node : to_check) {
340+
auto it = node_condition_cache_.find(node);
341+
if (it == node_condition_cache_.end()) {
385342
continue;
386343
}
387-
388-
TRYV(ReachabilitySegmentsAddToCheck(segments, visited_glyphs,
389-
visited_segments, to_check));
390-
}
391-
392-
return visited_segments;
393-
}
394-
395-
void DependencyClosure::ReachabilityInitFontAddToCheck(
396-
const GlyphSet& visited_glyphs, btree_set<Node>& to_check) const {
397-
GlyphSet additional = init_font_context_glyphs_;
398-
additional.subtract(visited_glyphs);
399-
for (glyph_id_t gid : additional) {
400-
to_check.insert(Node::Glyph(gid));
344+
out.union_set(it->second.TriggeringSegments());
401345
}
402-
}
403-
404-
Status DependencyClosure::ReachabilitySegmentsAddToCheck(
405-
const SegmentSet& segments, const GlyphSet& visited_glyphs,
406-
SegmentSet& visited_segments, btree_set<Node>& to_check) const {
407-
for (segment_index_t s : segments) {
408-
if (visited_segments.contains(s)) {
409-
continue;
410-
}
411-
412-
visited_segments.insert(s);
413-
414-
GlyphSet additional = context_reachability_.GlyphsForSegment(s);
415-
416-
additional.subtract(visited_glyphs);
417-
418-
for (glyph_id_t gid : additional) {
419-
to_check.insert(Node::Glyph(gid));
420-
}
421-
}
422-
return absl::OkStatus();
423-
}
424-
425-
Status DependencyClosure::UpdateReachabilityIndex(SegmentSet segments) {
426-
if (reachability_index_valid_) {
427-
// If indices have existing data, then we need to ensure prior entries for
428-
// the segments to be updated are cleared out.
429-
for (segment_index_t s : segments) {
430-
if (s >= segmentation_info_->Segments().size()) {
431-
break;
432-
}
433-
ClearReachabilityIndex(s);
434-
}
435-
} else {
436-
// If the index isn't built yet then all segments need to be updated.
437-
segments = SegmentSet::all();
438-
}
439-
440-
for (segment_index_t s : segments) {
441-
if (s >= segmentation_info_->Segments().size()) {
442-
break;
443-
}
444-
TRYV(UpdateReachabilityIndex(s));
445-
}
446-
447-
reachability_index_valid_ = true;
448-
return absl::OkStatus();
449-
}
450-
451-
Status DependencyClosure::UpdateReachabilityIndex(segment_index_t s) {
452-
auto traversal = TRY(graph_.ClosureTraversal({s}, false));
453-
for (glyph_id_t g : traversal.ReachedGlyphs()) {
454-
unconstrained_reachability_.AddGlyph(s, g);
455-
}
456-
457-
for (hb_codepoint_t cp : traversal.ReachedCodepoints()) {
458-
unconstrained_reachability_.AddCodepoint(s, cp);
459-
}
460-
461-
for (hb_tag_t f : traversal.ReachedLayoutFeatures()) {
462-
unconstrained_reachability_.AddFeature(s, f);
463-
}
464-
465-
for (glyph_id_t g : traversal.ContextGlyphs()) {
466-
context_reachability_.AddGlyph(s, g);
467-
}
468-
469-
return absl::OkStatus();
470-
}
471-
472-
void DependencyClosure::ClearReachabilityIndex(segment_index_t segment) {
473-
unconstrained_reachability_.ClearSegment(segment);
474-
context_reachability_.ClearSegment(segment);
346+
return out;
475347
}
476348

477349
flat_hash_map<Node, ActivationCondition>

ift/encoder/dependency_closure.h

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "ift/common/int_set.h"
1212
#include "ift/common/try.h"
1313
#include "ift/encoder/activation_condition.h"
14-
#include "ift/encoder/reachability_index.h"
1514
#include "ift/encoder/subset_definition.h"
1615
#include "ift/encoder/types.h"
1716

@@ -112,6 +111,8 @@ class DependencyClosure {
112111
//
113112
// Utilizes the dependency graph to make the determination, so it's possible
114113
// that the result may be overestimated.
114+
//
115+
// TODO XXXX can drop StatusOr<> from these.
115116
absl::StatusOr<ift::common::SegmentSet> SegmentsThatInteractWith(
116117
const common::GlyphSet& glyphs) const;
117118
absl::StatusOr<ift::common::SegmentSet> SegmentsThatInteractWith(
@@ -175,52 +176,25 @@ class DependencyClosure {
175176
absl::StatusOr<common::SegmentSet> FilterSegments(
176177
const common::SegmentSet& segments) const;
177178

178-
void ReachabilityInitFontAddToCheck(
179-
const common::GlyphSet& visited_glyphs,
180-
absl::btree_set<dep_graph::Node>& to_check) const;
181-
182-
absl::Status ReachabilitySegmentsAddToCheck(
183-
const ift::common::SegmentSet& segments,
184-
const common::GlyphSet& visited_glyphs,
185-
ift::common::SegmentSet& visited_segments,
186-
absl::btree_set<dep_graph::Node>& to_check) const;
187-
188179
absl::Status InitNodeConditionsCache();
189180
void UpdateNodeConditionsCache(segment_index_t base_segment,
190181
const common::SegmentSet& segments);
191182
absl::flat_hash_set<dep_graph::Node> SegmentsToAffectedNodeConditions(
192183
const common::SegmentSet& segments) const;
193184

194-
absl::Status UpdateReachabilityIndex(ift::common::SegmentSet segments);
195-
absl::Status UpdateReachabilityIndex(segment_index_t segment);
196-
void ClearReachabilityIndex(segment_index_t segment);
197-
198185
const RequestedSegmentationInformation* segmentation_info_;
199186
ift::common::hb_face_unique_ptr original_face_;
200187
dep_graph::DependencyGraph graph_;
201188

202189
ift::common::GlyphSet context_glyphs_;
203-
ift::common::GlyphSet init_font_reachable_glyphs_;
204190
ift::common::GlyphSet init_font_context_glyphs_;
205-
absl::flat_hash_set<hb_tag_t> init_font_features_;
206191

207192
absl::flat_hash_map<glyph_id_t, ActivationCondition> glyph_condition_cache_;
208193
absl::flat_hash_map<dep_graph::Node, ActivationCondition>
209194
node_condition_cache_;
210195
absl::flat_hash_map<segment_index_t, absl::flat_hash_set<dep_graph::Node>>
211196
node_conditions_with_segment_;
212197

213-
// Reachability indexes: these indexes are used to quickly locate segments
214-
// reachable from glyph and features (and in reverse as well).
215-
bool reachability_index_valid_ = false;
216-
217-
// Unconstrained reachability, these are the glyphs/features that can be
218-
// reached by a segment if context constraints are not enforced.
219-
ReachabilityIndex unconstrained_reachability_;
220-
221-
// Tracks which context glyphs (for contextual gsub substitutions) can be
222-
// reached from a segment.
223-
ReachabilityIndex context_reachability_;
224198
#endif
225199

226200
uint64_t accurate_results_ = 0;

0 commit comments

Comments
 (0)