hb-aat-layout.cc (27149B)
1 /* 2 * Copyright © 2017 Google, Inc. 3 * Copyright © 2018 Ebrahim Byagowi 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Google Author(s): Behdad Esfahbod 26 */ 27 28 #include "hb.hh" 29 30 #include "hb-aat-layout.hh" 31 #include "hb-aat-layout-ankr-table.hh" 32 #include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise. 33 #include "hb-aat-layout-feat-table.hh" 34 #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise. 35 #include "hb-aat-layout-kerx-table.hh" 36 #include "hb-aat-layout-morx-table.hh" 37 #include "hb-aat-layout-trak-table.hh" 38 #include "hb-aat-ltag-table.hh" 39 40 #include "hb-ot-layout-gsub-table.hh" 41 #include "hb-ot-layout-gdef-table.hh" 42 43 44 /* 45 * hb_aat_apply_context_t 46 */ 47 48 /* Note: This context is used for kerning, even without AAT, hence the condition. */ 49 #if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN) 50 51 AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_, 52 hb_font_t *font_, 53 hb_buffer_t *buffer_, 54 hb_blob_t *blob) : 55 plan (plan_), 56 font (font_), 57 face (font->face), 58 buffer (buffer_), 59 sanitizer (), 60 ankr_table (&Null (AAT::ankr)), 61 gdef ( 62 #ifndef HB_NO_OT_LAYOUT 63 *face->table.GDEF->table 64 #else 65 Null (GDEF) 66 #endif 67 ), 68 has_glyph_classes (gdef.has_glyph_classes ()), 69 lookup_index (0) 70 { 71 sanitizer.init (blob); 72 sanitizer.set_num_glyphs (face->get_num_glyphs ()); 73 sanitizer.start_processing (); 74 sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX); 75 } 76 77 AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t () 78 { sanitizer.end_processing (); } 79 80 void 81 AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) 82 { ankr_table = ankr_table_; } 83 84 #endif 85 86 87 /** 88 * SECTION:hb-aat-layout 89 * @title: hb-aat-layout 90 * @short_description: Apple Advanced Typography Layout 91 * @include: hb-aat.h 92 * 93 * Functions for querying AAT Layout features in the font face. 94 * 95 * HarfBuzz supports all of the AAT tables used to implement shaping. Other 96 * AAT tables and their associated features are not supported. 97 **/ 98 99 100 #if !defined(HB_NO_AAT) || defined(HAVE_CORETEXT) 101 102 /* Mapping from OpenType feature tags to AAT feature names and selectors. 103 * 104 * Table data courtesy of Apple. Converted from mnemonics to integers 105 * when moving to this file. */ 106 static const hb_aat_feature_mapping_t feature_mappings[] = 107 { 108 {HB_TAG ('a','f','r','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS}, 109 {HB_TAG ('c','2','p','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE}, 110 {HB_TAG ('c','2','s','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE}, 111 {HB_TAG ('c','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF}, 112 {HB_TAG ('c','a','s','e'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF}, 113 {HB_TAG ('c','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF}, 114 {HB_TAG ('c','p','s','p'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF}, 115 {HB_TAG ('c','s','w','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF}, 116 {HB_TAG ('d','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF}, 117 {HB_TAG ('e','x','p','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 118 {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS}, 119 {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7}, 120 {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, 121 {HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1}, 122 {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF}, 123 {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF}, 124 {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION}, 125 {HB_TAG ('h','o','j','o'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 126 {HB_TAG ('h','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, 127 {HB_TAG ('i','t','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN, HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF}, 128 {HB_TAG ('j','p','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 129 {HB_TAG ('j','p','7','8'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 130 {HB_TAG ('j','p','8','3'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 131 {HB_TAG ('j','p','9','0'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 132 {HB_TAG ('l','i','g','a'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF}, 133 {HB_TAG ('l','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS, (hb_aat_layout_feature_selector_t) 2}, 134 {HB_TAG ('m','g','r','k'), HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF}, 135 {HB_TAG ('n','l','c','k'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 136 {HB_TAG ('o','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS, (hb_aat_layout_feature_selector_t) 2}, 137 {HB_TAG ('o','r','d','n'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION}, 138 {HB_TAG ('p','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, 139 {HB_TAG ('p','c','a','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE}, 140 {HB_TAG ('p','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, 141 {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4}, 142 {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, 143 {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, 144 {HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF}, 145 {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF}, 146 {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION}, 147 {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE}, 148 {HB_TAG ('s','m','p','l'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 149 {HB_TAG ('s','s','0','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF}, 150 {HB_TAG ('s','s','0','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF}, 151 {HB_TAG ('s','s','0','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF}, 152 {HB_TAG ('s','s','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF}, 153 {HB_TAG ('s','s','0','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF}, 154 {HB_TAG ('s','s','0','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF}, 155 {HB_TAG ('s','s','0','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF}, 156 {HB_TAG ('s','s','0','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF}, 157 {HB_TAG ('s','s','0','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF}, 158 {HB_TAG ('s','s','1','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF}, 159 {HB_TAG ('s','s','1','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF}, 160 {HB_TAG ('s','s','1','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF}, 161 {HB_TAG ('s','s','1','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF}, 162 {HB_TAG ('s','s','1','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF}, 163 {HB_TAG ('s','s','1','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF}, 164 {HB_TAG ('s','s','1','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF}, 165 {HB_TAG ('s','s','1','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF}, 166 {HB_TAG ('s','s','1','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF}, 167 {HB_TAG ('s','s','1','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF}, 168 {HB_TAG ('s','s','2','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF}, 169 {HB_TAG ('s','u','b','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION}, 170 {HB_TAG ('s','u','p','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION}, 171 {HB_TAG ('s','w','s','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF}, 172 {HB_TAG ('t','i','t','l'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS}, 173 {HB_TAG ('t','n','a','m'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 174 {HB_TAG ('t','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS, (hb_aat_layout_feature_selector_t) 4}, 175 {HB_TAG ('t','r','a','d'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE, HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS, (hb_aat_layout_feature_selector_t) 16}, 176 {HB_TAG ('t','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, 177 {HB_TAG ('u','n','i','c'), HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE, (hb_aat_layout_feature_selector_t) 14, (hb_aat_layout_feature_selector_t) 15}, 178 {HB_TAG ('v','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, 179 {HB_TAG ('v','e','r','t'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF}, 180 {HB_TAG ('v','h','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, 181 {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF}, 182 {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, 183 {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF}, 184 {HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3}, 185 {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF}, 186 }; 187 188 /** 189 * hb_aat_layout_find_feature_mapping: 190 * @tag: The requested #hb_tag_t feature tag 191 * 192 * Fetches the AAT feature-and-selector combination that corresponds 193 * to a given OpenType feature tag. 194 * 195 * Return value: the AAT features and selectors corresponding to the 196 * OpenType feature tag queried 197 * 198 **/ 199 const hb_aat_feature_mapping_t * 200 hb_aat_layout_find_feature_mapping (hb_tag_t tag) 201 { 202 return hb_sorted_array (feature_mappings).bsearch (tag); 203 } 204 #endif 205 206 207 #ifndef HB_NO_AAT_SHAPE 208 209 /* 210 * mort/morx/kerx/trak 211 */ 212 213 214 bool 215 AAT::morx::is_blocklisted (hb_blob_t *blob, 216 hb_face_t *face) const 217 { 218 #ifdef HB_NO_AAT_LAYOUT_BLOCKLIST 219 return false; 220 #endif 221 222 switch HB_CODEPOINT_ENCODE3 (blob->length, 223 face->table.GSUB->table.get_length (), 224 face->table.GDEF->table.get_length ()) 225 { 226 /* https://github.com/harfbuzz/harfbuzz/issues/4108 227 sha1sum:a71ca6813b7e56a772cffff7c24a5166b087197c AALMAGHRIBI.ttf */ 228 case HB_CODEPOINT_ENCODE3 (19892, 2794, 340): 229 return true; 230 } 231 return false; 232 } 233 234 bool 235 AAT::mort::is_blocklisted (hb_blob_t *blob, 236 hb_face_t *face) const 237 { 238 #ifdef HB_NO_AAT_LAYOUT_BLOCKLIST 239 return false; 240 #endif 241 return false; 242 } 243 244 void 245 hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, 246 hb_aat_map_t *map) 247 { 248 const AAT::morx& morx = *mapper->face->table.morx->table; 249 if (morx.has_data ()) 250 { 251 morx.compile_flags (mapper, map); 252 return; 253 } 254 255 const AAT::mort& mort = *mapper->face->table.mort->table; 256 if (mort.has_data ()) 257 { 258 mort.compile_flags (mapper, map); 259 return; 260 } 261 } 262 263 264 /** 265 * hb_aat_layout_has_substitution: 266 * @face: #hb_face_t to work upon 267 * 268 * Tests whether the specified face includes any substitutions in the 269 * `morx` or `mort` tables. 270 * 271 * <note>Note: does not examine the `GSUB` table.</note> 272 * 273 * Return value: `true` if data found, `false` otherwise 274 * 275 * Since: 2.3.0 276 */ 277 hb_bool_t 278 hb_aat_layout_has_substitution (hb_face_t *face) 279 { 280 return face->table.morx->table->has_data () || 281 face->table.mort->table->has_data (); 282 } 283 284 void 285 hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, 286 hb_font_t *font, 287 hb_buffer_t *buffer, 288 const hb_feature_t *features, 289 unsigned num_features) 290 { 291 hb_aat_map_t map; 292 if (num_features) 293 { 294 hb_aat_map_builder_t builder (font->face, plan->props); 295 for (unsigned i = 0; i < num_features; i++) 296 builder.add_feature (features[i]); 297 builder.compile (map); 298 } 299 300 { 301 auto &accel = *font->face->table.morx; 302 const AAT::morx& morx = *accel.table; 303 if (morx.has_data ()) 304 { 305 AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); 306 if (!buffer->message (font, "start table morx")) return; 307 c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); 308 morx.apply (&c, num_features ? map : plan->aat_map, accel); 309 accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); 310 c.buffer_glyph_set = nullptr; 311 (void) buffer->message (font, "end table morx"); 312 return; 313 } 314 } 315 316 { 317 auto &accel = *font->face->table.mort; 318 const AAT::mort& mort = *accel.table; 319 if (mort.has_data ()) 320 { 321 AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); 322 if (!buffer->message (font, "start table mort")) return; 323 mort.apply (&c, num_features ? map : plan->aat_map, accel); 324 (void) buffer->message (font, "end table mort"); 325 return; 326 } 327 } 328 } 329 330 static bool 331 is_deleted_glyph (const hb_glyph_info_t *info) 332 { 333 return _hb_glyph_info_is_aat_deleted (info); 334 } 335 336 void 337 hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) 338 { 339 if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED) 340 buffer->delete_glyphs_inplace (is_deleted_glyph); 341 } 342 343 /** 344 * hb_aat_layout_has_positioning: 345 * @face: #hb_face_t to work upon 346 * 347 * Tests whether the specified face includes any positioning information 348 * in the `kerx` table. 349 * 350 * <note>Note: does not examine the `GPOS` table.</note> 351 * 352 * Return value: `true` if data found, `false` otherwise 353 * 354 * Since: 2.3.0 355 */ 356 hb_bool_t 357 hb_aat_layout_has_positioning (hb_face_t *face) 358 { 359 return face->table.kerx->table->has_data (); 360 } 361 362 void 363 hb_aat_layout_position (const hb_ot_shape_plan_t *plan, 364 hb_font_t *font, 365 hb_buffer_t *buffer) 366 { 367 auto &accel = *font->face->table.kerx; 368 369 AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); 370 if (!buffer->message (font, "start table kerx")) return; 371 c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); 372 c.set_ankr_table (font->face->table.ankr.get ()); 373 accel.apply (&c); 374 accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); 375 c.buffer_glyph_set = nullptr; 376 (void) buffer->message (font, "end table kerx"); 377 } 378 379 380 /** 381 * hb_aat_layout_has_tracking: 382 * @face:: #hb_face_t to work upon 383 * 384 * Tests whether the specified face includes any tracking information 385 * in the `trak` table. 386 * 387 * Return value: `true` if data found, `false` otherwise 388 * 389 * Since: 2.3.0 390 */ 391 hb_bool_t 392 hb_aat_layout_has_tracking (hb_face_t *face) 393 { 394 return face->table.trak->has_data (); 395 } 396 397 void 398 hb_aat_layout_track (const hb_ot_shape_plan_t *plan, 399 hb_font_t *font, 400 hb_buffer_t *buffer) 401 { 402 const AAT::trak& trak = *font->face->table.trak; 403 404 AAT::hb_aat_apply_context_t c (plan, font, buffer); 405 trak.apply (&c); 406 } 407 408 /** 409 * hb_aat_layout_get_feature_types: 410 * @face: #hb_face_t to work upon 411 * @start_offset: offset of the first feature type to retrieve 412 * @feature_count: (inout) (optional): Input = the maximum number of feature types to return; 413 * Output = the actual number of feature types returned (may be zero) 414 * @features: (out caller-allocates) (array length=feature_count): Array of feature types found 415 * 416 * Fetches a list of the AAT feature types included in the specified face. 417 * 418 * Return value: Number of all available feature types. 419 * 420 * Since: 2.2.0 421 */ 422 unsigned int 423 hb_aat_layout_get_feature_types (hb_face_t *face, 424 unsigned int start_offset, 425 unsigned int *feature_count, /* IN/OUT. May be NULL. */ 426 hb_aat_layout_feature_type_t *features /* OUT. May be NULL. */) 427 { 428 return face->table.feat->get_feature_types (start_offset, feature_count, features); 429 } 430 431 /** 432 * hb_aat_layout_feature_type_get_name_id: 433 * @face: #hb_face_t to work upon 434 * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type 435 * 436 * Fetches the name identifier of the specified feature type in the face's `name` table. 437 * 438 * Return value: Name identifier of the requested feature type 439 * 440 * Since: 2.2.0 441 */ 442 hb_ot_name_id_t 443 hb_aat_layout_feature_type_get_name_id (hb_face_t *face, 444 hb_aat_layout_feature_type_t feature_type) 445 { 446 return face->table.feat->get_feature_name_id (feature_type); 447 } 448 449 /** 450 * hb_aat_layout_feature_type_get_selector_infos: 451 * @face: #hb_face_t to work upon 452 * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type 453 * @start_offset: offset of the first feature type to retrieve 454 * @selector_count: (inout) (optional): Input = the maximum number of selectors to return; 455 * Output = the actual number of selectors returned (may be zero) 456 * @selectors: (out caller-allocates) (array length=selector_count) (optional): 457 * A buffer pointer. The selectors available for the feature type queries. 458 * @default_index: (out) (optional): The index of the feature's default selector, if any 459 * 460 * Fetches a list of the selectors available for the specified feature in the given face. 461 * 462 * If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then 463 * the feature type is non-exclusive. Otherwise, @default_index is the index of 464 * the selector that is selected by default. 465 * 466 * Return value: Number of all available feature selectors 467 * 468 * Since: 2.2.0 469 */ 470 unsigned int 471 hb_aat_layout_feature_type_get_selector_infos (hb_face_t *face, 472 hb_aat_layout_feature_type_t feature_type, 473 unsigned int start_offset, 474 unsigned int *selector_count, /* IN/OUT. May be NULL. */ 475 hb_aat_layout_feature_selector_info_t *selectors, /* OUT. May be NULL. */ 476 unsigned int *default_index /* OUT. May be NULL. */) 477 { 478 return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index); 479 } 480 481 482 #endif