Merge pull request #3021 from googlefonts/stable_api

[subset] update hb_subset api with final changes before going stable.
This commit is contained in:
Behdad Esfahbod 2021-07-23 12:15:15 -07:00 committed by GitHub
commit b235511ed8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 471 additions and 290 deletions

View File

@ -49,7 +49,7 @@
<ulink role="online-location" url="http://[SERVER]/libharfbuzz/index.html">http://[SERVER]/libharfbuzz/</ulink>.-->
</releaseinfo>
</partinfo>
<title>Reference manual</title>
<chapter id="core-api">
<title>Core API</title>
@ -97,6 +97,12 @@
<xi:include href="xml/hb-directwrite.xml"/>
</chapter>
<chapter id="subset-api">
<title>Subset API</title>
<xi:include href="xml/hb-subset.xml"/>
</chapter>
<!--chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>

View File

@ -706,3 +706,25 @@ hb_version
hb_version_atleast
hb_version_string
</SECTION>
<SECTION>
<FILE>hb-subset</FILE>
hb_subset_flag_t
hb_subset_input_create_or_fail
hb_subset_input_reference
hb_subset_input_destroy
hb_subset_input_set_user_data
hb_subset_input_get_user_data
hb_subset_input_unicode_set
hb_subset_input_glyph_set
hb_subset_input_nameid_set
hb_subset_input_namelangid_set
hb_subset_input_layout_features_set
hb_subset_input_set_retain_all_features
hb_subset_input_get_retain_all_features
hb_subset_input_no_subset_tables_set
hb_subset_input_drop_tables_set
hb_subset_input_get_flag
hb_subset_input_set_flag
hb_subset_or_fail
</SECTION>

View File

@ -488,6 +488,11 @@ struct hb_set_t
if (!resize (count))
return;
population = other.population;
if (!count)
// memcpy is not necessary if the vectors are zero length. This avoids possibly
// passing nullptr to memcpy.
return;
memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
}

View File

@ -50,6 +50,7 @@ hb_subset_input_create_or_fail ()
hb_set_add (input->name_languages, 0x0409);
input->layout_features = hb_set_create ();
input->drop_tables = hb_set_create ();
input->no_subset_tables = hb_set_create ();
input->drop_hints = false;
input->desubroutinize = false;
input->retain_gids = false;
@ -58,6 +59,7 @@ hb_subset_input_create_or_fail ()
input->notdef_outline = false;
input->no_prune_unicode_ranges = false;
input->retain_all_layout_features = false;
input->passthrough_unrecognized = false;
hb_tag_t default_drop_tables[] = {
// Layout disabled by default
@ -83,9 +85,24 @@ hb_subset_input_create_or_fail ()
HB_TAG ('S', 'i', 'l', 'f'),
HB_TAG ('S', 'i', 'l', 'l'),
};
input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
hb_tag_t default_no_subset_tables[] = {
HB_TAG ('a', 'v', 'a', 'r'),
HB_TAG ('f', 'v', 'a', 'r'),
HB_TAG ('g', 'a', 's', 'p'),
HB_TAG ('c', 'v', 't', ' '),
HB_TAG ('f', 'p', 'g', 'm'),
HB_TAG ('p', 'r', 'e', 'p'),
HB_TAG ('V', 'D', 'M', 'X'),
HB_TAG ('D', 'S', 'I', 'G'),
HB_TAG ('M', 'V', 'A', 'R'),
HB_TAG ('c', 'v', 'a', 'r'),
HB_TAG ('S', 'T', 'A', 'T'),
};
input->no_subset_tables->add_array (default_no_subset_tables,
ARRAY_LENGTH (default_no_subset_tables));
//copied from _layout_features_groups in fonttools
hb_tag_t default_layout_features[] = {
// default shaper
@ -179,202 +196,278 @@ hb_subset_input_create_or_fail ()
/**
* hb_subset_input_reference: (skip)
* @subset_input: a subset_input.
*
*
* @input: a #hb_subset_input_t object.
*
* Return value:
*
* Since: 1.8.0
**/
hb_subset_input_t *
hb_subset_input_reference (hb_subset_input_t *subset_input)
hb_subset_input_reference (hb_subset_input_t *input)
{
return hb_object_reference (subset_input);
return hb_object_reference (input);
}
/**
* hb_subset_input_destroy:
* @subset_input: a subset_input.
* @input: a #hb_subset_input_t object.
*
* Since: 1.8.0
**/
void
hb_subset_input_destroy (hb_subset_input_t *subset_input)
hb_subset_input_destroy (hb_subset_input_t *input)
{
if (!hb_object_destroy (subset_input)) return;
if (!hb_object_destroy (input)) return;
hb_set_destroy (subset_input->unicodes);
hb_set_destroy (subset_input->glyphs);
hb_set_destroy (subset_input->name_ids);
hb_set_destroy (subset_input->name_languages);
hb_set_destroy (subset_input->drop_tables);
hb_set_destroy (subset_input->layout_features);
hb_set_destroy (input->unicodes);
hb_set_destroy (input->glyphs);
hb_set_destroy (input->name_ids);
hb_set_destroy (input->name_languages);
hb_set_destroy (input->drop_tables);
hb_set_destroy (input->layout_features);
hb_set_destroy (input->no_subset_tables);
hb_free (subset_input);
hb_free (input);
}
/**
* hb_subset_input_unicode_set:
* @subset_input: a subset_input.
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of unicode codepoints to retain.
*
* Since: 1.8.0
**/
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *subset_input)
hb_subset_input_unicode_set (hb_subset_input_t *input)
{
return subset_input->unicodes;
return input->unicodes;
}
/**
* hb_subset_input_glyph_set:
* @subset_input: a subset_input.
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of glyph ids to retain.
*
* Since: 1.8.0
**/
HB_EXTERN hb_set_t *
hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
hb_subset_input_glyph_set (hb_subset_input_t *input)
{
return subset_input->glyphs;
}
HB_EXTERN hb_set_t *
hb_subset_input_nameid_set (hb_subset_input_t *subset_input)
{
return subset_input->name_ids;
}
HB_EXTERN hb_set_t *
hb_subset_input_namelangid_set (hb_subset_input_t *subset_input)
{
return subset_input->name_languages;
}
HB_EXTERN hb_set_t *
hb_subset_input_layout_features_set (hb_subset_input_t *subset_input)
{
return subset_input->layout_features;
}
HB_EXTERN void
hb_subset_input_set_retain_all_features (hb_subset_input_t *subset_input,
hb_bool_t value)
{
subset_input->retain_all_layout_features = value;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_all_features (hb_subset_input_t *subset_input)
{
return subset_input->retain_all_layout_features;
}
HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input)
{
return subset_input->drop_tables;
}
HB_EXTERN void
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
hb_bool_t drop_hints)
{
subset_input->drop_hints = drop_hints;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
{
return subset_input->drop_hints;
}
HB_EXTERN void
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
hb_bool_t desubroutinize)
{
subset_input->desubroutinize = desubroutinize;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
{
return subset_input->desubroutinize;
return input->glyphs;
}
/**
* hb_subset_input_set_retain_gids:
* @subset_input: a subset_input.
* @retain_gids: If true the subsetter will not renumber glyph ids.
* Since: 2.4.0
* hb_subset_input_nameid_set:
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of name ids to retain.
*
* Since: REPLACE
**/
HB_EXTERN void
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
hb_bool_t retain_gids)
HB_EXTERN hb_set_t *
hb_subset_input_nameid_set (hb_subset_input_t *input)
{
subset_input->retain_gids = retain_gids;
return input->name_ids;
}
/**
* hb_subset_input_get_retain_gids:
* Returns: value of retain_gids.
* Since: 2.4.0
* hb_subset_input_namelangid_set:
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of name language ids to retain.
*
* Since: REPLACE
**/
HB_EXTERN hb_set_t *
hb_subset_input_namelangid_set (hb_subset_input_t *input)
{
return input->name_languages;
}
/**
* hb_subset_input_layout_features_set:
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of feature tags to retain.
*
* Since: REPLACE
**/
HB_EXTERN hb_set_t *
hb_subset_input_layout_features_set (hb_subset_input_t *input)
{
return input->layout_features;
}
HB_EXTERN void
hb_subset_input_set_retain_all_features (hb_subset_input_t *input,
hb_bool_t value)
{
input->retain_all_layout_features = value;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_all_features (hb_subset_input_t *input)
{
return input->retain_all_layout_features;
}
/**
* hb_subset_input_drop_tabes_set:
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of table tags which specifies tables
* to be dropped.
*
* Since: REPLACE
**/
HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *input)
{
return input->drop_tables;
}
/**
* hb_subset_input_no_subset_tabes_set:
* @input: a #hb_subset_input_t object.
*
* Return value: pointer to the set of table tags which specifies tables
* that should not have subsetting applied to them.
*
* Since: REPLACE
**/
HB_EXTERN hb_set_t *
hb_subset_input_no_subset_tables_set (hb_subset_input_t *input)
{
return input->no_subset_tables;
}
/**
* hb_subset_input_get_flag:
* @input: a #hb_subset_input_t object.
* @flag: which flag to check.
*
* Return value: value of the specified flag.
*
* Since: REPLACE
**/
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
hb_subset_input_get_flag (hb_subset_input_t *input,
hb_subset_flag_t flag)
{
return subset_input->retain_gids;
switch (flag)
{
case HB_SUBSET_FLAG_HINTING:
return !input->drop_hints;
case HB_SUBSET_FLAG_RETAIN_GIDS:
return input->retain_gids;
case HB_SUBSET_FLAG_DESUBROUTINIZE:
return input->desubroutinize;
case HB_SUBSET_FLAG_NAME_LEGACY:
return input->name_legacy;
case HB_SUBSET_FLAG_SET_OVERLAPS_FLAG:
return input->overlaps_flag;
case HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED:
return input->passthrough_unrecognized;
case HB_SUBSET_FLAG_NOTDEF_OUTLINE:
return input->notdef_outline;
case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES:
return input->no_prune_unicode_ranges;
default:
return false;
}
}
/**
* hb_subset_input_set_flag:
* @input: a #hb_subset_input_t object.
* @flag: which flag to set.
* @value: new value for the flag.
*
* Set the specified flag to @value.
*
* Since: REPLACE
**/
HB_EXTERN void
hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
hb_bool_t name_legacy)
hb_subset_input_set_flag (hb_subset_input_t *input,
hb_subset_flag_t flag,
hb_bool_t value)
{
subset_input->name_legacy = name_legacy;
switch (flag)
{
case HB_SUBSET_FLAG_HINTING:
input->drop_hints = !value;
break;
case HB_SUBSET_FLAG_RETAIN_GIDS:
input->retain_gids = value;
break;
case HB_SUBSET_FLAG_DESUBROUTINIZE:
input->desubroutinize = value;
break;
case HB_SUBSET_FLAG_NAME_LEGACY:
input->name_legacy = value;
break;
case HB_SUBSET_FLAG_SET_OVERLAPS_FLAG:
input->overlaps_flag = value;
break;
case HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED:
input->passthrough_unrecognized = value;
break;
case HB_SUBSET_FLAG_NOTDEF_OUTLINE:
input->notdef_outline = value;
break;
case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES:
input->no_prune_unicode_ranges = value;
break;
default:
// Do nothing.
break;
}
}
HB_EXTERN hb_bool_t
hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input)
/**
* hb_subset_input_set_user_data: (skip)
* @input: a #hb_subset_input_t object.
* @key: The user-data key to set
* @data: A pointer to the user data
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the given subset input object.
*
* Return value: %true if success, %false otherwise
*
* Since: REPLACE
**/
hb_bool_t
hb_subset_input_set_user_data (hb_subset_input_t *input,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace)
{
return subset_input->name_legacy;
return hb_object_set_user_data (input, key, data, destroy, replace);
}
HB_EXTERN void
hb_subset_input_set_overlaps_flag (hb_subset_input_t *subset_input,
hb_bool_t overlaps_flag)
/**
* hb_subset_input_get_user_data: (skip)
* @input: a #hb_subset_input_t object.
* @key: The user-data key to query
*
* Fetches the user data associated with the specified key,
* attached to the specified subset input object.
*
* Return value: (transfer none): A pointer to the user data
*
* Since: REPLACE
**/
void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
hb_user_data_key_t *key)
{
subset_input->overlaps_flag = overlaps_flag;
return hb_object_get_user_data (input, key);
}
HB_EXTERN hb_bool_t
hb_subset_input_get_overlaps_flag (hb_subset_input_t *subset_input)
{
return subset_input->overlaps_flag;
}
HB_EXTERN void
hb_subset_input_set_notdef_outline (hb_subset_input_t *subset_input,
hb_bool_t notdef_outline)
{
subset_input->notdef_outline = notdef_outline;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_notdef_outline (hb_subset_input_t *subset_input)
{
return subset_input->notdef_outline;
}
HB_EXTERN void
hb_subset_input_set_no_prune_unicode_ranges (hb_subset_input_t *subset_input,
hb_bool_t no_prune_unicode_ranges)
{
subset_input->no_prune_unicode_ranges = no_prune_unicode_ranges;
}
HB_EXTERN hb_bool_t
hb_subset_input_get_no_prune_unicode_ranges (hb_subset_input_t *subset_input)
{
return subset_input->no_prune_unicode_ranges;
}

View File

@ -42,6 +42,7 @@ struct hb_subset_input_t
hb_set_t *glyphs;
hb_set_t *name_ids;
hb_set_t *name_languages;
hb_set_t *no_subset_tables;
hb_set_t *drop_tables;
hb_set_t *layout_features;
@ -54,6 +55,8 @@ struct hb_subset_input_t
hb_bool_t notdef_outline;
hb_bool_t no_prune_unicode_ranges;
hb_bool_t retain_all_layout_features;
hb_bool_t passthrough_unrecognized;
/* TODO
*
* features

View File

@ -58,7 +58,7 @@ _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
static void
_remap_palette_indexes (const hb_set_t *palette_indexes,
hb_map_t *mapping /* OUT */)
hb_map_t *mapping /* OUT */)
{
unsigned new_idx = 0;
for (unsigned palette_index : palette_indexes->iter ())
@ -87,12 +87,12 @@ _remap_indexes (const hb_set_t *indexes,
#ifndef HB_NO_SUBSET_LAYOUT
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 */);
static void _collect_subset_layout (hb_face_t *face,
hb_tag_t table_tag,
const hb_set_t *layout_features_to_retain,
bool retain_all_features,
static void _collect_subset_layout (hb_face_t *face,
hb_tag_t table_tag,
const hb_set_t *layout_features_to_retain,
bool retain_all_features,
layout_collect_func_t layout_collect_func,
hb_set_t *lookup_indices /* OUT */)
hb_set_t *lookup_indices /* OUT */)
{
if (retain_all_features)
{
@ -128,12 +128,12 @@ static void _collect_subset_layout (hb_face_t *face,
template <typename T>
static inline void
_closure_glyphs_lookups_features (hb_face_t *face,
hb_set_t *gids_to_retain,
_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,
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);
@ -208,9 +208,9 @@ static inline void
#endif
static inline void
_cmap_closure (hb_face_t *face,
const hb_set_t *unicodes,
hb_set_t *glyphset)
_cmap_closure (hb_face_t *face,
const hb_set_t *unicodes,
hb_set_t *glyphset)
{
OT::cmap::accelerator_t cmap;
cmap.init (face);
@ -341,10 +341,10 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_VAR
if (close_over_gdef)
_collect_layout_variation_indices (plan->source,
plan->_glyphset_gsub,
plan->gpos_lookups,
plan->layout_variation_indices,
plan->layout_variation_idx_map);
plan->_glyphset_gsub,
plan->gpos_lookups,
plan->layout_variation_indices,
plan->layout_variation_idx_map);
#endif
#ifndef HB_NO_SUBSET_CFF
@ -355,11 +355,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
static void
_create_old_gid_to_new_gid_map (const hb_face_t *face,
bool retain_gids,
const hb_set_t *all_gids_to_retain,
hb_map_t *glyph_map, /* OUT */
hb_map_t *reverse_glyph_map, /* OUT */
unsigned int *num_glyphs /* OUT */)
bool retain_gids,
const hb_set_t *all_gids_to_retain,
hb_map_t *glyph_map, /* OUT */
hb_map_t *reverse_glyph_map, /* OUT */
unsigned int *num_glyphs /* OUT */)
{
if (!retain_gids)
{
@ -402,6 +402,9 @@ _nameid_closure (hb_face_t *face,
/**
* hb_subset_plan_create:
* @face: font face to create the plan for.
* @input: a subset input.
*
* Computes a plan for subsetting the supplied face according
* to a provided input. The plan describes
* which tables and glyphs should be retained.
@ -411,8 +414,8 @@ _nameid_closure (hb_face_t *face,
* Since: 1.7.5
**/
hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face,
hb_subset_input_t *input)
hb_subset_plan_create (hb_face_t *face,
const hb_subset_input_t *input)
{
hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
@ -427,13 +430,15 @@ hb_subset_plan_create (hb_face_t *face,
plan->notdef_outline = input->notdef_outline;
plan->prune_unicode_ranges = !input->no_prune_unicode_ranges;
plan->retain_all_layout_features = input->retain_all_layout_features;
plan->passthrough_unrecognized = input->passthrough_unrecognized;
plan->unicodes = hb_set_create ();
plan->name_ids = hb_set_reference (input->name_ids);
plan->name_ids = hb_set_copy (input->name_ids);
_nameid_closure (face, plan->name_ids);
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->drop_tables = hb_set_reference (input->drop_tables);
plan->name_languages = hb_set_copy (input->name_languages);
plan->layout_features = hb_set_copy (input->layout_features);
plan->glyphs_requested = hb_set_copy (input->glyphs);
plan->drop_tables = hb_set_copy (input->drop_tables);
plan->no_subset_tables = hb_set_copy (input->no_subset_tables);
plan->source = hb_face_reference (face);
plan->dest = hb_face_builder_create ();
@ -496,6 +501,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_set_destroy (plan->layout_features);
hb_set_destroy (plan->glyphs_requested);
hb_set_destroy (plan->drop_tables);
hb_set_destroy (plan->no_subset_tables);
hb_face_destroy (plan->source);
hb_face_destroy (plan->dest);
hb_map_destroy (plan->codepoint_to_glyph);

View File

@ -48,6 +48,7 @@ struct hb_subset_plan_t
bool notdef_outline : 1;
bool prune_unicode_ranges : 1;
bool retain_all_layout_features : 1;
bool passthrough_unrecognized : 1;
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
@ -64,6 +65,9 @@ struct hb_subset_plan_t
//glyph ids requested to retain
hb_set_t *glyphs_requested;
// Tables which should not be processed, just pass them through.
hb_set_t *no_subset_tables;
// Tables which should be dropped.
hb_set_t *drop_tables;
@ -204,7 +208,7 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
HB_INTERNAL hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face,
hb_subset_input_t *input);
const hb_subset_input_t *input);
HB_INTERNAL void
hb_subset_plan_destroy (hb_subset_plan_t *plan);

View File

@ -53,6 +53,17 @@
#include "hb-ot-var-hvar-table.hh"
#include "hb-repacker.hh"
/**
* SECTION:hb-subset
* @title: hb-subset
* @short_description: Subsets font files.
* @include: hb-subset.h
*
* Subsetting reduces the codepoint coverage of font files and removes all data
* that is no longer needed. A subset input describes the desired subset. The input is
* provided along with a font to the subsetting operation. Output is a new font file
* containing only the data specified in the input.
*/
static unsigned
_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
@ -244,9 +255,22 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
}
}
static bool
_passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
{
hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
bool result = plan->add_table (tag, source_table);
hb_blob_destroy (source_table);
return result;
}
static bool
_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
{
if (plan->no_subset_tables->has (tag)) {
return _passthrough (plan, tag);
}
DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
switch (tag)
{
@ -288,29 +312,33 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
#endif
default:
hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
bool result = plan->add_table (tag, source_table);
hb_blob_destroy (source_table);
return result;
if (plan->passthrough_unrecognized)
return _passthrough (plan, tag);
// Drop table
return true;
}
}
/**
* hb_subset:
* hb_subset_or_fail:
* @source: font face data to be subset.
* @input: input to use for the subsetting.
*
* Subsets a font according to provided input.
* Subsets a font according to provided input. Returns nullptr
* if the subset operation fails.
*
* Since: REPLACE
**/
hb_face_t *
hb_subset (hb_face_t *source, hb_subset_input_t *input)
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return hb_face_get_empty ();
return nullptr;
}
hb_set_t tags_set;
@ -331,7 +359,7 @@ hb_subset (hb_face_t *source, hb_subset_input_t *input)
}
end:
hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr;
hb_subset_plan_destroy (plan);
return result;

View File

@ -39,88 +39,103 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t;
/**
* hb_subset_flag_t:
* @HB_SUBSET_FLAG_HINTING: If set hinting instructions will be retained in
* the produced subset. Otherwise hinting instructions will be dropped.
* Defaults to true.
* @HB_SUBSET_FLAG_RETAIN_GIDS: If set glyph indices will not be modified in
* the produced subset. If glyphs are dropped their indices will be retained
* as an empty glyph. Defaults to false.
* @HB_SUBSET_FLAG_DESUBROUTINIZE: If set and subsetting a CFF font the
* subsetter will attempt to remove subroutines from the CFF glyphs.
* Defaults to false.
* @HB_SUBSET_FLAG_NAME_LEGACY: If set non-unicode name records will be
* retained in the subset. Defaults to false.
* @HB_SUBSET_FLAG_SET_OVERLAPS_FLAG: If set the subsetter will set the
* OVERLAP_SIMPLE flag on each simple glyph. Defaults to false.
* @HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED: If set the subsetter will not
* drop unrecognized tables and instead pass them through untouched.
* Defaults to false.
* @HB_SUBSET_FLAG_NOTDEF_OUTLINE: If set the notdef glyph outline will be
* retained in the final subset. Defaults to false.
* @HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
* OS/2 will not be recalculated.
*
* List of boolean properties that can be configured on the subset input.
*
* Since: REPLACE
**/
typedef enum
{
HB_SUBSET_FLAG_HINTING = 0,
HB_SUBSET_FLAG_RETAIN_GIDS,
HB_SUBSET_FLAG_DESUBROUTINIZE,
HB_SUBSET_FLAG_NAME_LEGACY,
HB_SUBSET_FLAG_SET_OVERLAPS_FLAG,
HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED,
HB_SUBSET_FLAG_NOTDEF_OUTLINE,
HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES,
} hb_subset_flag_t;
HB_EXTERN hb_subset_input_t *
hb_subset_input_create_or_fail (void);
HB_EXTERN hb_subset_input_t *
hb_subset_input_reference (hb_subset_input_t *subset_input);
hb_subset_input_reference (hb_subset_input_t *input);
HB_EXTERN void
hb_subset_input_destroy (hb_subset_input_t *subset_input);
hb_subset_input_destroy (hb_subset_input_t *input);
HB_EXTERN hb_bool_t
hb_subset_input_set_user_data (hb_subset_input_t *input,
hb_user_data_key_t *key,
void * data,
hb_destroy_func_t destroy,
hb_bool_t replace);
HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
hb_user_data_key_t *key);
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
hb_subset_input_unicode_set (hb_subset_input_t *input);
HB_EXTERN hb_set_t *
hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
hb_subset_input_glyph_set (hb_subset_input_t *input);
HB_EXTERN hb_set_t *
hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
hb_subset_input_nameid_set (hb_subset_input_t *input);
HB_EXTERN hb_set_t *
hb_subset_input_namelangid_set (hb_subset_input_t *subset_input);
hb_subset_input_namelangid_set (hb_subset_input_t *input);
HB_EXTERN hb_set_t *
hb_subset_input_layout_features_set (hb_subset_input_t *subset_input);
hb_subset_input_layout_features_set (hb_subset_input_t *input);
HB_EXTERN void
hb_subset_input_set_retain_all_features (hb_subset_input_t *subset_input,
hb_bool_t value);
hb_subset_input_set_retain_all_features (hb_subset_input_t *input,
hb_bool_t value);
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_all_features (hb_subset_input_t *subset_input);
hb_subset_input_get_retain_all_features (hb_subset_input_t *input);
HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input);
hb_subset_input_no_subset_tables_set (hb_subset_input_t *input);
HB_EXTERN void
hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
hb_bool_t drop_hints);
HB_EXTERN hb_bool_t
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
hb_bool_t desubroutinize);
HB_EXTERN hb_bool_t
hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
hb_bool_t retain_gids);
HB_EXTERN hb_bool_t
hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_name_legacy (hb_subset_input_t *subset_input,
hb_bool_t name_legacy);
HB_EXTERN hb_bool_t
hb_subset_input_get_name_legacy (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_overlaps_flag (hb_subset_input_t *subset_input,
hb_bool_t overlaps_flag);
HB_EXTERN hb_set_t *
hb_subset_input_drop_tables_set (hb_subset_input_t *input);
HB_EXTERN hb_bool_t
hb_subset_input_get_overlaps_flag (hb_subset_input_t *subset_input);
hb_subset_input_get_flag (hb_subset_input_t *input,
hb_subset_flag_t flag);
HB_EXTERN void
hb_subset_input_set_notdef_outline (hb_subset_input_t *subset_input,
hb_bool_t notdef_outline);
hb_subset_input_set_flag (hb_subset_input_t *input,
hb_subset_flag_t flag,
hb_bool_t value);
HB_EXTERN hb_bool_t
hb_subset_input_get_notdef_outline (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_set_no_prune_unicode_ranges (hb_subset_input_t *subset_input,
hb_bool_t no_prune_unicode_ranges);
HB_EXTERN hb_bool_t
hb_subset_input_get_no_prune_unicode_ranges (hb_subset_input_t *subset_input);
/* hb_subset () */
HB_EXTERN hb_face_t *
hb_subset (hb_face_t *source, hb_subset_input_t *input);
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
HB_END_DECLS

View File

@ -75,7 +75,7 @@ hb_subset_test_create_input_from_nameids (const hb_set_t *name_ids)
hb_set_t *name_langids = hb_subset_input_namelangid_set (input);
hb_set_add_range (name_langids, 0, 0x5FFF);
hb_subset_input_set_name_legacy (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_NAME_LEGACY, true);
return input;
}
@ -83,7 +83,7 @@ static inline hb_face_t *
hb_subset_test_create_subset (hb_face_t *source,
hb_subset_input_t *input)
{
hb_face_t *subset = hb_subset (source, input);
hb_face_t *subset = hb_subset_or_fail (source, input);
g_assert (subset);
hb_subset_input_destroy (input);

View File

@ -80,7 +80,7 @@ test_subset_cff1_strip_hints (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -103,7 +103,7 @@ test_subset_cff1_desubr (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -126,8 +126,8 @@ test_subset_cff1_desubr_strip_hints (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -170,7 +170,7 @@ test_subset_cff1_j_strip_hints (void)
hb_set_add (codepoints, 0x41);
hb_set_add (codepoints, 0x4C2E);
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
hb_set_destroy (codepoints);
@ -193,7 +193,7 @@ test_subset_cff1_j_desubr (void)
hb_set_add (codepoints, 0x41);
hb_set_add (codepoints, 0x4C2E);
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
hb_set_destroy (codepoints);
@ -216,8 +216,8 @@ test_subset_cff1_j_desubr_strip_hints (void)
hb_set_add (codepoints, 0x41);
hb_set_add (codepoints, 0x4C2E);
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
hb_set_destroy (codepoints);
@ -279,7 +279,7 @@ test_subset_cff1_dotsection (void)
hb_face_t *face_test;
hb_set_add (codepoints, 0x69); /* i */
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_test = hb_subset_test_create_subset (face, input);
hb_set_destroy (codepoints);
@ -302,7 +302,7 @@ test_subset_cff1_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -325,7 +325,7 @@ test_subset_cff1_j_retaingids (void)
hb_set_add (codepoints, 0x41);
hb_set_add (codepoints, 0x4C2E);
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
hb_set_destroy (codepoints);

View File

@ -80,7 +80,7 @@ test_subset_cff2_strip_hints (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -103,7 +103,7 @@ test_subset_cff2_desubr (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -126,8 +126,8 @@ test_subset_cff2_desubr_strip_hints (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_desubroutinize (input, true);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_DESUBROUTINIZE, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -150,7 +150,7 @@ test_subset_cff2_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);

View File

@ -42,7 +42,8 @@ test_subset_drop_tables (void)
hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG ('h', 'm', 't', 'x'));
hb_set_destroy (codepoints);
hb_face_t* subset = hb_subset (face, input);
hb_face_t* subset = hb_subset_or_fail (face, input);
g_assert (subset);
hb_blob_t *hdmx = hb_face_reference_table (subset, HB_TAG ('h', 'd', 'm', 'x'));
hb_blob_t *hmtx = hb_face_reference_table (subset, HB_TAG ('h', 'm', 't', 'x'));

View File

@ -92,7 +92,7 @@ test_subset_glyf_set_overlaps_flag (void)
hb_set_add (codepoints, 508);
hb_subset_input_t* input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_overlaps_flag (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_SET_OVERLAPS_FLAG, true);
face_abcAE_subset = hb_subset_test_create_subset (face_abcAE, input);
hb_set_destroy (codepoints);
@ -239,7 +239,7 @@ test_subset_glyf_strip_hints_simple (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -263,7 +263,7 @@ test_subset_glyf_strip_hints_composite (void)
hb_face_t *face_generated_subset;
hb_set_add (codepoints, 0x1fc);
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
face_generated_subset = hb_subset_test_create_subset (face_components, input);
hb_set_destroy (codepoints);
@ -298,14 +298,13 @@ test_subset_glyf_strip_hints_invalid (void)
}
input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_drop_hints (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, false);
hb_set_destroy (codepoints);
face_subset = hb_subset_test_create_subset (face, input);
g_assert (face_subset);
g_assert (face_subset == hb_face_get_empty ());
face_subset = hb_subset_or_fail (face, input);
g_assert (!face_subset);
hb_face_destroy (face_subset);
hb_subset_input_destroy (input);
hb_face_destroy (face);
}
@ -321,7 +320,7 @@ test_subset_glyf_retain_gids (void)
hb_set_add (codepoints, 99);
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -345,7 +344,7 @@ test_subset_glyf_retain_gids_truncates (void)
hb_set_add (codepoints, 97);
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);

View File

@ -79,7 +79,7 @@ test_subset_gvar_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);

View File

@ -82,9 +82,8 @@ test_subset_hdmx_invalid (void)
hb_set_add (codepoints, 'b');
hb_set_add (codepoints, 'c');
subset = hb_subset (face, input);
g_assert (subset);
g_assert (subset == hb_face_get_empty ());
subset = hb_subset_or_fail (face, input);
g_assert (!subset);
hb_subset_input_destroy (input);
hb_face_destroy (subset);

View File

@ -162,9 +162,8 @@ test_subset_invalid_hmtx (void)
hb_set_add (codepoints, 'b');
hb_set_add (codepoints, 'c');
subset = hb_subset (face, input);
g_assert (subset);
g_assert (subset == hb_face_get_empty ());
subset = hb_subset_or_fail (face, input);
g_assert (!subset);
hb_subset_input_destroy (input);
hb_face_destroy (subset);

View File

@ -79,7 +79,7 @@ test_subset_map_HVAR_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);
@ -160,7 +160,7 @@ test_subset_identity_HVAR_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);

View File

@ -79,7 +79,7 @@ test_subset_VVAR_retaingids (void)
hb_set_add (codepoints, 'a');
hb_set_add (codepoints, 'c');
hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
hb_subset_input_set_retain_gids (input, true);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, true);
face_abc_subset = hb_subset_test_create_subset (face_abc, input);
hb_set_destroy (codepoints);

View File

@ -42,7 +42,7 @@ test_subset_32_tables (void)
hb_set_add (codepoints, 'b');
hb_set_add (codepoints, 'c');
subset = hb_subset (face, input);
subset = hb_subset_or_fail (face, input);
g_assert (subset);
g_assert (subset != hb_face_get_empty ());
@ -64,9 +64,8 @@ test_subset_no_inf_loop (void)
hb_set_add (codepoints, 'b');
hb_set_add (codepoints, 'c');
subset = hb_subset (face, input);
g_assert (subset);
g_assert (subset == hb_face_get_empty ());
subset = hb_subset_or_fail (face, input);
g_assert (!subset);
hb_subset_input_destroy (input);
hb_face_destroy (subset);
@ -86,9 +85,8 @@ test_subset_crash (void)
hb_set_add (codepoints, 'b');
hb_set_add (codepoints, 'c');
subset = hb_subset (face, input);
g_assert (subset);
g_assert (subset == hb_face_get_empty ());
subset = hb_subset_or_fail (face, input);
g_assert (!subset);
hb_subset_input_destroy (input);
hb_face_destroy (subset);

View File

@ -17,8 +17,8 @@ trySubset (hb_face_t *face,
{
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
if (!input) return;
hb_subset_input_set_drop_hints (input, drop_hints);
hb_subset_input_set_retain_gids (input, retain_gids);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_HINTING, !drop_hints);
hb_subset_input_set_flag (input, HB_SUBSET_FLAG_RETAIN_GIDS, retain_gids);
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
if (!drop_layout)
@ -31,7 +31,8 @@ trySubset (hb_face_t *face,
for (int i = 0; i < text_length; i++)
hb_set_add (codepoints, text[i]);
hb_face_t *result = hb_subset (face, input);
hb_face_t *result = hb_subset_or_fail (face, input);
if (result)
{
hb_blob_t *blob = hb_face_reference_blob (result);
unsigned int length;

View File

@ -101,16 +101,18 @@ struct subset_consumer_t
hb_face_t *new_face = nullptr;
for (unsigned i = 0; i < subset_options.num_iterations; i++) {
hb_face_destroy (new_face);
new_face = hb_subset (face, input);
new_face = hb_subset_or_fail (face, input);
}
hb_blob_t *result = hb_face_reference_blob (new_face);
failed = !hb_blob_get_length (result);
failed = !new_face;
if (!failed)
{
hb_blob_t *result = hb_face_reference_blob (new_face);
write_file (options.output_file, result);
hb_blob_destroy (result);
}
hb_subset_input_destroy (input);
hb_blob_destroy (result);
hb_face_destroy (new_face);
hb_font_destroy (font);
}