1 /* 2 * Copyright © 2018 Ebrahim Byagowi 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 */ 24 25 #ifndef HB_AAT_LAYOUT_FEAT_TABLE_HH 26 #define HB_AAT_LAYOUT_FEAT_TABLE_HH 27 28 #include "hb-aat-layout-common.hh" 29 30 /* 31 * feat -- Feature Name 32 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html 33 */ 34 #define HB_AAT_TAG_feat HB_TAG('f', 'e', 'a', 't') 35 36 namespace AAT { 37 38 struct SettingName 39 { 40 friend struct FeatureName; 41 cmpAAT::SettingName42 int cmp(hb_aat_layout_feature_selector_t key) const 43 { 44 return (int)key - (int)setting; 45 } 46 get_selectorAAT::SettingName47 hb_aat_layout_feature_selector_t get_selector() const 48 { 49 return (hb_aat_layout_feature_selector_t)(unsigned)setting; 50 } 51 get_infoAAT::SettingName52 hb_aat_layout_feature_selector_info_t get_info(hb_aat_layout_feature_selector_t default_selector) const 53 { 54 return {nameIndex, 55 (hb_aat_layout_feature_selector_t)(unsigned int)setting, 56 default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID 57 ? (hb_aat_layout_feature_selector_t)(setting + 1) 58 : default_selector, 59 0}; 60 } 61 sanitizeAAT::SettingName62 bool sanitize(hb_sanitize_context_t *c) const 63 { 64 TRACE_SANITIZE(this); 65 return_trace(likely(c->check_struct(this))); 66 } 67 68 protected: 69 HBUINT16 setting; /* The setting. */ 70 NameID nameIndex; /* The name table index for the setting's name. */ 71 public: 72 DEFINE_SIZE_STATIC(4); 73 }; 74 DECLARE_NULL_NAMESPACE_BYTES(AAT, SettingName); 75 76 struct feat; 77 78 struct FeatureName 79 { cmpAAT::FeatureName80 int cmp(hb_aat_layout_feature_type_t key) const 81 { 82 return (int)key - (int)feature; 83 } 84 85 enum { 86 Exclusive = 0x8000, /* If set, the feature settings are mutually exclusive. */ 87 NotDefault = 0x4000, /* If clear, then the setting with an index of 0 in 88 * the setting name array for this feature should 89 * be taken as the default for the feature 90 * (if one is required). If set, then bits 0-15 of this 91 * featureFlags field contain the index of the setting 92 * which is to be taken as the default. */ 93 IndexMask = 0x00FF /* If bits 30 and 31 are set, then these sixteen bits 94 * indicate the index of the setting in the setting name 95 * array for this feature which should be taken 96 * as the default. */ 97 }; 98 get_selector_infosAAT::FeatureName99 unsigned int get_selector_infos(unsigned int start_offset, 100 unsigned int *selectors_count, /* IN/OUT. May be NULL. */ 101 hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */ 102 unsigned int *pdefault_index, /* OUT. May be NULL. */ 103 const void *base) const 104 { 105 hb_array_t<const SettingName> settings_table = (base + settingTableZ).as_array(nSettings); 106 107 static_assert(Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, ""); 108 109 hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID; 110 unsigned int default_index = Index::NOT_FOUND_INDEX; 111 if (featureFlags & Exclusive) { 112 default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0; 113 default_selector = settings_table[default_index].get_selector(); 114 } 115 if (pdefault_index) 116 *pdefault_index = default_index; 117 118 if (selectors_count) { 119 +settings_table.sub_array(start_offset, selectors_count) | 120 hb_map([=](const SettingName &setting) { return setting.get_info(default_selector); }) | 121 hb_sink(hb_array(selectors, *selectors_count)); 122 } 123 return settings_table.length; 124 } 125 get_feature_typeAAT::FeatureName126 hb_aat_layout_feature_type_t get_feature_type() const 127 { 128 return (hb_aat_layout_feature_type_t)(unsigned int)feature; 129 } 130 get_feature_name_idAAT::FeatureName131 hb_ot_name_id_t get_feature_name_id() const 132 { 133 return nameIndex; 134 } 135 is_exclusiveAAT::FeatureName136 bool is_exclusive() const 137 { 138 return featureFlags & Exclusive; 139 } 140 141 /* A FeatureName with no settings is meaningless */ has_dataAAT::FeatureName142 bool has_data() const 143 { 144 return nSettings; 145 } 146 sanitizeAAT::FeatureName147 bool sanitize(hb_sanitize_context_t *c, const void *base) const 148 { 149 TRACE_SANITIZE(this); 150 return_trace(likely(c->check_struct(this) && (base + settingTableZ).sanitize(c, nSettings))); 151 } 152 153 protected: 154 HBUINT16 feature; /* Feature type. */ 155 HBUINT16 nSettings; /* The number of records in the setting name array. */ 156 LNNOffsetTo<UnsizedArrayOf<SettingName>> settingTableZ; /* Offset in bytes from the beginning of this table to 157 * this feature's setting name array. The actual type of 158 * record this offset refers to will depend on the 159 * exclusivity value, as described below. */ 160 HBUINT16 featureFlags; /* Single-bit flags associated with the feature type. */ 161 HBINT16 nameIndex; /* The name table index for the feature's name. 162 * This index has values greater than 255 and 163 * less than 32768. */ 164 public: 165 DEFINE_SIZE_STATIC(12); 166 }; 167 168 struct feat 169 { 170 static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat; 171 has_dataAAT::feat172 bool has_data() const 173 { 174 return version.to_int(); 175 } 176 177 unsigned int get_feature_typesAAT::feat178 get_feature_types(unsigned int start_offset, unsigned int *count, hb_aat_layout_feature_type_t *features) const 179 { 180 if (count) { 181 +namesZ.as_array(featureNameCount).sub_array(start_offset, count) | hb_map(&FeatureName::get_feature_type) | 182 hb_sink(hb_array(features, *count)); 183 } 184 return featureNameCount; 185 } 186 exposes_featureAAT::feat187 bool exposes_feature(hb_aat_layout_feature_type_t feature_type) const 188 { 189 return get_feature(feature_type).has_data(); 190 } 191 get_featureAAT::feat192 const FeatureName &get_feature(hb_aat_layout_feature_type_t feature_type) const 193 { 194 return namesZ.bsearch(featureNameCount, feature_type); 195 } 196 get_feature_name_idAAT::feat197 hb_ot_name_id_t get_feature_name_id(hb_aat_layout_feature_type_t feature) const 198 { 199 return get_feature(feature).get_feature_name_id(); 200 } 201 get_selector_infosAAT::feat202 unsigned int get_selector_infos(hb_aat_layout_feature_type_t feature_type, 203 unsigned int start_offset, 204 unsigned int *selectors_count, /* IN/OUT. May be NULL. */ 205 hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */ 206 unsigned int *default_index /* OUT. May be NULL. */) const 207 { 208 return get_feature(feature_type) 209 .get_selector_infos(start_offset, selectors_count, selectors, default_index, this); 210 } 211 sanitizeAAT::feat212 bool sanitize(hb_sanitize_context_t *c) const 213 { 214 TRACE_SANITIZE(this); 215 return_trace(likely(c->check_struct(this) && version.major == 1 && namesZ.sanitize(c, featureNameCount, this))); 216 } 217 218 protected: 219 FixedVersion<> version; /* Version number of the feature name table 220 * (0x00010000 for the current version). */ 221 HBUINT16 featureNameCount; 222 /* The number of entries in the feature name array. */ 223 HBUINT16 reserved1; /* Reserved (set to zero). */ 224 HBUINT32 reserved2; /* Reserved (set to zero). */ 225 SortedUnsizedArrayOf<FeatureName> namesZ; /* The feature name array. */ 226 public: 227 DEFINE_SIZE_ARRAY(12, namesZ); 228 }; 229 230 } /* namespace AAT */ 231 232 #endif /* HB_AAT_LAYOUT_FEAT_TABLE_HH */ 233