Skip to content

Commit f52f144

Browse files
committed
Remove SetBaseSubsetFromPatches() method.
Base subset is now always set in terms of codepoints or a subset def.
1 parent 4fa6167 commit f52f144

File tree

6 files changed

+111
-173
lines changed

6 files changed

+111
-173
lines changed

ift/encoder/condition.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
namespace ift::encoder {
1010

1111
/*
12-
* This conditions is satisfied if the input subset definition matches at
13-
* least one segment in each required group and every feature in
14-
* required_features.
12+
* This conditions is satisfied if the input subset definition
13+
* matches the conditions subset_definition and all child conditions
14+
* are matched.
15+
*
16+
* Child conditions refer to the indices of previous condition entries
17+
* See: https://w3c.github.io/IFT/Overview.html#mapping-entry-childentryindices
1518
*/
1619
struct Condition {
1720
SubsetDefinition subset_definition;

ift/encoder/encoder.cc

Lines changed: 27 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "common/try.h"
2121
#include "common/woff2.h"
2222
#include "hb-subset.h"
23+
#include "ift/encoder/subset_definition.h"
2324
#include "ift/glyph_keyed_diff.h"
2425
#include "ift/proto/ift_table.h"
2526
#include "ift/proto/patch_encoding.h"
@@ -86,7 +87,7 @@ void Encoder::AddCombinations(const std::vector<const SubsetDefinition*>& in,
8687
StatusOr<FontData> Encoder::FullyExpandedSubset(
8788
const ProcessingContext& context) const {
8889
SubsetDefinition all;
89-
all.Union(base_subset_);
90+
all.Union(context.base_subset_);
9091

9192
for (const auto& s : extension_subsets_) {
9293
all.Union(s);
@@ -191,58 +192,6 @@ Status Encoder::AddGlyphDataPatchCondition(Condition condition) {
191192
return absl::OkStatus();
192193
}
193194

194-
Status Encoder::SetBaseSubsetFromPatches(
195-
const flat_hash_set<uint32_t>& included_glyph_data) {
196-
design_space_t empty;
197-
return SetBaseSubsetFromPatches(included_glyph_data, empty);
198-
}
199-
200-
Status Encoder::SetBaseSubsetFromPatches(
201-
const flat_hash_set<uint32_t>& included_glyph_data,
202-
const design_space_t& design_space) {
203-
// TODO(garretrieger): support also providing initial features.
204-
if (!face_) {
205-
return absl::FailedPreconditionError("Encoder must have a face set.");
206-
}
207-
208-
if (!base_subset_.empty()) {
209-
return absl::FailedPreconditionError("Base subset has already been set.");
210-
}
211-
212-
for (uint32_t patch_id : included_glyph_data) {
213-
if (!glyph_data_patches_.contains(patch_id)) {
214-
return absl::InvalidArgumentError(StrCat("Glyph data patch, ", patch_id,
215-
", not added to the encoder."));
216-
}
217-
}
218-
219-
auto included = SubsetDefinitionForPatches(included_glyph_data);
220-
if (!included.ok()) {
221-
return included.status();
222-
}
223-
224-
base_subset_ = *included;
225-
base_subset_.design_space = design_space;
226-
227-
// Glyph keyed patches can't change the glyph count in the font (and hence
228-
// loca len) so always include the last gid in the base subset to force the
229-
// loca table to remain at the full length from the start.
230-
//
231-
// TODO(garretrieger): this unnecessarily includes the last gid in the subset,
232-
// should update the subsetter to retain the glyph count
233-
// but not actually keep the last gid.
234-
//
235-
// TODO(garretrieger): instead of forcing max glyph count here we can utilize
236-
// table keyed patches to change loca len/glyph count to
237-
// the max for any currently reachable segments. This
238-
// would improve efficiency slightly by avoid including
239-
// extra space in the initial font.
240-
uint32_t gid_count = hb_face_get_glyph_count(face_.get());
241-
if (gid_count > 0) base_subset_.gids.insert(gid_count - 1);
242-
243-
return absl::OkStatus();
244-
}
245-
246195
void Encoder::AddFeatureGroupSegment(const btree_set<hb_tag_t>& feature_tags) {
247196
SubsetDefinition def;
248197
def.feature_tags = feature_tags;
@@ -255,36 +204,35 @@ void Encoder::AddDesignSpaceSegment(const design_space_t& space) {
255204
extension_subsets_.push_back(def);
256205
}
257206

258-
StatusOr<SubsetDefinition> Encoder::SubsetDefinitionForPatches(
259-
const flat_hash_set<uint32_t>& patch_ids) const {
260-
auto gid_to_unicode = FontHelper::GidToUnicodeMap(face_.get());
261-
262-
SubsetDefinition result;
263-
for (uint32_t patch_id : patch_ids) {
264-
auto p = glyph_data_patches_.find(patch_id);
265-
if (p == glyph_data_patches_.end()) {
266-
return absl::InvalidArgumentError(
267-
StrCat("Glyph data patches, ", patch_id, ", not found."));
268-
}
269-
270-
for (uint32_t gid : p->second) {
271-
auto cp = gid_to_unicode.find(gid);
272-
if (cp != gid_to_unicode.end()) {
273-
result.codepoints.insert(cp->second);
274-
}
275-
result.gids.insert(gid);
276-
}
277-
}
278-
279-
return result;
280-
}
281-
282207
StatusOr<Encoder::Encoding> Encoder::Encode() const {
283208
if (!face_) {
284209
return absl::FailedPreconditionError("Encoder must have a face set.");
285210
}
286211

287212
ProcessingContext context(next_id_);
213+
context.base_subset_ = base_subset_;
214+
if (IsMixedMode()) {
215+
// Glyph keyed patches can't change the glyph count in the font (and hence
216+
// loca len) so always include the last gid in the base subset to force the
217+
// loca table to remain at the full length from the start.
218+
//
219+
// TODO(garretrieger): this unnecessarily includes the last gid in the
220+
// subset,
221+
// should update the subsetter to retain the glyph count
222+
// but not actually keep the last gid.
223+
//
224+
// TODO(garretrieger): instead of forcing max glyph count here we can
225+
// utilize
226+
// table keyed patches to change loca len/glyph count to
227+
// the max for any currently reachable segments. This
228+
// would improve efficiency slightly by avoid including
229+
// extra space in the initial font. However, it would
230+
// require us to examine conditions against each subset
231+
// to determine patch reachability.
232+
uint32_t gid_count = hb_face_get_glyph_count(face_.get());
233+
if (gid_count > 0) context.base_subset_.gids.insert(gid_count - 1);
234+
}
235+
288236
context.force_long_loca_and_gvar_ = false;
289237
auto expanded = FullyExpandedSubset(context);
290238
if (!expanded.ok()) {
@@ -297,7 +245,7 @@ StatusOr<Encoder::Encoding> Encoder::Encode() const {
297245
FontHelper::HasLongLoca(expanded_face.get()) ||
298246
FontHelper::HasWideGvar(expanded_face.get());
299247

300-
auto init_font = Encode(context, base_subset_, true);
248+
auto init_font = Encode(context, context.base_subset_, true);
301249
if (!init_font.ok()) {
302250
return init_font.status();
303251
}
@@ -603,7 +551,7 @@ StatusOr<FontData> Encoder::GenerateBaseGvar(
603551
}
604552

605553
// Step 2: glyph subsetting
606-
SubsetDefinition subset = base_subset_;
554+
SubsetDefinition subset = context.base_subset_;
607555
// We don't want to apply any instancing here as it was done in step 1
608556
// so clear out the design space.
609557
subset.design_space = {};

ift/encoder/encoder.h

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -69,35 +69,21 @@ class Encoder {
6969
* Configure the base subset to cover the provided codepoints, and the set of
7070
* layout features retained by default in the harfbuzz subsetter.
7171
*/
72-
template <typename T>
73-
absl::Status SetBaseSubset(const T& base_subset) {
72+
template <typename Set>
73+
absl::Status SetBaseSubset(const Set& base_codepoints) {
7474
if (!base_subset_.empty()) {
7575
return absl::FailedPreconditionError("Base subset has already been set.");
7676
}
77-
base_subset_.codepoints.insert(base_subset.begin(), base_subset.end());
77+
base_subset_.codepoints.insert(base_codepoints.begin(),
78+
base_codepoints.end());
7879
return absl::OkStatus();
7980
}
8081

81-
/*
82-
* Set up the base subset to cover all glyphs in the provided list of glyph
83-
* data patches.
84-
*/
85-
absl::Status SetBaseSubsetFromPatches(
86-
const absl::flat_hash_set<uint32_t>& included_glyph_data);
87-
88-
/*
89-
* Set up the base subset to cover all glyphs in the provided list of glyph
90-
* data patches. Additionally, instance to the supplied design space.
91-
*/
92-
absl::Status SetBaseSubsetFromPatches(
93-
const absl::flat_hash_set<uint32_t>& included_segments,
94-
const design_space_t& design_space);
95-
9682
/*
9783
* Adds a segment around which the non glyph data in the font will be split.
9884
*/
99-
template <typename T>
100-
void AddNonGlyphDataSegment(const T& codepoints) {
85+
template <typename Set>
86+
void AddNonGlyphDataSegment(const Set& codepoints) {
10187
SubsetDefinition def;
10288
def.codepoints.insert(codepoints.begin(), codepoints.end());
10389
extension_subsets_.push_back(def);
@@ -138,13 +124,6 @@ class Encoder {
138124
if (!base_subset_.empty()) {
139125
return absl::FailedPreconditionError("Base subset has already been set.");
140126
}
141-
// TODO(garretrieger): XXXXXXX we need to use the last gid trick from
142-
// SetBaseSubsetFromPatches (if we're mixed mode) or
143-
// table keyed patch generation needs to extend the loca
144-
// up to the maximum reachable gid for each subset.
145-
//
146-
// Also add a test that checks this case works
147-
// correctly.
148127
base_subset_ = base_subset;
149128
return absl::OkStatus();
150129
}
@@ -189,9 +168,6 @@ class Encoder {
189168
const SubsetDefinition& base_subset,
190169
bool is_root = true) const;
191170

192-
absl::StatusOr<SubsetDefinition> SubsetDefinitionForPatches(
193-
const absl::flat_hash_set<uint32_t>& patch_ids) const;
194-
195171
/*
196172
* Returns true if this encoding will contain both glyph keyed and table keyed
197173
* patches.
@@ -283,6 +259,7 @@ class Encoder {
283259

284260
absl::flat_hash_map<SubsetDefinition, common::FontData> built_subsets_;
285261
absl::flat_hash_map<std::string, common::FontData> patches_;
262+
SubsetDefinition base_subset_;
286263

287264
common::CompatId GenerateCompatId();
288265
};

ift/encoder/encoder_test.cc

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,6 @@ TEST_F(EncoderTest, MissingFace) {
349349
auto s1 = encoder.AddGlyphDataPatch(1, segment_1_gids);
350350
ASSERT_TRUE(absl::IsFailedPrecondition(s1)) << s1;
351351

352-
auto s2 = encoder.SetBaseSubsetFromPatches({});
353-
ASSERT_TRUE(absl::IsFailedPrecondition(s2)) << s2;
354-
355352
auto s3 = encoder.Encode();
356353
ASSERT_TRUE(absl::IsFailedPrecondition(s3.status())) << s3.status();
357354
}
@@ -368,21 +365,6 @@ TEST_F(EncoderTest, GlyphDataSegments_GidsNotInFace) {
368365
ASSERT_TRUE(absl::IsInvalidArgument(s)) << s;
369366
}
370367

371-
TEST_F(EncoderTest, InvalidGlyphDataPatchIds) {
372-
Encoder encoder;
373-
{
374-
hb_face_t* face = noto_sans_jp.reference_face();
375-
encoder.SetFace(face);
376-
hb_face_destroy(face);
377-
}
378-
379-
auto s = encoder.AddGlyphDataPatch(1, segment_1_gids);
380-
ASSERT_TRUE(s.ok()) << s;
381-
382-
s = encoder.SetBaseSubsetFromPatches({2});
383-
ASSERT_TRUE(absl::IsInvalidArgument(s)) << s;
384-
}
385-
386368
TEST_F(EncoderTest, DontClobberBaseSubset) {
387369
Encoder encoder;
388370
{
@@ -394,13 +376,13 @@ TEST_F(EncoderTest, DontClobberBaseSubset) {
394376
auto s = encoder.AddGlyphDataPatch(1, segment_1_gids);
395377
ASSERT_TRUE(s.ok()) << s;
396378

397-
s = encoder.SetBaseSubsetFromPatches({});
379+
s = encoder.SetBaseSubset(flat_hash_set<uint32_t>{});
398380
ASSERT_TRUE(s.ok()) << s;
399381

400382
s = encoder.SetBaseSubset(flat_hash_set<uint32_t>{1});
401-
ASSERT_TRUE(absl::IsFailedPrecondition(s)) << s;
383+
ASSERT_TRUE(s.ok()) << s;
402384

403-
s = encoder.SetBaseSubsetFromPatches({});
385+
s = encoder.SetBaseSubset(flat_hash_set<uint32_t>{});
404386
ASSERT_TRUE(absl::IsFailedPrecondition(s)) << s;
405387
}
406388

@@ -587,7 +569,11 @@ TEST_F(EncoderTest, Encode_ThreeSubsets_Mixed) {
587569
s.Update(encoder.AddGlyphDataPatchCondition(Condition::SimpleCondition(
588570
SubsetDefinition::Codepoints(segment_4_cps), 4)));
589571

590-
s.Update(encoder.SetBaseSubsetFromPatches({0, 1, 2}));
572+
flat_hash_set<uint32_t> base_subset;
573+
base_subset.insert(segment_0_cps.begin(), segment_0_cps.end());
574+
base_subset.insert(segment_1_cps.begin(), segment_1_cps.end());
575+
base_subset.insert(segment_2_cps.begin(), segment_2_cps.end());
576+
s.Update(encoder.SetBaseSubset(base_subset));
591577

592578
flat_hash_set<uint32_t> extension_segment;
593579
extension_segment.insert(segment_3_cps.begin(), segment_3_cps.end());
@@ -658,7 +644,10 @@ TEST_F(EncoderTest, Encode_ThreeSubsets_Mixed_WithFeatureMappings) {
658644
ASSERT_TRUE(s.ok()) << s;
659645

660646
// Partitions {0, 1}, {2, 3, 4}, +ccmp
661-
s.Update(encoder.SetBaseSubsetFromPatches({0, 1}));
647+
flat_hash_set<uint32_t> base_subset;
648+
base_subset.insert(segment_0_cps.begin(), segment_0_cps.end());
649+
base_subset.insert(segment_1_cps.begin(), segment_1_cps.end());
650+
s.Update(encoder.SetBaseSubset(base_subset));
662651

663652
flat_hash_set<uint32_t> extension_segment;
664653
extension_segment.insert(segment_2_cps.begin(), segment_2_cps.end());

0 commit comments

Comments
 (0)