Merge pull request #3429 from harfbuzz/external_plan

[subset] expose subset plan in public subsetting API
This commit is contained in:
Behdad Esfahbod 2022-02-24 12:55:01 -07:00 committed by GitHub
commit 222301bfa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 236 additions and 30 deletions

View File

@ -458,7 +458,7 @@ _nameid_closure (hb_face_t *face,
} }
/** /**
* hb_subset_plan_create: * hb_subset_plan_create_or_fail:
* @face: font face to create the plan for. * @face: font face to create the plan for.
* @input: a #hb_subset_input_t input. * @input: a #hb_subset_input_t input.
* *
@ -467,17 +467,18 @@ _nameid_closure (hb_face_t *face,
* which tables and glyphs should be retained. * which tables and glyphs should be retained.
* *
* Return value: (transfer full): New subset plan. Destroy with * Return value: (transfer full): New subset plan. Destroy with
* hb_subset_plan_destroy(). * hb_subset_plan_destroy(). If there is a failure creating the plan
* nullptr will be returned.
* *
* Since: 1.7.5 * Since: REPLACEME
**/ **/
hb_subset_plan_t * hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face, hb_subset_plan_create_or_fail (hb_face_t *face,
const hb_subset_input_t *input) const hb_subset_input_t *input)
{ {
hb_subset_plan_t *plan; hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ()))) if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t)); return nullptr;
plan->successful = true; plan->successful = true;
plan->flags = input->flags; plan->flags = input->flags;
@ -514,8 +515,9 @@ hb_subset_plan_create (hb_face_t *face,
plan->layout_variation_indices = hb_set_create (); plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create (); plan->layout_variation_idx_map = hb_map_create ();
if (plan->in_error ()) { if (unlikely (plan->in_error ())) {
return plan; hb_subset_plan_destroy (plan);
return nullptr;
} }
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan); _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
@ -532,6 +534,10 @@ hb_subset_plan_create (hb_face_t *face,
plan->reverse_glyph_map, plan->reverse_glyph_map,
&plan->_num_output_glyphs); &plan->_num_output_glyphs);
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
}
return plan; return plan;
} }
@ -542,7 +548,7 @@ hb_subset_plan_create (hb_face_t *face,
* Decreases the reference count on @plan, and if it reaches zero, destroys * Decreases the reference count on @plan, and if it reaches zero, destroys
* @plan, freeing all memory. * @plan, freeing all memory.
* *
* Since: 1.7.5 * Since: REPLACEME
**/ **/
void void
hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_subset_plan_destroy (hb_subset_plan_t *plan)
@ -596,3 +602,108 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_free (plan); hb_free (plan);
} }
/**
* hb_subset_plan_old_to_new_glyph_mapping:
* @plan: a subsetting plan.
*
* Return value:
* the mapping between glyphs in the original font to glyphs
* in the subset that will be produced by @plan.
*
* Since: REPLACEME
**/
const hb_map_t*
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->glyph_map;
}
/**
* hb_subset_plan_old_to_new_glyph_mapping:
* @plan: a subsetting plan.
*
* Returns the mapping between glyphs in the subset that will be produced by
* @plan and the glyph in the original font.
*
* Since: REPLACEME
**/
const hb_map_t*
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->reverse_glyph_map;
}
/**
* hb_subset_plan_old_to_new_glyph_mapping:
* @plan: a subsetting plan.
*
* Returns the mapping between codepoints in the original font and the
* associated glyph id in the original font.
*
* Since: REPLACEME
**/
const hb_map_t*
hb_subset_plan_codepoint_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->codepoint_to_glyph;
}
/**
* hb_subset_plan_reference: (skip)
* @plan: a #hb_subset_plan_t object.
*
* Increases the reference count on @plan.
*
* Return value: @plan.
*
* Since: REPLACEME
**/
hb_subset_plan_t *
hb_subset_plan_reference (hb_subset_plan_t *plan)
{
return hb_object_reference (plan);
}
/**
* hb_subset_plan_set_user_data: (skip)
* @plan: a #hb_subset_plan_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 plan object.
*
* Return value: %true if success, %false otherwise
*
* Since: REPLACEME
**/
hb_bool_t
hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
hb_user_data_key_t *key,
void *data,
hb_destroy_func_t destroy,
hb_bool_t replace)
{
return hb_object_set_user_data (plan, key, data, destroy, replace);
}
/**
* hb_subset_plan_get_user_data: (skip)
* @plan: a #hb_subset_plan_t object.
* @key: The user-data key to query
*
* Fetches the user data associated with the specified key,
* attached to the specified subset plan object.
*
* Return value: (transfer none): A pointer to the user data
*
* Since: REPLACEME
**/
void *
hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (plan, key);
}

View File

@ -198,13 +198,4 @@ struct hb_subset_plan_t
} }
}; };
typedef struct hb_subset_plan_t hb_subset_plan_t;
HB_INTERNAL hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face,
const hb_subset_input_t *input);
HB_INTERNAL void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
#endif /* HB_SUBSET_PLAN_HH */ #endif /* HB_SUBSET_PLAN_HH */

View File

@ -343,9 +343,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{ {
if (unlikely (!input || !source)) return hb_face_get_empty (); if (unlikely (!input || !source)) return hb_face_get_empty ();
hb_subset_plan_t *plan = hb_subset_plan_create (source, input); hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
if (unlikely (plan->in_error ())) { if (unlikely (!plan)) {
return nullptr;
}
hb_face_t * result = hb_subset_plan_execute_or_fail (plan);
hb_subset_plan_destroy (plan); hb_subset_plan_destroy (plan);
return result;
}
/**
* hb_subset_plan_execute_or_fail:
* @plan: a subsetting plan.
*
* Executes the provided subsetting @plan.
*
* Return value:
* on success returns a reference to generated font subset. If the subsetting operation fails
* returns nullptr.
*
* Since: REPLACEME
**/
hb_face_t *
hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
{
if (unlikely (!plan || plan->in_error ())) {
return nullptr; return nullptr;
} }
@ -353,7 +377,7 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
bool success = true; bool success = true;
hb_tag_t table_tags[32]; hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables)) while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
{ {
for (unsigned i = 0; i < num_tables; ++i) for (unsigned i = 0; i < num_tables; ++i)
{ {
@ -367,8 +391,5 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
} }
end: end:
hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr; return success ? hb_face_reference (plan->dest) : nullptr;
hb_subset_plan_destroy (plan);
return result;
} }

View File

@ -39,6 +39,15 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t; typedef struct hb_subset_input_t hb_subset_input_t;
/**
* hb_subset_plan_t:
*
* Contains information about how the subset operation will be executed.
* Such as mappings from the old glyph ids to the new ones in the subset.
*/
typedef struct hb_subset_plan_t hb_subset_plan_t;
/** /**
* hb_subset_flags_t: * hb_subset_flags_t:
* @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false. * @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false.
@ -145,6 +154,41 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
HB_EXTERN hb_face_t * HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input); hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
HB_EXTERN hb_face_t *
hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan);
HB_EXTERN hb_subset_plan_t *
hb_subset_plan_create_or_fail (hb_face_t *face,
const hb_subset_input_t *input);
HB_EXTERN void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_codepoint_to_old_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN hb_subset_plan_t *
hb_subset_plan_reference (hb_subset_plan_t *plan);
HB_EXTERN hb_bool_t
hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
hb_user_data_key_t *key,
void *data,
hb_destroy_func_t destroy,
hb_bool_t replace);
HB_EXTERN void *
hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
hb_user_data_key_t *key);
HB_END_DECLS HB_END_DECLS
#endif /* HB_SUBSET_H */ #endif /* HB_SUBSET_H */

View File

@ -155,6 +155,44 @@ test_subset_sets (void)
hb_subset_input_destroy (input); hb_subset_input_destroy (input);
} }
static void
test_subset_plan (void)
{
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create();
hb_set_add (codepoints, 97);
hb_set_add (codepoints, 99);
hb_subset_input_t* input = hb_subset_test_create_input (codepoints);
hb_set_destroy (codepoints);
hb_subset_plan_t* plan = hb_subset_plan_create_or_fail (face_abc, input);
g_assert (plan);
const hb_map_t* mapping = hb_subset_plan_old_to_new_glyph_mapping (plan);
g_assert (hb_map_get (mapping, 1) == 1);
g_assert (hb_map_get (mapping, 3) == 2);
mapping = hb_subset_plan_new_to_old_glyph_mapping (plan);
g_assert (hb_map_get (mapping, 1) == 1);
g_assert (hb_map_get (mapping, 2) == 3);
mapping = hb_subset_plan_codepoint_to_old_glyph_mapping (plan);
g_assert (hb_map_get (mapping, 0x63) == 3);
hb_face_t* face_abc_subset = hb_subset_plan_execute_or_fail (plan);
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
hb_subset_input_destroy (input);
hb_subset_plan_destroy (plan);
hb_face_destroy (face_abc_subset);
hb_face_destroy (face_abc);
hb_face_destroy (face_ac);
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -165,6 +203,7 @@ main (int argc, char **argv)
hb_test_add (test_subset_crash); hb_test_add (test_subset_crash);
hb_test_add (test_subset_set_flags); hb_test_add (test_subset_set_flags);
hb_test_add (test_subset_sets); hb_test_add (test_subset_sets);
hb_test_add (test_subset_plan);
return hb_test_run(); return hb_test_run();
} }