[subset] support option --layout-features
This commit is contained in:
parent
0989b5553a
commit
cb5a6b5a27
|
@ -48,12 +48,14 @@ hb_subset_input_create_or_fail ()
|
||||||
hb_set_add_range (input->name_ids, 0, 6);
|
hb_set_add_range (input->name_ids, 0, 6);
|
||||||
input->name_languages = hb_set_create ();
|
input->name_languages = hb_set_create ();
|
||||||
hb_set_add (input->name_languages, 0x0409);
|
hb_set_add (input->name_languages, 0x0409);
|
||||||
|
input->layout_features = hb_set_create ();
|
||||||
input->drop_tables = hb_set_create ();
|
input->drop_tables = hb_set_create ();
|
||||||
input->drop_hints = false;
|
input->drop_hints = false;
|
||||||
input->desubroutinize = false;
|
input->desubroutinize = false;
|
||||||
input->retain_gids = false;
|
input->retain_gids = false;
|
||||||
input->name_legacy = false;
|
input->name_legacy = false;
|
||||||
input->overlaps_flag = false;
|
input->overlaps_flag = false;
|
||||||
|
input->retain_all_layout_features = false;
|
||||||
|
|
||||||
hb_tag_t default_drop_tables[] = {
|
hb_tag_t default_drop_tables[] = {
|
||||||
// Layout disabled by default
|
// Layout disabled by default
|
||||||
|
@ -82,6 +84,94 @@ hb_subset_input_create_or_fail ()
|
||||||
|
|
||||||
input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
|
input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
|
||||||
|
|
||||||
|
//copied from _layout_features_groups in fonttools
|
||||||
|
hb_tag_t default_layout_features[] = {
|
||||||
|
// default shaper
|
||||||
|
// common
|
||||||
|
HB_TAG ('r', 'v', 'r', 'n'),
|
||||||
|
HB_TAG ('c', 'c', 'm', 'p'),
|
||||||
|
HB_TAG ('l', 'i', 'g', 'a'),
|
||||||
|
HB_TAG ('l', 'o', 'c', 'l'),
|
||||||
|
HB_TAG ('m', 'a', 'r', 'k'),
|
||||||
|
HB_TAG ('m', 'k', 'm', 'k'),
|
||||||
|
HB_TAG ('r', 'l', 'i', 'g'),
|
||||||
|
|
||||||
|
//fractions
|
||||||
|
HB_TAG ('f', 'r', 'a', 'c'),
|
||||||
|
HB_TAG ('n', 'u', 'm', 'r'),
|
||||||
|
HB_TAG ('d', 'n', 'o', 'm'),
|
||||||
|
|
||||||
|
//horizontal
|
||||||
|
HB_TAG ('c', 'a', 'l', 't'),
|
||||||
|
HB_TAG ('c', 'l', 'i', 'g'),
|
||||||
|
HB_TAG ('c', 'u', 'r', 's'),
|
||||||
|
HB_TAG ('k', 'e', 'r', 'n'),
|
||||||
|
HB_TAG ('r', 'c', 'l', 't'),
|
||||||
|
|
||||||
|
//vertical
|
||||||
|
HB_TAG ('v', 'a', 'l', 't'),
|
||||||
|
HB_TAG ('v', 'e', 'r', 't'),
|
||||||
|
HB_TAG ('v', 'k', 'r', 'n'),
|
||||||
|
HB_TAG ('v', 'p', 'a', 'l'),
|
||||||
|
HB_TAG ('v', 'r', 't', '2'),
|
||||||
|
|
||||||
|
//ltr
|
||||||
|
HB_TAG ('l', 't', 'r', 'a'),
|
||||||
|
HB_TAG ('l', 't', 'r', 'm'),
|
||||||
|
|
||||||
|
//rtl
|
||||||
|
HB_TAG ('r', 't', 'l', 'a'),
|
||||||
|
HB_TAG ('r', 't', 'l', 'm'),
|
||||||
|
|
||||||
|
//Complex shapers
|
||||||
|
//arabic
|
||||||
|
HB_TAG ('i', 'n', 'i', 't'),
|
||||||
|
HB_TAG ('m', 'e', 'd', 'i'),
|
||||||
|
HB_TAG ('f', 'i', 'n', 'a'),
|
||||||
|
HB_TAG ('i', 's', 'o', 'l'),
|
||||||
|
HB_TAG ('m', 'e', 'd', '2'),
|
||||||
|
HB_TAG ('f', 'i', 'n', '2'),
|
||||||
|
HB_TAG ('f', 'i', 'n', '3'),
|
||||||
|
HB_TAG ('c', 's', 'w', 'h'),
|
||||||
|
HB_TAG ('m', 's', 'e', 't'),
|
||||||
|
HB_TAG ('s', 't', 'c', 'h'),
|
||||||
|
|
||||||
|
//hangul
|
||||||
|
HB_TAG ('l', 'j', 'm', 'o'),
|
||||||
|
HB_TAG ('v', 'j', 'm', 'o'),
|
||||||
|
HB_TAG ('t', 'j', 'm', 'o'),
|
||||||
|
|
||||||
|
//tibetan
|
||||||
|
HB_TAG ('a', 'b', 'v', 's'),
|
||||||
|
HB_TAG ('b', 'l', 'w', 's'),
|
||||||
|
HB_TAG ('a', 'b', 'v', 'm'),
|
||||||
|
HB_TAG ('b', 'l', 'w', 'm'),
|
||||||
|
|
||||||
|
//indic
|
||||||
|
HB_TAG ('n', 'u', 'k', 't'),
|
||||||
|
HB_TAG ('a', 'k', 'h', 'n'),
|
||||||
|
HB_TAG ('r', 'p', 'h', 'f'),
|
||||||
|
HB_TAG ('r', 'k', 'r', 'f'),
|
||||||
|
HB_TAG ('p', 'r', 'e', 'f'),
|
||||||
|
HB_TAG ('b', 'l', 'w', 'f'),
|
||||||
|
HB_TAG ('h', 'a', 'l', 'f'),
|
||||||
|
HB_TAG ('a', 'b', 'v', 'f'),
|
||||||
|
HB_TAG ('p', 's', 't', 'f'),
|
||||||
|
HB_TAG ('c', 'f', 'a', 'r'),
|
||||||
|
HB_TAG ('v', 'a', 't', 'u'),
|
||||||
|
HB_TAG ('c', 'j', 'c', 't'),
|
||||||
|
HB_TAG ('i', 'n', 'i', 't'),
|
||||||
|
HB_TAG ('p', 'r', 'e', 's'),
|
||||||
|
HB_TAG ('a', 'b', 'v', 's'),
|
||||||
|
HB_TAG ('b', 'l', 'w', 's'),
|
||||||
|
HB_TAG ('p', 's', 't', 's'),
|
||||||
|
HB_TAG ('h', 'a', 'l', 'n'),
|
||||||
|
HB_TAG ('d', 'i', 's', 't'),
|
||||||
|
HB_TAG ('a', 'b', 'v', 'm'),
|
||||||
|
HB_TAG ('b', 'l', 'w', 'm'),
|
||||||
|
};
|
||||||
|
|
||||||
|
input->layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +207,7 @@ hb_subset_input_destroy (hb_subset_input_t *subset_input)
|
||||||
hb_set_destroy (subset_input->name_ids);
|
hb_set_destroy (subset_input->name_ids);
|
||||||
hb_set_destroy (subset_input->name_languages);
|
hb_set_destroy (subset_input->name_languages);
|
||||||
hb_set_destroy (subset_input->drop_tables);
|
hb_set_destroy (subset_input->drop_tables);
|
||||||
|
hb_set_destroy (subset_input->layout_features);
|
||||||
|
|
||||||
free (subset_input);
|
free (subset_input);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,14 @@ struct hb_subset_input_t
|
||||||
hb_set_t *name_ids;
|
hb_set_t *name_ids;
|
||||||
hb_set_t *name_languages;
|
hb_set_t *name_languages;
|
||||||
hb_set_t *drop_tables;
|
hb_set_t *drop_tables;
|
||||||
|
hb_set_t *layout_features;
|
||||||
|
|
||||||
bool drop_hints;
|
bool drop_hints;
|
||||||
bool desubroutinize;
|
bool desubroutinize;
|
||||||
bool retain_gids;
|
bool retain_gids;
|
||||||
bool name_legacy;
|
bool name_legacy;
|
||||||
bool overlaps_flag;
|
bool overlaps_flag;
|
||||||
|
bool retain_all_layout_features;
|
||||||
/* TODO
|
/* TODO
|
||||||
*
|
*
|
||||||
* features
|
* features
|
||||||
|
|
|
@ -85,88 +85,96 @@ _remap_indexes (const hb_set_t *indexes,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_SUBSET_LAYOUT
|
#ifndef HB_NO_SUBSET_LAYOUT
|
||||||
static inline void
|
typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
|
||||||
_gsub_closure_glyphs_lookups_features (hb_face_t *face,
|
|
||||||
hb_set_t *gids_to_retain,
|
static void _collect_subset_layout (hb_face_t *face,
|
||||||
hb_map_t *gsub_lookups,
|
hb_tag_t table_tag,
|
||||||
hb_map_t *gsub_features,
|
const hb_set_t *layout_features_to_retain,
|
||||||
script_langsys_map *gsub_langsys)
|
bool retain_all_features,
|
||||||
|
layout_collect_func_t layout_collect_func,
|
||||||
|
hb_set_t *lookup_indices /* OUT */)
|
||||||
{
|
{
|
||||||
|
if (retain_all_features)
|
||||||
|
{
|
||||||
|
layout_collect_func (face,
|
||||||
|
table_tag,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
lookup_indices);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hb_set_is_empty (layout_features_to_retain)) return;
|
||||||
|
unsigned num = layout_features_to_retain->get_population () + 1;
|
||||||
|
hb_tag_t *features = (hb_tag_t *) malloc (num * sizeof (hb_tag_t));
|
||||||
|
if (!features) return;
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
for (hb_tag_t f : layout_features_to_retain->iter ())
|
||||||
|
features[i++] = f;
|
||||||
|
|
||||||
|
features[i] = 0;
|
||||||
|
|
||||||
|
layout_collect_func (face,
|
||||||
|
table_tag,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
features,
|
||||||
|
lookup_indices);
|
||||||
|
|
||||||
|
free (features);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline void
|
||||||
|
_closure_glyphs_lookups_features (hb_face_t *face,
|
||||||
|
hb_set_t *gids_to_retain,
|
||||||
|
const hb_set_t *layout_features_to_retain,
|
||||||
|
bool retain_all_features,
|
||||||
|
hb_map_t *lookups,
|
||||||
|
hb_map_t *features,
|
||||||
|
script_langsys_map *langsys_map)
|
||||||
|
{
|
||||||
|
hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
|
||||||
|
hb_tag_t table_tag = table->tableTag;
|
||||||
hb_set_t lookup_indices;
|
hb_set_t lookup_indices;
|
||||||
hb_ot_layout_collect_lookups (face,
|
_collect_subset_layout (face,
|
||||||
HB_OT_TAG_GSUB,
|
table_tag,
|
||||||
nullptr,
|
layout_features_to_retain,
|
||||||
nullptr,
|
retain_all_features,
|
||||||
nullptr,
|
hb_ot_layout_collect_lookups,
|
||||||
&lookup_indices);
|
&lookup_indices);
|
||||||
hb_ot_layout_lookups_substitute_closure (face,
|
|
||||||
&lookup_indices,
|
if (table_tag == HB_OT_TAG_GSUB)
|
||||||
gids_to_retain);
|
hb_ot_layout_lookups_substitute_closure (face,
|
||||||
hb_blob_ptr_t<OT::GSUB> gsub = hb_sanitize_context_t ().reference_table<OT::GSUB> (face);
|
&lookup_indices,
|
||||||
gsub->closure_lookups (face,
|
gids_to_retain);
|
||||||
gids_to_retain,
|
table->closure_lookups (face,
|
||||||
|
gids_to_retain,
|
||||||
&lookup_indices);
|
&lookup_indices);
|
||||||
_remap_indexes (&lookup_indices, gsub_lookups);
|
_remap_indexes (&lookup_indices, lookups);
|
||||||
|
|
||||||
// Collect and prune features
|
// Collect and prune features
|
||||||
hb_set_t feature_indices;
|
hb_set_t feature_indices;
|
||||||
hb_ot_layout_collect_features (face,
|
_collect_subset_layout (face,
|
||||||
HB_OT_TAG_GSUB,
|
table_tag,
|
||||||
nullptr,
|
layout_features_to_retain,
|
||||||
nullptr,
|
retain_all_features,
|
||||||
nullptr,
|
hb_ot_layout_collect_features,
|
||||||
&feature_indices);
|
&feature_indices);
|
||||||
|
|
||||||
gsub->prune_features (gsub_lookups, &feature_indices);
|
table->prune_features (lookups, &feature_indices);
|
||||||
hb_map_t duplicate_feature_map;
|
hb_map_t duplicate_feature_map;
|
||||||
gsub->find_duplicate_features (gsub_lookups, &feature_indices, &duplicate_feature_map);
|
table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map);
|
||||||
|
|
||||||
feature_indices.clear ();
|
feature_indices.clear ();
|
||||||
gsub->prune_langsys (&duplicate_feature_map, gsub_langsys, &feature_indices);
|
table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices);
|
||||||
_remap_indexes (&feature_indices, gsub_features);
|
_remap_indexes (&feature_indices, features);
|
||||||
|
|
||||||
gsub.destroy ();
|
table.destroy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
_gpos_closure_lookups_features (hb_face_t *face,
|
|
||||||
const hb_set_t *gids_to_retain,
|
|
||||||
hb_map_t *gpos_lookups,
|
|
||||||
hb_map_t *gpos_features,
|
|
||||||
script_langsys_map *gpos_langsys)
|
|
||||||
{
|
|
||||||
hb_set_t lookup_indices;
|
|
||||||
hb_ot_layout_collect_lookups (face,
|
|
||||||
HB_OT_TAG_GPOS,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
&lookup_indices);
|
|
||||||
hb_blob_ptr_t<OT::GPOS> gpos = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
|
|
||||||
gpos->closure_lookups (face,
|
|
||||||
gids_to_retain,
|
|
||||||
&lookup_indices);
|
|
||||||
_remap_indexes (&lookup_indices, gpos_lookups);
|
|
||||||
|
|
||||||
// Collect and prune features
|
|
||||||
hb_set_t feature_indices;
|
|
||||||
hb_ot_layout_collect_features (face,
|
|
||||||
HB_OT_TAG_GPOS,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
&feature_indices);
|
|
||||||
|
|
||||||
gpos->prune_features (gpos_lookups, &feature_indices);
|
|
||||||
hb_map_t duplicate_feature_map;
|
|
||||||
gpos->find_duplicate_features (gpos_lookups, &feature_indices, &duplicate_feature_map);
|
|
||||||
|
|
||||||
feature_indices.clear ();
|
|
||||||
gpos->prune_langsys (&duplicate_feature_map, gpos_langsys, &feature_indices);
|
|
||||||
_remap_indexes (&feature_indices, gpos_features);
|
|
||||||
|
|
||||||
gpos.destroy ();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
|
@ -265,10 +273,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
#ifndef HB_NO_SUBSET_LAYOUT
|
#ifndef HB_NO_SUBSET_LAYOUT
|
||||||
if (close_over_gsub)
|
if (close_over_gsub)
|
||||||
// closure all glyphs/lookups/features needed for GSUB substitutions.
|
// closure all glyphs/lookups/features needed for GSUB substitutions.
|
||||||
_gsub_closure_glyphs_lookups_features (plan->source, plan->_glyphset_gsub, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys);
|
_closure_glyphs_lookups_features<OT::GSUB> (plan->source, plan->_glyphset_gsub, plan->layout_features, plan->retain_all_layout_features, plan->gsub_lookups, plan->gsub_features, plan->gsub_langsys);
|
||||||
|
|
||||||
if (close_over_gpos)
|
if (close_over_gpos)
|
||||||
_gpos_closure_lookups_features (plan->source, plan->_glyphset_gsub, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys);
|
_closure_glyphs_lookups_features<OT::GPOS> (plan->source, plan->_glyphset_gsub, plan->layout_features, plan->retain_all_layout_features, plan->gpos_lookups, plan->gpos_features, plan->gpos_langsys);
|
||||||
#endif
|
#endif
|
||||||
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||||
|
|
||||||
|
@ -393,10 +401,12 @@ hb_subset_plan_create (hb_face_t *face,
|
||||||
plan->retain_gids = input->retain_gids;
|
plan->retain_gids = input->retain_gids;
|
||||||
plan->name_legacy = input->name_legacy;
|
plan->name_legacy = input->name_legacy;
|
||||||
plan->overlaps_flag = input->overlaps_flag;
|
plan->overlaps_flag = input->overlaps_flag;
|
||||||
|
plan->retain_all_layout_features = input->retain_all_layout_features;
|
||||||
plan->unicodes = hb_set_create ();
|
plan->unicodes = hb_set_create ();
|
||||||
plan->name_ids = hb_set_reference (input->name_ids);
|
plan->name_ids = hb_set_reference (input->name_ids);
|
||||||
_nameid_closure (face, plan->name_ids);
|
_nameid_closure (face, plan->name_ids);
|
||||||
plan->name_languages = hb_set_reference (input->name_languages);
|
plan->name_languages = hb_set_reference (input->name_languages);
|
||||||
|
plan->layout_features = hb_set_reference (input->layout_features);
|
||||||
plan->glyphs_requested = hb_set_reference (input->glyphs);
|
plan->glyphs_requested = hb_set_reference (input->glyphs);
|
||||||
plan->drop_tables = hb_set_reference (input->drop_tables);
|
plan->drop_tables = hb_set_reference (input->drop_tables);
|
||||||
plan->source = hb_face_reference (face);
|
plan->source = hb_face_reference (face);
|
||||||
|
@ -456,6 +466,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
||||||
hb_set_destroy (plan->unicodes);
|
hb_set_destroy (plan->unicodes);
|
||||||
hb_set_destroy (plan->name_ids);
|
hb_set_destroy (plan->name_ids);
|
||||||
hb_set_destroy (plan->name_languages);
|
hb_set_destroy (plan->name_languages);
|
||||||
|
hb_set_destroy (plan->layout_features);
|
||||||
hb_set_destroy (plan->glyphs_requested);
|
hb_set_destroy (plan->glyphs_requested);
|
||||||
hb_set_destroy (plan->drop_tables);
|
hb_set_destroy (plan->drop_tables);
|
||||||
hb_face_destroy (plan->source);
|
hb_face_destroy (plan->source);
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct hb_subset_plan_t
|
||||||
bool retain_gids : 1;
|
bool retain_gids : 1;
|
||||||
bool name_legacy : 1;
|
bool name_legacy : 1;
|
||||||
bool overlaps_flag : 1;
|
bool overlaps_flag : 1;
|
||||||
|
bool retain_all_layout_features : 1;
|
||||||
|
|
||||||
// For each cp that we'd like to retain maps to the corresponding gid.
|
// For each cp that we'd like to retain maps to the corresponding gid.
|
||||||
hb_set_t *unicodes;
|
hb_set_t *unicodes;
|
||||||
|
@ -55,6 +56,9 @@ struct hb_subset_plan_t
|
||||||
// name_languages we would like to retain
|
// name_languages we would like to retain
|
||||||
hb_set_t *name_languages;
|
hb_set_t *name_languages;
|
||||||
|
|
||||||
|
//layout features which will be preserved
|
||||||
|
hb_set_t *layout_features;
|
||||||
|
|
||||||
//glyph ids requested to retain
|
//glyph ids requested to retain
|
||||||
hb_set_t *glyphs_requested;
|
hb_set_t *glyphs_requested;
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue