diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-face.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-face.cc | 419 |
1 files changed, 319 insertions, 100 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc index 26fddbe529..0c9949fff1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc @@ -26,48 +26,81 @@ * Google Author(s): Behdad Esfahbod */ -#include "hb-private.hh" +#include "hb.hh" -#include "hb-face-private.hh" -#include "hb-open-file-private.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-maxp-table.hh" +#include "hb-face.hh" +#include "hb-blob.hh" +#include "hb-open-file.hh" +#include "hb-ot-face.hh" +#include "hb-ot-cmap-table.hh" +/** + * SECTION:hb-face + * @title: hb-face + * @short_description: Font face objects + * @include: hb.h + * + * Font face is objects represent a single face in a font family. + * More exactly, a font face represents a single face in a binary font file. + * Font faces are typically built from a binary blob and a face index. + * Font faces are used to create fonts. + **/ + + +/** + * hb_face_count: + * @blob: a blob. + * + * Get number of faces in a blob. + * + * Return value: Number of faces in @blob + * + * Since: 1.7.7 + **/ +unsigned int +hb_face_count (hb_blob_t *blob) +{ + if (unlikely (!blob)) + return 0; + + /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */ + /* Make API signature const after. */ + hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)); + const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> (); + unsigned int ret = ot.get_face_count (); + hb_blob_destroy (sanitized); + + return ret; +} + /* * hb_face_t */ -const hb_face_t _hb_face_nil = { +DEFINE_NULL_INSTANCE (hb_face_t) = +{ HB_OBJECT_HEADER_STATIC, - true, /* immutable */ - nullptr, /* reference_table_func */ nullptr, /* user_data */ nullptr, /* destroy */ 0, /* index */ - 1000, /* upem */ - 0, /* num_glyphs */ - - { -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - }, + HB_ATOMIC_INT_INIT (1000), /* upem */ + HB_ATOMIC_INT_INIT (0), /* num_glyphs */ - nullptr, /* shape_plans */ + /* Zero for the rest is fine. */ }; /** * hb_face_create_for_tables: * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @user_data: + * @destroy: + * * - * * * Return value: (transfer full) * @@ -90,8 +123,10 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, face->user_data = user_data; face->destroy = destroy; - face->upem = 0; - face->num_glyphs = (unsigned int) -1; + face->num_glyphs.set_relaxed (-1); + + face->data.init0 (face); + face->table.init0 (face); return face; } @@ -134,22 +169,23 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void if (tag == HB_TAG_NONE) return hb_blob_reference (data->blob); - const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); - const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); + unsigned int base_offset; + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset); const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag); - hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); + hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length); return blob; } /** * hb_face_create: (Xconstructor) - * @blob: - * @index: + * @blob: + * @index: + * * - * * * Return value: (transfer full): * @@ -164,7 +200,7 @@ hb_face_create (hb_blob_t *blob, if (unlikely (!blob)) blob = hb_blob_get_empty (); - hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); + hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index); if (unlikely (!closure)) return hb_face_get_empty (); @@ -181,16 +217,16 @@ hb_face_create (hb_blob_t *blob, /** * hb_face_get_empty: * - * + * * * Return value: (transfer full) * * Since: 0.9.2 **/ hb_face_t * -hb_face_get_empty (void) +hb_face_get_empty () { - return const_cast<hb_face_t *> (&_hb_face_nil); + return const_cast<hb_face_t *> (&Null(hb_face_t)); } @@ -198,9 +234,9 @@ hb_face_get_empty (void) * hb_face_reference: (skip) * @face: a face. * - * * - * Return value: + * + * Return value: * * Since: 0.9.2 **/ @@ -214,7 +250,7 @@ hb_face_reference (hb_face_t *face) * hb_face_destroy: (skip) * @face: a face. * - * + * * * Since: 0.9.2 **/ @@ -231,9 +267,8 @@ hb_face_destroy (hb_face_t *face) node = next; } -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT + face->data.fini (); + face->table.fini (); if (face->destroy) face->destroy (face->user_data); @@ -244,14 +279,14 @@ hb_face_destroy (hb_face_t *face) /** * hb_face_set_user_data: (skip) * @face: a face. - * @key: - * @data: - * @destroy: - * @replace: + * @key: + * @data: + * @destroy: + * @replace: + * * - * * - * Return value: + * Return value: * * Since: 0.9.2 **/ @@ -268,16 +303,16 @@ hb_face_set_user_data (hb_face_t *face, /** * hb_face_get_user_data: (skip) * @face: a face. - * @key: + * @key: + * * - * * * Return value: (transfer none): * * Since: 0.9.2 **/ void * -hb_face_get_user_data (hb_face_t *face, +hb_face_get_user_data (const hb_face_t *face, hb_user_data_key_t *key) { return hb_object_get_user_data (face, key); @@ -287,51 +322,54 @@ hb_face_get_user_data (hb_face_t *face, * hb_face_make_immutable: * @face: a face. * - * + * * * Since: 0.9.2 **/ void hb_face_make_immutable (hb_face_t *face) { - if (unlikely (hb_object_is_inert (face))) + if (hb_object_is_immutable (face)) return; - face->immutable = true; + hb_object_make_immutable (face); } /** * hb_face_is_immutable: * @face: a face. * - * * - * Return value: + * + * Return value: * * Since: 0.9.2 **/ hb_bool_t -hb_face_is_immutable (hb_face_t *face) +hb_face_is_immutable (const hb_face_t *face) { - return face->immutable; + return hb_object_is_immutable (face); } /** * hb_face_reference_table: * @face: a face. - * @tag: + * @tag: + * * - * * * Return value: (transfer full): * * Since: 0.9.2 **/ hb_blob_t * -hb_face_reference_table (hb_face_t *face, - hb_tag_t tag) +hb_face_reference_table (const hb_face_t *face, + hb_tag_t tag) { + if (unlikely (tag == HB_TAG_NONE)) + return hb_blob_get_empty (); + return face->reference_table (tag); } @@ -339,7 +377,7 @@ hb_face_reference_table (hb_face_t *face, * hb_face_reference_blob: * @face: a face. * - * + * * * Return value: (transfer full): * @@ -354,9 +392,9 @@ hb_face_reference_blob (hb_face_t *face) /** * hb_face_set_index: * @face: a face. - * @index: + * @index: + * * - * * * Since: 0.9.2 **/ @@ -364,7 +402,7 @@ void hb_face_set_index (hb_face_t *face, unsigned int index) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; face->index = index; @@ -374,14 +412,14 @@ hb_face_set_index (hb_face_t *face, * hb_face_get_index: * @face: a face. * - * * - * Return value: + * + * Return value: * * Since: 0.9.2 **/ unsigned int -hb_face_get_index (hb_face_t *face) +hb_face_get_index (const hb_face_t *face) { return face->index; } @@ -389,9 +427,9 @@ hb_face_get_index (hb_face_t *face) /** * hb_face_set_upem: * @face: a face. - * @upem: + * @upem: + * * - * * * Since: 0.9.2 **/ @@ -399,43 +437,34 @@ void hb_face_set_upem (hb_face_t *face, unsigned int upem) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; - face->upem = upem; + face->upem.set_relaxed (upem); } /** * hb_face_get_upem: * @face: a face. * - * * - * Return value: + * + * Return value: * * Since: 0.9.2 **/ unsigned int -hb_face_get_upem (hb_face_t *face) +hb_face_get_upem (const hb_face_t *face) { return face->get_upem (); } -void -hb_face_t::load_upem (void) const -{ - hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head)); - const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob); - upem = head_table->get_upem (); - hb_blob_destroy (head_blob); -} - /** * hb_face_set_glyph_count: * @face: a face. - * @glyph_count: + * @glyph_count: + * * - * * * Since: 0.9.7 **/ @@ -443,40 +472,34 @@ void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count) { - if (face->immutable) + if (hb_object_is_immutable (face)) return; - face->num_glyphs = glyph_count; + face->num_glyphs.set_relaxed (glyph_count); } /** * hb_face_get_glyph_count: * @face: a face. * - * * - * Return value: + * + * Return value: * * Since: 0.9.7 **/ unsigned int -hb_face_get_glyph_count (hb_face_t *face) +hb_face_get_glyph_count (const hb_face_t *face) { return face->get_num_glyphs (); } -void -hb_face_t::load_num_glyphs (void) const -{ - hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp)); - const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob); - num_glyphs = maxp_table->get_num_glyphs (); - hb_blob_destroy (maxp_blob); -} - /** * hb_face_get_table_tags: * @face: a face. + * @start_offset: index of first tag to return. + * @table_count: input length of @table_tags array, output number of items written. + * @table_tags: array to write tags into. * * Retrieves table tags for a face, if possible. * @@ -485,12 +508,12 @@ hb_face_t::load_num_glyphs (void) const * Since: 1.6.0 **/ unsigned int -hb_face_get_table_tags (hb_face_t *face, +hb_face_get_table_tags (const hb_face_t *face, unsigned int start_offset, unsigned int *table_count, /* IN/OUT */ hb_tag_t *table_tags /* OUT */) { - if (face->destroy != _hb_face_for_data_closure_destroy) + if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy) { if (table_count) *table_count = 0; @@ -499,8 +522,204 @@ hb_face_get_table_tags (hb_face_t *face, hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; - const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); + const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> (); const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); return ot_face.get_table_tags (start_offset, table_count, table_tags); } + + +/* + * Character set. + */ + + +#ifndef HB_NO_FACE_COLLECT_UNICODES +/** + * hb_face_collect_unicodes: + * @face: font face. + * @out: set to add Unicode characters covered by @face to. + * + * Since: 1.9.0 + */ +void +hb_face_collect_unicodes (hb_face_t *face, + hb_set_t *out) +{ + face->table.cmap->collect_unicodes (out); +} +/** + * hb_face_collect_variation_selectors: + * @face: font face. + * @out: set to add Variation Selector characters covered by @face to. + * + * + * + * Since: 1.9.0 + */ +void +hb_face_collect_variation_selectors (hb_face_t *face, + hb_set_t *out) +{ + face->table.cmap->collect_variation_selectors (out); +} +/** + * hb_face_collect_variation_unicodes: + * @face: font face. + * @out: set to add Unicode characters for @variation_selector covered by @face to. + * + * + * + * Since: 1.9.0 + */ +void +hb_face_collect_variation_unicodes (hb_face_t *face, + hb_codepoint_t variation_selector, + hb_set_t *out) +{ + face->table.cmap->collect_variation_unicodes (variation_selector, out); +} +#endif + + +/* + * face-builder: A face that has add_table(). + */ + +struct hb_face_builder_data_t +{ + struct table_entry_t + { + int cmp (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<table_entry_t> tables; +}; + +static hb_face_builder_data_t * +_hb_face_builder_data_create () +{ + 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.length; 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.length; + 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[i].blob)); + + char *buf = (char *) malloc (face_length); + if (unlikely (!buf)) + return nullptr; + + hb_serialize_context_t c (buf, face_length); + c.propagate_error (data->tables); + OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> (); + + 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; + + bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ()); + + 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_UNUSED, 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: 1.9.0 + **/ +hb_face_t * +hb_face_builder_create () +{ + 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: 1.9.0 + **/ +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; +} |