#ifndef HB_NO_VAR if (!colr.has_var_store () || !variation_indices) return;
const OT::ItemVariationStore &var_store = colr.get_var_store (); // generated inner_maps is used by ItemVariationStore serialize(), which is subset only unsigned subtable_count = var_store.get_sub_table_count ();
generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
/* colr variation indices mapping during planning phase: *generatecolrv1_variation_idx_delta_map.Whendeltasetindexmapisnot *included,it'samappingfromvarIdx->(newvarIdx,delta).Otherwise,it's *amappingfromolddeltasetidx->(newdeltasetidx,delta).Mapping *deltasetindicesisthesameasgidmapping. *Besides,weneedtogenerateadeltasetidx->newvar_idxmapforupdating *deltasetindexmapifexists.Thismapwillbeupdatedagainafter
* instancing. */ if (!plan->all_axes_pinned)
{
remap_variation_indices (var_store,
variation_indices,
plan->normalized_coords, false, /* no need to calculate delta for COLR during planning */
plan->all_axes_pinned,
plan->colrv1_variation_idx_delta_map);
template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, hb_requires (hb_is_iterator (I))> staticvoid
_fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
I unicode_iterator,
F unicode_to_gid_for_iterator)
{
_fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator);
}
/* *Findsadditionalunicodecodepointswhicharereachablefromtheinputunicodeset. *Currentlythisaddsinmirroredvariants(neededforbidi)ofanyinputunicodes.
*/ static hb_set_t
_unicode_closure (const hb_set_t* unicodes, bool bidi_closure) { // TODO: we may want to also consider pulling in reachable unicode composition and decompositions. // see: https://github.com/harfbuzz/harfbuzz/issues/2283
hb_set_t out = *unicodes; if (!bidi_closure) return out;
if (out.is_inverted()) { // don't closure inverted sets, they are asking to specifically exclude certain codepoints. // otherwise everything is already included. return out;
}
auto unicode_funcs = hb_unicode_funcs_get_default (); for (hb_codepoint_t cp : *unicodes) {
hb_codepoint_t mirror = hb_unicode_mirroring(unicode_funcs, cp); if (unlikely (mirror != cp)) {
out.add(mirror);
}
}
if (glyphs->is_empty () && unicodes.get_population () < size_threshold)
{
const hb_map_t* unicode_to_gid = nullptr; if (plan->accelerator)
unicode_to_gid = &plan->accelerator->unicode_to_gid;
// This is approach to collection is faster, but can only be used if glyphs // are not being explicitly added to the subset and the input unicodes set is // not excessively large (eg. an inverted set).
plan->unicode_to_new_gid_list.alloc (unicodes.get_population ()); if (!unicode_to_gid) {
_fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) {
hb_codepoint_t gid; if (!cmap.get_nominal_glyph (cp, &gid)) { return HB_MAP_VALUE_INVALID;
} return gid;
});
} else { // Use in memory unicode to gid map it's faster then looking up from // the map. This code is mostly duplicated from above to avoid doing // conditionals on the presence of the unicode_to_gid map each // iteration.
_fill_unicode_and_glyph_map(plan, unicodes.iter(), [&] (hb_codepoint_t cp) { return unicode_to_gid->get (cp);
});
}
} else
{ // This approach is slower, but can handle adding in glyphs to the subset and will match // them with cmap entries.
/* Add gids which where requested, but not mapped in cmap */ unsigned num_glyphs = plan->source->get_num_glyphs ();
hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID; for (; glyphs->next_range (&first, &last); )
{ if (first >= num_glyphs) break; if (last >= num_glyphs)
last = num_glyphs - 1;
plan->_glyphset_gsub.add_range (first, last);
}
}
auto &arr = plan->unicode_to_new_gid_list; if (arr.length)
{
plan->unicodes.add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
plan->_glyphset_gsub.add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
}
// Variation selectors don't have glyphs associated with them in the cmap so they will have been filtered out above // but should still be retained. Add them back here.
// However, the min and max codepoints for OS/2 should be calculated without considering variation selectors, // so record those first.
plan->os2_info.min_cmap_codepoint = plan->unicodes.get_min();
plan->os2_info.max_cmap_codepoint = plan->unicodes.get_max();
staticvoid
_populate_gids_to_retain (hb_subset_plan_t* plan,
hb_set_t* drop_tables)
{
OT::glyf_accelerator_t glyf (plan->source); #ifndef HB_NO_SUBSET_CFF // Note: we cannot use inprogress_accelerator here, since it has not been // created yet. So in case of preprocessed-face (and otherwise), we do an // extra sanitize pass here, which is not ideal.
OT::cff1::accelerator_subset_t stack_cff (plan->accelerator ? nullptr : plan->source); const OT::cff1::accelerator_subset_t *cff (plan->accelerator ? plan->accelerator->cff1_accel.get () : &stack_cff); #endif
staticbool
_create_old_gid_to_new_gid_map (const hb_face_t *face, bool retain_gids, const hb_set_t *all_gids_to_retain, const hb_map_t *requested_glyph_map,
hb_map_t *glyph_map, /* OUT */
hb_map_t *reverse_glyph_map, /* OUT */
hb_sorted_vector_t<hb_codepoint_pair_t> *new_to_old_gid_list /* OUT */, unsignedint *num_glyphs /* OUT */)
{ unsigned pop = all_gids_to_retain->get_population ();
reverse_glyph_map->alloc (pop);
glyph_map->alloc (pop);
new_to_old_gid_list->alloc (pop);
if (*requested_glyph_map)
{
hb_set_t new_gids(requested_glyph_map->values()); if (new_gids.get_population() != requested_glyph_map->get_population())
{
DEBUG_MSG (SUBSET, nullptr, "The provided custom glyph mapping is not unique."); returnfalse;
}
if (retain_gids)
{
DEBUG_MSG (SUBSET, nullptr, "HB_SUBSET_FLAGS_RETAIN_GIDS cannot be set if " "a custom glyph mapping has been provided."); returnfalse;
}
// Anything that wasn't mapped by the requested mapping should // be placed after the requested mapping. for (auto old_gid : remaining)
new_to_old_gid_list->push (hb_pair (++max_glyph, old_gid));
#ifdef HB_EXPERIMENTAL_API if ((input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS) &&
(input->flags & HB_SUBSET_FLAGS_RETAIN_NUM_GLYPHS)) { // We've been requested to maintain the num glyphs count from the // input face.
_num_output_glyphs = source->get_num_glyphs ();
} #endif
// Now that we have old to new gid map update the unicode to new gid list. for (unsigned i = 0; i < unicode_to_new_gid_list.length; i++)
{ // Use raw array access for performance.
unicode_to_new_gid_list.arrayZ[i].second =
glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
}
bounds_width_vec.resize_dirty (_num_output_glyphs); for (auto &v : bounds_width_vec)
v = 0xFFFFFFFF;
bounds_height_vec.resize_dirty (_num_output_glyphs); for (auto &v : bounds_height_vec)
v = 0xFFFFFFFF;
#ifndef HB_NO_SUBSET_LAYOUT if (!drop_tables.has (HB_OT_TAG_GDEF))
remap_used_mark_sets (this, used_mark_sets_map); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.