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)