[subset] Add hb_subset_cff_get_glyph_cid() Exposes cff1::glyph_to_sid() Subsetting preserves the CIDs of the input font, so the glyph indices of a subset font are generally not its CIDs. Consumers that address glyphs by CID need this mapping, e.g. PDF producers embedding the subset as a CIDFontType0 font, where CIDs are mapped to glyphs through the charset.
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 29e578f..6b43394 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt
@@ -991,6 +991,7 @@ hb_subset_plan_new_to_old_glyph_mapping hb_subset_plan_old_to_new_glyph_mapping hb_subset_preprocess +hb_subset_cff_get_glyph_cid hb_subset_flags_t hb_subset_input_t hb_subset_sets_t
diff --git a/src/hb-subset-table-cff.cc b/src/hb-subset-table-cff.cc index 12d3888..7ceeb1b 100644 --- a/src/hb-subset-table-cff.cc +++ b/src/hb-subset-table-cff.cc
@@ -39,6 +39,35 @@ } +#ifndef HB_NO_CFF +/** + * hb_subset_cff_get_glyph_cid: + * @face: A face object + * @glyph: The glyph index to get the CID of + * @cid: (out): The CID of @glyph + * + * Fetches the CID of the specified glyph from the charset of @face's `CFF ` + * table, if the font is CID-keyed. + * + * Return value: `true` if @face is CID-keyed and @glyph is valid, `false` + * otherwise + * + * XSince: REPLACEME + **/ +hb_bool_t +hb_subset_cff_get_glyph_cid (hb_face_t *face, + hb_codepoint_t glyph, + hb_codepoint_t *cid) +{ + auto &cff = *face->table.cff1; + if (unlikely (!cff.is_valid () || !cff.is_CID () || glyph >= cff.num_glyphs)) + return false; + + *cid = cff.glyph_to_sid (glyph); + return true; +} +#endif + #ifdef HB_EXPERIMENTAL_API #ifndef HB_NO_CFF
diff --git a/src/hb-subset.h b/src/hb-subset.h index 6f62327..84ad9eb 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h
@@ -258,6 +258,11 @@ hb_subset_cff2_get_charstrings_index (hb_face_t* face); #endif +HB_EXTERN hb_bool_t +hb_subset_cff_get_glyph_cid (hb_face_t *face, + hb_codepoint_t glyph, + hb_codepoint_t *cid); + HB_EXTERN hb_face_t * hb_subset_preprocess (hb_face_t *source);
diff --git a/test/api/test-subset-cff1.c b/test/api/test-subset-cff1.c index f6a79a9..f6c406d 100644 --- a/test/api/test-subset-cff1.c +++ b/test/api/test-subset-cff1.c
@@ -336,6 +336,62 @@ hb_face_destroy (face_41_4c2e); } +static void +test_subset_cff1_get_glyph_cid (void) +{ + hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf"); + hb_codepoint_t cid = (hb_codepoint_t) -1; + + g_assert_true (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e, 0, &cid)); + g_assert_cmpuint (cid, ==, 0); + g_assert_true (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e, 1, &cid)); + g_assert_cmpuint (cid, ==, 34); + g_assert_true (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e, 2, &cid)); + g_assert_cmpuint (cid, ==, 1453); + g_assert_true (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e, 3, &cid)); + g_assert_cmpuint (cid, ==, 9407); + + /* Out of range glyph */ + g_assert_false (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e, 5, &cid)); + + hb_face_destroy (face_41_3041_4c2e); +} + +static void +test_subset_cff1_get_glyph_cid_subset (void) +{ + hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf"); + + hb_set_t *codepoints = hb_set_create (); + hb_face_t *face_41_3041_4c2e_subset; + hb_codepoint_t cid = (hb_codepoint_t) -1; + hb_set_add (codepoints, 0x4C2E); + face_41_3041_4c2e_subset + = hb_subset_test_create_subset (face_41_3041_4c2e, hb_subset_test_create_input (codepoints)); + hb_set_destroy (codepoints); + + /* U+4C2E is glyph 3 in the original font and glyph 1 in the subset, the CID + * remains the same. */ + g_assert_true (hb_subset_cff_get_glyph_cid (face_41_3041_4c2e_subset, 1, &cid)); + g_assert_cmpuint (cid, ==, 9407); + + hb_face_destroy (face_41_3041_4c2e_subset); + hb_face_destroy (face_41_3041_4c2e); +} + +static void +test_subset_cff1_get_glyph_cid_name_keyed (void) +{ + hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf"); + hb_codepoint_t cid = (hb_codepoint_t) -1; + + /* Not a CID-keyed font */ + g_assert_false (hb_subset_cff_get_glyph_cid (face_abc, 0, &cid)); + g_assert_false (hb_subset_cff_get_glyph_cid (face_abc, 1, &cid)); + + hb_face_destroy (face_abc); +} + #ifdef HB_EXPERIMENTAL_API static void test_subset_cff1_iftb_requirements (void) @@ -383,6 +439,9 @@ hb_test_add (test_subset_cff1_dotsection); hb_test_add (test_subset_cff1_retaingids); hb_test_add (test_subset_cff1_j_retaingids); + hb_test_add (test_subset_cff1_get_glyph_cid); + hb_test_add (test_subset_cff1_get_glyph_cid_subset); + hb_test_add (test_subset_cff1_get_glyph_cid_name_keyed); #ifdef HB_EXPERIMENTAL_API hb_test_add (test_subset_cff1_iftb_requirements);