#ifndef HB_AAT_LAYOUT_FEAT_TABLE_HH
#define HB_AAT_LAYOUT_FEAT_TABLE_HH
#include "hb-aat-layout-common.hh"
#define HB_AAT_TAG_feat HB_TAG('f','e','a','t')
namespace AAT {
struct SettingName
{
friend struct FeatureName;
int cmp (hb_aat_layout_feature_selector_t key) const
{ return (int) key - (int) setting; }
hb_aat_layout_feature_selector_t get_selector () const
{ return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
hb_aat_layout_feature_selector_info_t get_info (hb_aat_layout_feature_selector_t default_selector) const
{
return {
nameIndex,
(hb_aat_layout_feature_selector_t) (unsigned int) setting,
default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID
? (hb_aat_layout_feature_selector_t) (setting + 1)
: default_selector,
0
};
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
HBUINT16 setting;
NameID nameIndex;
public:
DEFINE_SIZE_STATIC (4);
};
DECLARE_NULL_NAMESPACE_BYTES (AAT, SettingName);
struct feat;
struct FeatureName
{
int cmp (hb_aat_layout_feature_type_t key) const
{ return (int) key - (int) feature; }
enum {
Exclusive = 0x8000,
NotDefault = 0x4000,
IndexMask = 0x00FF
};
unsigned int get_selector_infos (unsigned int start_offset,
unsigned int *selectors_count,
hb_aat_layout_feature_selector_info_t *selectors,
unsigned int *pdefault_index,
const void *base) const
{
hb_array_t< const SettingName> settings_table = (base+settingTableZ).as_array (nSettings);
static_assert (Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, "");
hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID;
unsigned int default_index = Index::NOT_FOUND_INDEX;
if (featureFlags & Exclusive)
{
default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0;
default_selector = settings_table[default_index].get_selector ();
}
if (pdefault_index)
*pdefault_index = default_index;
if (selectors_count)
{
+ settings_table.sub_array (start_offset, selectors_count)
| hb_map ([=] (const SettingName& setting) { return setting.get_info (default_selector); })
| hb_sink (hb_array (selectors, *selectors_count))
;
}
return settings_table.length;
}
hb_aat_layout_feature_type_t get_feature_type () const
{ return (hb_aat_layout_feature_type_t) (unsigned int) feature; }
hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
bool is_exclusive () const { return featureFlags & Exclusive; }
bool has_data () const { return nSettings; }
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
hb_barrier () &&
(base+settingTableZ).sanitize (c, nSettings)));
}
protected:
HBUINT16 feature;
HBUINT16 nSettings;
NNOffset32To<UnsizedArrayOf<SettingName>>
settingTableZ;
HBUINT16 featureFlags;
HBINT16 nameIndex;
public:
DEFINE_SIZE_STATIC (12);
};
struct feat
{
static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat;
bool has_data () const { return version.to_int (); }
unsigned int get_feature_types (unsigned int start_offset,
unsigned int *count,
hb_aat_layout_feature_type_t *features) const
{
if (count)
{
+ namesZ.as_array (featureNameCount).sub_array (start_offset, count)
| hb_map (&FeatureName::get_feature_type)
| hb_sink (hb_array (features, *count))
;
}
return featureNameCount;
}
bool exposes_feature (hb_aat_layout_feature_type_t feature_type) const
{ return get_feature (feature_type).has_data (); }
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
{ return namesZ.bsearch (featureNameCount, feature_type); }
hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
{ return get_feature (feature).get_feature_name_id (); }
unsigned int get_selector_infos (hb_aat_layout_feature_type_t feature_type,
unsigned int start_offset,
unsigned int *selectors_count,
hb_aat_layout_feature_selector_info_t *selectors,
unsigned int *default_index ) const
{
return get_feature (feature_type).get_selector_infos (start_offset, selectors_count, selectors,
default_index, this);
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
hb_barrier () &&
version.major == 1 &&
namesZ.sanitize (c, featureNameCount, this)));
}
protected:
FixedVersion<>version;
HBUINT16 featureNameCount;
HBUINT16 reserved1;
HBUINT32 reserved2;
SortedUnsizedArrayOf<FeatureName>
namesZ;
public:
DEFINE_SIZE_ARRAY (12, namesZ);
};
}
#endif