|
4 | 4 | #include "common/int_set.h" |
5 | 5 | #include "common/try.h" |
6 | 6 | #include "ift/encoder/requested_segmentation_information.h" |
| 7 | +#include "ift/encoder/subset_definition.h" |
7 | 8 | #include "ift/encoder/types.h" |
8 | 9 |
|
9 | 10 | using absl::Status; |
@@ -63,6 +64,37 @@ StatusOr<GlyphSet> GlyphClosureCache::CodepointsToOrGids( |
63 | 64 | return or_gids; |
64 | 65 | } |
65 | 66 |
|
| 67 | +// This generates the subset definition that contains all segments except for |
| 68 | +// those listed in segment_ids. |
| 69 | +SubsetDefinition ComputExceptSegment( |
| 70 | + const RequestedSegmentationInformation& segmentation_info, |
| 71 | + const SegmentSet& segment_ids, const SubsetDefinition& combined) { |
| 72 | + if (segmentation_info.SegmentsAreDisjoint() && |
| 73 | + (segment_ids.size() == 1 || |
| 74 | + segment_ids.size() < (segmentation_info.Segments().size() / 2))) { |
| 75 | + // Approach that is optimzied for the case where input segments are disjoint |
| 76 | + // and the number of segment ids is smallish. |
| 77 | + SubsetDefinition except_segment = segmentation_info.FullDefinition(); |
| 78 | + except_segment.Subtract(combined); |
| 79 | + return except_segment; |
| 80 | + } |
| 81 | + |
| 82 | + // Otherwise this approach will always work even with non-disjoint segments |
| 83 | + SegmentSet except_segment_ids = segment_ids; |
| 84 | + except_segment_ids.invert(); |
| 85 | + |
| 86 | + uint32_t num_segments = segmentation_info.Segments().size(); |
| 87 | + SubsetDefinition except_segment = segmentation_info.InitFontSegment(); |
| 88 | + for (segment_index_t s : except_segment_ids) { |
| 89 | + if (s >= num_segments) { |
| 90 | + break; |
| 91 | + } |
| 92 | + except_segment.Union(segmentation_info.Segments()[s].Definition()); |
| 93 | + } |
| 94 | + |
| 95 | + return except_segment; |
| 96 | +} |
| 97 | + |
66 | 98 | Status GlyphClosureCache::AnalyzeSegment( |
67 | 99 | const RequestedSegmentationInformation& segmentation_info, |
68 | 100 | const SegmentSet& segment_ids, GlyphSet& and_gids, GlyphSet& or_gids, |
@@ -95,20 +127,19 @@ Status GlyphClosureCache::AnalyzeSegment( |
95 | 127 | // * I - D: the activation conditions for these glyphs is s_i OR … |
96 | 128 | // Where … is one or more additional segments. |
97 | 129 | // * D intersection I: the activation conditions for these glyphs is only s_i |
98 | | - SubsetDefinition except_segment = segmentation_info.InitFontSegment(); |
99 | | - for (uint32_t s = 0; s < segmentation_info.Segments().size(); s++) { |
100 | | - if (segment_ids.contains(s)) { |
101 | | - continue; |
102 | | - } |
103 | | - except_segment.Union(segmentation_info.Segments()[s].Definition()); |
| 130 | + |
| 131 | + SubsetDefinition |
| 132 | + combined; // This is the subset definition of the unions of segment_ids. |
| 133 | + for (segment_index_t s_id : segment_ids) { |
| 134 | + combined.Union(segmentation_info.Segments()[s_id].Definition()); |
104 | 135 | } |
105 | 136 |
|
| 137 | + SubsetDefinition except_segment = |
| 138 | + ComputExceptSegment(segmentation_info, segment_ids, combined); |
106 | 139 | auto B_except_segment_closure = TRY(GlyphClosure(except_segment)); |
107 | 140 |
|
108 | | - SubsetDefinition only_segment = segmentation_info.InitFontSegment(); |
109 | | - for (segment_index_t s_id : segment_ids) { |
110 | | - only_segment.Union(segmentation_info.Segments()[s_id].Definition()); |
111 | | - } |
| 141 | + SubsetDefinition only_segment = combined; |
| 142 | + only_segment.Union(segmentation_info.InitFontSegment()); |
112 | 143 |
|
113 | 144 | auto I_only_segment_closure = TRY(GlyphClosure(only_segment)); |
114 | 145 | I_only_segment_closure.subtract(segmentation_info.InitFontGlyphs()); |
|
0 commit comments