summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2018-02-07 13:47:35 -0500
committerBehdad Esfahbod <behdad@behdad.org>2018-02-07 13:47:35 -0500
commit6804b61d2e49fcf9eac9fa0b86497ba91b220bee (patch)
tree8903a03532add5c783c2f4bef0cc0373aa7763fe
parentaf02812fc51812a7e2265a1100bbca1a5bf8af45 (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.hh9
-rw-r--r--src/hb-subset.cc88
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.