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,
8687StatusOr<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-
246195void 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-
282207StatusOr<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 = {};
0 commit comments