diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 16b662777..f98e8cc13 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -170,6 +170,7 @@ hb_coretext_font_get_ct_font
hb-face
hb_face_count
+hb_face_t
hb_face_create
hb_face_create_for_tables
hb_face_destroy
@@ -188,7 +189,8 @@ hb_face_set_glyph_count
hb_face_set_index
hb_face_set_upem
hb_face_set_user_data
-hb_face_t
+hb_face_builder_create
+hb_face_builder_add_table
@@ -226,6 +228,7 @@ hb_font_get_glyph
hb_font_get_glyph_advance_for_direction
hb_font_get_glyph_advance_func_t
hb_font_get_glyph_advances_for_direction
+hb_font_get_glyph_advances_func_t
hb_font_get_glyph_contour_point
hb_font_get_glyph_contour_point_for_origin
hb_font_get_glyph_contour_point_func_t
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 49f29d3fa..9cb0f2654 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -512,3 +512,152 @@ hb_face_get_table_tags (const hb_face_t *face,
return ot_face.get_table_tags (start_offset, table_count, table_tags);
}
+
+
+/*
+ * face-builder: A face that has add_table().
+ */
+
+struct hb_face_builder_data_t
+{
+ struct table_entry_t
+ {
+ inline int cmp (const hb_tag_t *t) const
+ {
+ if (*t < tag) return -1;
+ if (*t > tag) return -1;
+ return 0;
+ }
+
+ hb_tag_t tag;
+ hb_blob_t *blob;
+ };
+
+ hb_vector_t tables;
+};
+
+static hb_face_builder_data_t *
+_hb_face_builder_data_create (void)
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
+ if (unlikely (!data))
+ return nullptr;
+
+ data->tables.init ();
+
+ return data;
+}
+
+static void
+_hb_face_builder_data_destroy (void *user_data)
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+ for (unsigned int i = 0; i < data->tables.len; i++)
+ hb_blob_destroy (data->tables[i].blob);
+
+ data->tables.fini ();
+
+ free (data);
+}
+
+static hb_blob_t *
+_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
+{
+
+ unsigned int table_count = data->tables.len;
+ unsigned int face_length = table_count * 16 + 12;
+
+ for (unsigned int i = 0; i < table_count; i++)
+ face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables.arrayZ[i].blob));
+
+ char *buf = (char *) malloc (face_length);
+ if (unlikely (!buf))
+ return nullptr;
+
+ hb_serialize_context_t c (buf, face_length);
+ OT::OpenTypeFontFile *f = c.start_serialize ();
+
+ bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
+ hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+ Supplier tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
+ Supplier blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
+ bool ret = f->serialize_single (&c,
+ sfnt_tag,
+ tags_supplier,
+ blobs_supplier,
+ table_count);
+
+ c.end_serialize ();
+
+ if (unlikely (!ret))
+ {
+ free (buf);
+ return nullptr;
+ }
+
+ return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+}
+
+static hb_blob_t *
+_hb_face_builder_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+{
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+ if (!tag)
+ return _hb_face_builder_data_reference_blob (data);
+
+ hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
+ if (entry)
+ return hb_blob_reference (entry->blob);
+
+ return nullptr;
+}
+
+
+/**
+ * hb_face_builder_create:
+ *
+ * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
+ * After tables are added to the face, it can be compiled to a binary
+ * font file by calling hb_face_reference_blob().
+ *
+ * Return value: (transfer full) New face.
+ *
+ * Since: REPLACEME
+ **/
+hb_face_t *
+hb_face_builder_create (void)
+{
+ hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+ if (unlikely (!data)) return hb_face_get_empty ();
+
+ return hb_face_create_for_tables (_hb_face_builder_reference_table,
+ data,
+ _hb_face_builder_data_destroy);
+}
+
+/**
+ * hb_face_builder_add_table:
+ *
+ * Add table for @tag with data provided by @blob to the face. @face must
+ * be created using hb_face_builder_create().
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+{
+ if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+ return false;
+
+ hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+ hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
+
+ entry->tag = tag;
+ entry->blob = hb_blob_reference (blob);
+
+ return true;
+}
+
diff --git a/src/hb-face.h b/src/hb-face.h
index 208092efc..2bc3e8957 100644
--- a/src/hb-face.h
+++ b/src/hb-face.h
@@ -120,6 +120,20 @@ hb_face_get_table_tags (const hb_face_t *face,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */);
+
+/*
+ * Builder face.
+ */
+
+HB_EXTERN hb_face_t *
+hb_face_builder_create (void);
+
+HB_EXTERN hb_bool_t
+hb_face_builder_add_table (hb_face_t *face,
+ hb_tag_t tag,
+ hb_blob_t *blob);
+
+
HB_END_DECLS
#endif /* HB_FACE_H */
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 125668272..6e556c20b 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -154,7 +154,7 @@ hb_subset_plan_create (hb_face_t *face,
plan->unicodes = hb_set_create();
plan->glyphs.init();
plan->source = hb_face_reference (face);
- plan->dest = hb_subset_face_create ();
+ plan->dest = hb_face_builder_create ();
plan->codepoint_to_glyph = hb_map_create();
plan->glyph_map = hb_map_create();
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 7501294d7..b7f14d2ef 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -89,7 +89,7 @@ struct hb_subset_plan_t
hb_blob_get_length (contents),
hb_blob_get_length (source_blob));
hb_blob_destroy (source_blob);
- return hb_subset_face_add_table(dest, tag, contents);
+ return hb_face_builder_add_table (dest, tag, contents);
}
};
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index 6b2b207ff..42c93d7d3 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -34,8 +34,6 @@
#include "hb-font-private.hh"
-typedef struct hb_subset_face_data_t hb_subset_face_data_t;
-
struct hb_subset_input_t {
hb_object_header_t header;
ASSERT_POD ();
@@ -54,10 +52,5 @@ struct hb_subset_input_t {
*/
};
-HB_INTERNAL hb_face_t *
-hb_subset_face_create (void);
-
-HB_INTERNAL hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob);
#endif /* HB_SUBSET_PRIVATE_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 411c6b861..88f6d6784 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -96,135 +96,6 @@ _subset (hb_subset_plan_t *plan)
}
-/*
- * A face that has add_table().
- */
-
-struct hb_subset_face_data_t
-{
- struct table_entry_t
- {
- inline int cmp (const hb_tag_t *t) const
- {
- if (*t < tag) return -1;
- if (*t > tag) return -1;
- return 0;
- }
-
- hb_tag_t tag;
- hb_blob_t *blob;
- };
-
- hb_vector_t tables;
-};
-
-static hb_subset_face_data_t *
-_hb_subset_face_data_create (void)
-{
- hb_subset_face_data_t *data = (hb_subset_face_data_t *) calloc (1, sizeof (hb_subset_face_data_t));
- if (unlikely (!data))
- return nullptr;
-
- data->tables.init ();
-
- return data;
-}
-
-static void
-_hb_subset_face_data_destroy (void *user_data)
-{
- hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
-
- for (unsigned int i = 0; i < data->tables.len; i++)
- hb_blob_destroy (data->tables[i].blob);
-
- data->tables.fini ();
-
- free (data);
-}
-
-static hb_blob_t *
-_hb_subset_face_data_reference_blob (hb_subset_face_data_t *data)
-{
-
- unsigned int table_count = data->tables.len;
- unsigned int face_length = table_count * 16 + 12;
-
- for (unsigned int i = 0; i < table_count; i++)
- face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables.arrayZ[i].blob));
-
- char *buf = (char *) malloc (face_length);
- if (unlikely (!buf))
- return nullptr;
-
- hb_serialize_context_t c (buf, face_length);
- OT::OpenTypeFontFile *f = c.start_serialize ();
-
- bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
- hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
-
- Supplier tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
- Supplier blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
- bool ret = f->serialize_single (&c,
- sfnt_tag,
- tags_supplier,
- blobs_supplier,
- table_count);
-
- c.end_serialize ();
-
- if (unlikely (!ret))
- {
- free (buf);
- return nullptr;
- }
-
- return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
-}
-
-static hb_blob_t *
-_hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
-{
- hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
-
- if (!tag)
- return _hb_subset_face_data_reference_blob (data);
-
- hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (tag);
- if (entry)
- return hb_blob_reference (entry->blob);
-
- return nullptr;
-}
-
-/* TODO: Move this to hb-face.h and rename to hb_face_builder_create()
- * with hb_face_builder_add_table(). */
-hb_face_t *
-hb_subset_face_create (void)
-{
- hb_subset_face_data_t *data = _hb_subset_face_data_create ();
- if (unlikely (!data)) return hb_face_get_empty ();
-
- return hb_face_create_for_tables (_hb_subset_face_reference_table,
- data,
- _hb_subset_face_data_destroy);
-}
-
-hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
-{
- if (unlikely (face->destroy != (hb_destroy_func_t) _hb_subset_face_data_destroy))
- return false;
-
- hb_subset_face_data_t *data = (hb_subset_face_data_t *) face->user_data;
- hb_subset_face_data_t::table_entry_t *entry = data->tables.push ();
-
- entry->tag = tag;
- entry->blob = hb_blob_reference (blob);
-
- return true;
-}
-
static bool
_subset_table (hb_subset_plan_t *plan,
hb_tag_t tag)