[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);