From 95abd53758e281325b9124f0942aafb382a89090 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 1 Nov 2018 13:14:29 +0330 Subject: [PATCH] [feat] Expose public API * hb_aat_get_feature_settings --- src/Makefile.sources | 1 + src/hb-aat-layout-feat-table.hh | 68 ++++++++++++++++++++++++- src/hb-aat-layout-morx-table.hh | 6 +-- src/hb-aat-layout.cc | 33 ++++++++++++ src/hb-aat-layout.h | 75 +++++++++++++++++++++++++++ src/hb-aat-layout.hh | 7 +-- src/hb-aat-map.hh | 5 +- src/hb-ot-face.hh | 1 + test/api/Makefile.am | 1 + test/api/test-aat-layout.c | 89 +++++++++++++++++++++++++++++++++ test/api/test-c.c | 1 + 11 files changed, 278 insertions(+), 9 deletions(-) create mode 100644 src/hb-aat-layout.h create mode 100644 test/api/test-aat-layout.c diff --git a/src/Makefile.sources b/src/Makefile.sources index 3dcd771f4..2635cbc31 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -189,6 +189,7 @@ HB_OT_headers = \ hb-ot-name.h \ hb-ot-shape.h \ hb-ot-var.h \ + hb-aat-layout.h \ $(NULL) # Optional Sources and Headers with external deps diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh index 87ab4abd3..5e7781353 100644 --- a/src/hb-aat-layout-feat-table.hh +++ b/src/hb-aat-layout-feat-table.hh @@ -45,15 +45,28 @@ struct SettingName return_trace (likely (c->check_struct (this))); } - protected: HBUINT16 setting; /* The setting. */ NameID nameIndex; /* The name table index for the setting's name. */ public: DEFINE_SIZE_STATIC (4); }; +struct feat; + struct FeatureName { +<<<<<<< HEAD +======= + static int cmp (const void *key_, const void *entry_) + { + hb_aat_feature_type_t key = * (hb_aat_feature_type_t *) key_; + const FeatureName * entry = (const FeatureName *) entry_; + return key < entry->feature ? -1 : + key > entry->feature ? 1 : + 0; + } + +>>>>>>> 08982bb4... [feat] Expose public API enum { Exclusive = 0x8000, /* If set, the feature settings are mutually exclusive. */ NotDefault = 0x4000, /* If clear, then the setting with an index of 0 in @@ -68,6 +81,39 @@ struct FeatureName * as the default. */ }; +<<<<<<< HEAD +======= + inline unsigned int get_settings (const feat *feat, + hb_bool_t *is_exclusive, + unsigned int start_offset, + unsigned int *records_count, + hb_aat_feature_option_record_t *records_buffer) const + { + bool exclusive = featureFlags & Exclusive; + bool not_default = featureFlags & NotDefault; + if (is_exclusive) *is_exclusive = exclusive; + const UnsizedArrayOf& settings = feat+settingTable; + unsigned int len = 0; + unsigned int settings_count = nSettings; + if (records_count && records_buffer) + { + len = MIN (settings_count - start_offset, *records_count); + for (unsigned int i = 0; i < len; i++) + { + records_buffer[i].is_default = exclusive && not_default && + i + start_offset == (featureFlags & IndexMask); + records_buffer[i].name_id = settings[start_offset + i].nameIndex; + records_buffer[i].setting = settings[start_offset + i].setting; + } + if (exclusive && !not_default && start_offset == 0 && len != 0) + records_buffer[0].is_default = true; + } + if (is_exclusive) *is_exclusive = exclusive; + if (records_count) *records_count = len; + return settings_count; + } + +>>>>>>> 08982bb4... [feat] Expose public API inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -95,6 +141,26 @@ struct feat { static const hb_tag_t tableTag = HB_AAT_TAG_feat; + inline const FeatureName& get_feature (hb_aat_feature_type_t key) const + { + const FeatureName* feature = (FeatureName*) hb_bsearch (&key, &names, + FeatureName::static_size, + sizeof (FeatureName), + FeatureName::cmp); + + return feature ? *feature : Null (FeatureName); + } + + inline unsigned int get_settings (hb_aat_feature_type_t key, + hb_bool_t *is_exclusive, + unsigned int start_offset, + unsigned int *records_count, + hb_aat_feature_option_record_t *records_buffer) const + { + return get_feature (key).get_settings (this, is_exclusive, start_offset, + records_count, records_buffer); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 15332d0f6..a62519755 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -957,9 +957,9 @@ struct Chain unsigned int count = featureCount; for (unsigned i = 0; i < count; i++) { - const Feature &feature = featureZ[i]; - uint16_t type = feature.featureType; - uint16_t setting = feature.featureSetting; + const Feature &feature = featureZ[i]; + hb_aat_feature_type_t type = feature.featureType; + hb_aat_feature_setting_t setting = feature.featureSetting; retry: const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type); if (info && info->setting == setting) diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index d9580c152..5eca51756 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -1,5 +1,6 @@ /* * Copyright © 2017 Google, Inc. + * Copyright © 2018 Ebrahim Byagowi * * This is part of HarfBuzz, a text shaping library. * @@ -27,6 +28,7 @@ #include "hb-open-type.hh" #include "hb-ot-face.hh" +#include "hb-aat-layout.h" #include "hb-aat-layout.hh" #include "hb-aat-layout-ankr-table.hh" #include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise. @@ -167,6 +169,12 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_, ankr_table = ankr_table_; ankr_end = ankr_end_; } +static inline const AAT::feat& +_get_feat (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::feat); + return *(hb_ot_face_data (face)->feat.get ()); +} /* @@ -297,3 +305,28 @@ _hb_aat_language_get (hb_face_t *face, { return face->table.ltag->get_language (i); } + +/** + * hb_aat_get_feature_settings: + * @face: a font face. + * @identifier: aat feature id you are querying. + * @is_exclusive: (out): is only one of the features can be enabled. + * @start_offset: start offset, if you are iterating + * @records_count: (inout): gets input buffer size, puts number of filled one + * @records_buffer: (out): buffer of records + * + * Returns: Total number of records available for the feature. + * + * Since: REPLACEME + */ +unsigned int +hb_aat_get_feature_settings (hb_face_t *face, + hb_aat_feature_type_t identifier, + hb_bool_t *is_exclusive, + unsigned int start_offset, + unsigned int *records_count, /* IN/OUT. May be NULL. */ + hb_aat_feature_option_record_t *records_buffer /* OUT. May be NULL. */) +{ + return _get_feat (face).get_settings (identifier, is_exclusive, start_offset, + records_count, records_buffer); +} diff --git a/src/hb-aat-layout.h b/src/hb-aat-layout.h new file mode 100644 index 000000000..186293529 --- /dev/null +++ b/src/hb-aat-layout.h @@ -0,0 +1,75 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_AAT_LAYOUT_H +#define HB_AAT_LAYOUT_H + +#include "hb.h" +#include "hb-ot.h" + +HB_BEGIN_DECLS + +/** + * hb_aat_type_t: + * + * Feature identifier + * + * Since: REPLACEME + */ +typedef uint16_t hb_aat_feature_type_t; + +/** + * hb_aat_feature_t: + * + * Feature value + * + * Since: REPLACEME + */ +typedef uint16_t hb_aat_feature_setting_t; + +/** + * hb_aat_feature_option_record_t: + * + * Feature type record + * + * Since: REPLACEME + **/ +typedef struct hb_aat_feature_option_record_t +{ + hb_bool_t is_default; + hb_aat_feature_setting_t setting; + hb_ot_name_id_t name_id; +} hb_aat_feature_option_record_t; + +HB_EXTERN unsigned int +hb_aat_get_feature_settings (hb_face_t *face, + hb_aat_feature_type_t identifier, + hb_bool_t *is_exclusive, + unsigned int start_offset, + unsigned int *records_count, /* IN/OUT. May be NULL. */ + hb_aat_feature_option_record_t *records_buffer /* OUT. May be NULL. */); + +HB_END_DECLS + +#endif /* HB_AAT_LAYOUT_H */ diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh index 1d3407971..d7296aa68 100644 --- a/src/hb-aat-layout.hh +++ b/src/hb-aat-layout.hh @@ -29,15 +29,16 @@ #include "hb.hh" +#include "hb-aat-layout.h" #include "hb-ot-shape.hh" struct hb_aat_feature_mapping_t { hb_tag_t otFeatureTag; - uint16_t aatFeatureType; - uint16_t selectorToEnable; - uint16_t selectorToDisable; + hb_aat_feature_type_t aatFeatureType; + hb_aat_feature_setting_t selectorToEnable; + hb_aat_feature_setting_t selectorToDisable; static inline int cmp (const void *key_, const void *entry_) { diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh index 7d85c7c38..07720e882 100644 --- a/src/hb-aat-map.hh +++ b/src/hb-aat-map.hh @@ -28,6 +28,7 @@ #define HB_AAT_MAP_HH #include "hb.hh" +#include "hb-aat-layout.h" struct hb_aat_map_t @@ -65,8 +66,8 @@ struct hb_aat_map_builder_t public: struct feature_info_t { - uint16_t type; - uint16_t setting; + hb_aat_feature_type_t type; + hb_aat_feature_setting_t setting; unsigned seq; /* For stable sorting only. */ static int cmp (const void *pa, const void *pb) diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 3ca875e71..4a3260626 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -65,6 +65,7 @@ HB_OT_TABLE(AAT, trak) \ HB_OT_TABLE(AAT, lcar) \ HB_OT_TABLE(AAT, ltag) \ + HB_OT_TABLE(AAT, feat) \ /* OpenType variations. */ \ HB_OT_TABLE(OT, fvar) \ HB_OT_TABLE(OT, avar) \ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 4c329408f..89f03b851 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -28,6 +28,7 @@ check_PROGRAMS = $(TEST_PROGS) noinst_PROGRAMS = $(TEST_PROGS) TEST_PROGS = \ + test-aat-layout \ test-baseline \ test-blob \ test-buffer \ diff --git a/test/api/test-aat-layout.c b/test/api/test-aat-layout.c new file mode 100644 index 000000000..8019c5f27 --- /dev/null +++ b/test/api/test-aat-layout.c @@ -0,0 +1,89 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb-test.h" + +#include + +/* Unit tests for hb-aat-layout.h */ + +static void +test_aat_get_feature_settings (void) +{ + hb_bool_t is_exclusive; + hb_aat_feature_option_record_t records[3]; + unsigned int count = 3; + + hb_face_t *face = hb_test_open_font_file ("fonts/aat-feat.ttf"); + + g_assert_cmpuint (4, ==, hb_aat_get_feature_settings (face, 18, &is_exclusive, + 0, &count, records)); + g_assert_cmpuint (3, ==, count); + g_assert (is_exclusive); + + g_assert_cmpuint (1, ==, records[0].is_default); + g_assert_cmpuint (0, ==, records[0].setting); + g_assert_cmpuint (294, ==, records[0].name_id); + + g_assert_cmpuint (0, ==, records[1].is_default); + g_assert_cmpuint (1, ==, records[1].setting); + g_assert_cmpuint (295, ==, records[1].name_id); + + g_assert_cmpuint (0, ==, records[2].is_default); + g_assert_cmpuint (2, ==, records[2].setting); + g_assert_cmpuint (296, ==, records[2].name_id); + + count = 3; + g_assert_cmpuint (4, ==, hb_aat_get_feature_settings (face, 18, &is_exclusive, + 3, &count, records)); + g_assert_cmpuint (1, ==, count); + g_assert (is_exclusive); + + g_assert_cmpuint (0, ==, records[0].is_default); + g_assert_cmpuint (3, ==, records[0].setting); + g_assert_cmpuint (297, ==, records[0].name_id); + + count = 100; + g_assert_cmpuint (0, ==, hb_aat_get_feature_settings (face, 32, &is_exclusive, + 0, &count, records)); + g_assert_cmpuint (0, ==, count); + g_assert (!is_exclusive); + + hb_face_destroy (face); + + hb_face_t *sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf"); + g_assert_cmpuint (0, ==, hb_aat_get_feature_settings (face, 100, &is_exclusive, + 0, &count, records)); + hb_face_destroy (sbix); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_aat_get_feature_settings); + + return hb_test_run(); +} diff --git a/test/api/test-c.c b/test/api/test-c.c index 061f35cdc..3d1d6e8c5 100644 --- a/test/api/test-c.c +++ b/test/api/test-c.c @@ -33,6 +33,7 @@ #include #include +#include #ifdef HAVE_GLIB #include