diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2018-02-07 13:47:35 -0500 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2018-02-07 13:47:35 -0500 |
commit | 6804b61d2e49fcf9eac9fa0b86497ba91b220bee (patch) | |
tree | 8903a03532add5c783c2f4bef0cc0373aa7763fe | |
parent | af02812fc51812a7e2265a1100bbca1a5bf8af45 (diff) |
[subset] Add hb_subset_face
It's a hb_face_t that has add_table() and in the future knows how to
compile itself into a font blob.
-rw-r--r-- | src/hb-private.hh | 9 | ||||
-rw-r--r-- | src/hb-subset.cc | 88 |
2 files changed, 97 insertions, 0 deletions
diff --git a/src/hb-private.hh b/src/hb-private.hh index 53ed11c8..67ede7cc 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -492,6 +492,15 @@ struct hb_prealloced_array_t } template <typename T> + inline Type *lsearch (T *x) + { + for (unsigned int i = 0; i < len; i++) + if (0 == this->array[i].cmp (x)) + return &array[i]; + return nullptr; + } + + template <typename T> inline Type *bsearch (T *x) { unsigned int i; diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 28cfd300..bb7d831f 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -102,6 +102,94 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input) } + +/* + * 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_prealloced_array_t<table_entry_t, 32> 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; + + 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; + + free (data); +} + +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) + { + /* TODO Compile face blob... */ + return nullptr; + } + + hb_subset_face_data_t::table_entry_t *entry = data->tables.lsearch (&tag); + if (entry) + return hb_blob_reference (entry->blob); + + return nullptr; +} + +static 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); +} + +static bool +hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) +{ + if (unlikely (face->destroy != _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.lsearch (&tag); + if (unlikely (!entry)) + return false; + + entry->tag = tag; + entry->blob = hb_blob_reference (blob); + + return true; +} + /** * hb_subset: * @profile: profile to use for the subsetting. |