From 7d542a5274d56229a72c30e53aecbae8ea938f4e Mon Sep 17 00:00:00 2001 From: ckitagawa Date: Wed, 29 Jan 2020 10:20:00 -0500 Subject: [PATCH] Refactor to two iterators --- src/hb-ot-color-colr-table.hh | 142 ++++++++++-------- src/hb-subset-plan.cc | 2 +- .../TwemojiMozilla.subset.default.32,3299.ttf | Bin 0 -> 5264 bytes test/api/test-subset-colr.c | 21 +++ 4 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index cd5b95713..3f88005ce 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -127,16 +127,16 @@ struct COLR bool is_valid () { return colr.get_blob ()->length; } - void get_related_glyphs (hb_codepoint_t glyph, - hb_set_t *related_ids /* OUT */) const + void closure_glyphs (hb_codepoint_t glyph, + hb_set_t *related_ids /* OUT */) const { colr->get_related_glyphs (glyph, related_ids); } private: hb_blob_ptr_t colr; }; - void get_related_glyphs (hb_codepoint_t glyph, - hb_set_t *related_ids /* OUT */) const + void closure_glyphs (hb_codepoint_t glyph, + hb_set_t *related_ids /* OUT */) const { const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph); @@ -155,87 +155,111 @@ struct COLR (this+layersZ).sanitize (c, numLayers))); } - template - bool serialize (hb_subset_context_t *c, + template + bool serialize (hb_serialize_context_t *c, unsigned version, - Iterator it, - hb_array_t all_layers) + BaseIterator base_it, + LayerIterator layer_it) { TRACE_SERIALIZE (this); + if (unlikely (base_it.len () != layer_it.len ())) + return_trace (false); - if (unlikely (!c->serializer->extend_min (this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->version = version; numLayers = 0; - numBaseGlyphs = it.len (); + numBaseGlyphs = base_it.len (); baseGlyphsZ = COLR::min_size; layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size; - if (unlikely (!c->serializer->allocate_size ((unsigned int) layersZ - (unsigned int) baseGlyphsZ))) - return_trace (false); - hb_sorted_array_t glyph_records = (this+baseGlyphsZ).as_array (numBaseGlyphs); - - unsigned int index = 0; - for (const hb_item_type& _ : + it.iter ()) + for (const hb_item_type& _ : + base_it.iter ()) { - const unsigned int new_gid = _.first; - const BaseGlyphRecord* record = _.second; - if (record->firstLayerIdx >= all_layers.length || - record->firstLayerIdx + record->numLayers > all_layers.length) - return_trace (false); - - glyph_records[index].glyphId = new_gid; - glyph_records[index].numLayers = record->numLayers; - glyph_records[index].firstLayerIdx = numLayers; - index += 1; - - hb_array_t layers = all_layers.sub_array (record->firstLayerIdx, - record->numLayers); - - for (unsigned int i = 0; i < layers.length; i++) - { - hb_codepoint_t new_gid = 0; - if (unlikely (!c->plan->new_gid_for_old_gid (layers[i].glyphId, &new_gid))) return_trace (false); - - LayerRecord* out_layer = c->serializer->start_embed (); - if (unlikely (!c->serializer->extend_min (out_layer))) return_trace (false); - - out_layer->glyphId = new_gid; - out_layer->colorIdx = layers[i].colorIdx; - } + auto* record = c->embed(_); + if (unlikely (!record)) return_trace (false); + record->firstLayerIdx = numLayers; numLayers += record->numLayers; } + for (const hb_item_type& _ : + layer_it.iter ()) + _.as_array ().copy (c); + return_trace (true); } + const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const + { + if ((unsigned int) gid == 0) // Ignore notdef. + return nullptr; + const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid); + if ((record && (hb_codepoint_t) record->glyphId != gid)) + record = nullptr; + return record; + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto it = - + hb_range (1u, c->plan->num_output_glyphs ()) // Skip notdef. - | hb_map ([&](unsigned int new_gid) - { - hb_codepoint_t old_gid = 0; - if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) - return hb_pair_t(new_gid, nullptr); + const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map; - const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, old_gid); - if (record && (hb_codepoint_t) record->glyphId != old_gid) - record = nullptr; - return hb_pair_t (new_gid, record); + auto base_it = + + hb_range (c->plan->num_output_glyphs ()) + | hb_map_retains_sorting ([&](hb_codepoint_t new_gid) + { + hb_codepoint_t old_gid = reverse_glyph_map.get(new_gid); + const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); + + BaseGlyphRecord new_record; + if (unlikely (!old_record)) + return hb_pair_t (false, new_record); + + new_record.glyphId = new_gid; + new_record.numLayers = old_record->numLayers; + return hb_pair_t (true, new_record); }) - | hb_filter (hb_second) + | hb_filter (hb_first) + | hb_map_retains_sorting (hb_second) ; - if (unlikely (!it.len ())) return_trace (false); + auto layer_it = + + hb_range (c->plan->num_output_glyphs ()) + | hb_map (reverse_glyph_map) + | hb_map_retains_sorting ([&](hb_codepoint_t old_gid) + { + const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); + hb_vector_t out_layers; + + if (unlikely (!old_record || + old_record->firstLayerIdx >= numLayers || + old_record->firstLayerIdx + old_record->numLayers > numLayers)) + return hb_pair_t> (false, out_layers); + + hb_array_t layers = (this+layersZ).as_array (numLayers).sub_array(old_record->firstLayerIdx, + old_record->numLayers); + out_layers.resize (layers.length); + for (unsigned int i = 0; i < layers.length; i++) { + out_layers[i] = layers[i]; + hb_codepoint_t new_gid = 0; + if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid))) + return hb_pair_t> (false, out_layers); + out_layers[i].glyphId = new_gid; + } + + return hb_pair_t> (true, out_layers); + }) + | hb_filter (hb_first) + | hb_map_retains_sorting (hb_second) + ; + + if (unlikely (!base_it.len () || + !layer_it.len () || + base_it.len () != layer_it.len ())) + return_trace (false); COLR *colr_prime = c->serializer->start_embed (); - - hb_array_t all_layers = (this+layersZ).as_array (numLayers); - - return_trace (colr_prime->serialize (c, version, it, all_layers)); + return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it)); } protected: diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index b59af2f60..672b748bb 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -205,7 +205,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, _add_cff_seac_components (cff, gid, plan->_glyphset); #endif if (colr.is_valid ()) - colr.get_related_glyphs (gid, plan->_glyphset); + colr.closure_glyphs (gid, plan->_glyphset); } _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ()); diff --git a/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf b/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf new file mode 100644 index 0000000000000000000000000000000000000000..be3a53d6dec69a7f67c7e7e99ad9ff8064bf947e GIT binary patch literal 5264 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