[subset] Add subset plan to public API.

Add the ability to create a subset plan which an be used to gather info on things like glyph mappings in the final subset. The plan can then be passed on to perform the subsetting operation.
This commit is contained in:
Garret Rieger 2022-02-11 12:44:58 -08:00
parent 6893723879
commit b65e48a786
5 changed files with 140 additions and 19 deletions

View File

@ -111,7 +111,7 @@ static void _collect_layout_indices (hb_face_t *face,
retain_all_features = false; retain_all_features = false;
continue; continue;
} }
if (visited_features.has (tag)) if (visited_features.has (tag))
continue; continue;
@ -249,9 +249,9 @@ static void _colr_closure (hb_face_t *face,
hb_set_t glyphset_colrv0; hb_set_t glyphset_colrv0;
for (hb_codepoint_t gid : glyphs_colred->iter ()) for (hb_codepoint_t gid : glyphs_colred->iter ())
colr.closure_glyphs (gid, &glyphset_colrv0); colr.closure_glyphs (gid, &glyphset_colrv0);
glyphs_colred->union_ (glyphset_colrv0); glyphs_colred->union_ (glyphset_colrv0);
//closure for COLRv1 //closure for COLRv1
colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices); colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES && } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
@ -469,7 +469,7 @@ _nameid_closure (hb_face_t *face,
* 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().
* *
* 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 (hb_face_t *face,
@ -542,7 +542,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 +596,48 @@ 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.
*
* Returns 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;
}

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

@ -349,11 +349,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
return nullptr; return nullptr;
} }
hb_face_t * result = hb_subset_from_plan_or_fail (plan);
hb_subset_plan_destroy (plan);
return result;
}
/**
* hb_subset_from_plan_or_fail:
* @plan: a subsetting plan.
*
* Subsets a font according to provided plan. Returns nullptr
* if the subset operation fails.
*
* Since: REPLACEME
**/
hb_face_t *
hb_subset_from_plan_or_fail (hb_subset_plan_t *plan)
{
if (unlikely (plan->in_error ())) {
return nullptr;
}
hb_set_t tags_set; hb_set_t tags_set;
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 +389,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,25 @@ 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_from_plan_or_fail (hb_subset_plan_t *plan);
HB_EXTERN hb_subset_plan_t *
hb_subset_plan_create (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_END_DECLS HB_END_DECLS
#endif /* HB_SUBSET_H */ #endif /* HB_SUBSET_H */

View File

@ -155,6 +155,43 @@ 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 (face_abc, input);
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_from_plan_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 +202,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();
} }