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-feat-table.hh"
33 #include "hb-aat-layout-kerx-table.hh"
34 #include "hb-aat-layout-morx-table.hh"
35 #include "hb-aat-layout-trak-table.hh"
36 
37 /*
38  * hb_aat_apply_context_t
39  */
40 
41 /* Note: This context is used for kerning, even without AAT, hence the condition. */
42 #if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN)
43 
hb_aat_apply_context_t(const hb_ot_shape_plan_t * plan_,hb_font_t * font_,hb_buffer_t * buffer_,hb_blob_t * blob)44 AAT::hb_aat_apply_context_t::hb_aat_apply_context_t(const hb_ot_shape_plan_t *plan_,
45                                                     hb_font_t *font_,
46                                                     hb_buffer_t *buffer_,
47                                                     hb_blob_t *blob)
48     : plan(plan_)
49     , font(font_)
50     , face(font->face)
51     , buffer(buffer_)
52     , sanitizer()
53     , ankr_table(&Null(AAT::ankr))
54     , lookup_index(0)
55 {
56     sanitizer.init(blob);
57     sanitizer.set_num_glyphs(face->get_num_glyphs());
58     sanitizer.start_processing();
59     sanitizer.set_max_ops(HB_SANITIZE_MAX_OPS_MAX);
60 }
61 
~hb_aat_apply_context_t()62 AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t()
63 {
64     sanitizer.end_processing();
65 }
66 
set_ankr_table(const AAT::ankr * ankr_table_)67 void AAT::hb_aat_apply_context_t::set_ankr_table(const AAT::ankr *ankr_table_)
68 {
69     ankr_table = ankr_table_;
70 }
71 
72 #endif
73 
74 /**
75  * SECTION:hb-aat-layout
76  * @title: hb-aat-layout
77  * @short_description: Apple Advanced Typography Layout
78  * @include: hb-aat.h
79  *
80  * Functions for querying OpenType Layout features in the font face.
81  **/
82 
83 #if !defined(HB_NO_AAT) || defined(HAVE_CORETEXT)
84 
85 /* Table data courtesy of Apple.  Converted from mnemonics to integers
86  * when moving to this file. */
87 static const hb_aat_feature_mapping_t feature_mappings[] = {
88     {HB_TAG('a', 'f', 'r', 'c'),
89      HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,
90      HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS,
91      HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
92     {HB_TAG('c', '2', 'p', 'c'),
93      HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,
94      HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS,
95      HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
96     {HB_TAG('c', '2', 's', 'c'),
97      HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,
98      HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS,
99      HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
100     {HB_TAG('c', 'a', 'l', 't'),
101      HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES,
102      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON,
103      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF},
104     {HB_TAG('c', 'a', 's', 'e'),
105      HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,
106      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON,
107      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF},
108     {HB_TAG('c', 'l', 'i', 'g'),
109      HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,
110      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON,
111      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF},
112     {HB_TAG('c', 'p', 's', 'p'),
113      HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,
114      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON,
115      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF},
116     {HB_TAG('c', 's', 'w', 'h'),
117      HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES,
118      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON,
119      HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF},
120     {HB_TAG('d', 'l', 'i', 'g'),
121      HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,
122      HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON,
123      HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF},
124     {HB_TAG('e', 'x', 'p', 't'),
125      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
126      HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS,
127      (hb_aat_layout_feature_selector_t)16},
128     {HB_TAG('f', 'r', 'a', 'c'),
129      HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,
130      HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS,
131      HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
132     {HB_TAG('f', 'w', 'i', 'd'),
133      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
134      HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT,
135      (hb_aat_layout_feature_selector_t)7},
136     {HB_TAG('h', 'a', 'l', 't'),
137      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
138      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,
139      (hb_aat_layout_feature_selector_t)7},
140     {HB_TAG('h', 'i', 's', 't'),
141      HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,
142      HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,
143      HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
144     {HB_TAG('h', 'k', 'n', 'a'),
145      HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,
146      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON,
147      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
148     {HB_TAG('h', 'l', 'i', 'g'),
149      HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,
150      HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,
151      HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
152     {HB_TAG('h', 'n', 'g', 'l'),
153      HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION,
154      HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL,
155      HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
156     {HB_TAG('h', 'o', 'j', 'o'),
157      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
158      HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS,
159      (hb_aat_layout_feature_selector_t)16},
160     {HB_TAG('h', 'w', 'i', 'd'),
161      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
162      HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT,
163      (hb_aat_layout_feature_selector_t)7},
164     {HB_TAG('i', 't', 'a', 'l'),
165      HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN,
166      HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON,
167      HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF},
168     {HB_TAG('j', 'p', '0', '4'),
169      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
170      HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS,
171      (hb_aat_layout_feature_selector_t)16},
172     {HB_TAG('j', 'p', '7', '8'),
173      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
174      HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS,
175      (hb_aat_layout_feature_selector_t)16},
176     {HB_TAG('j', 'p', '8', '3'),
177      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
178      HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS,
179      (hb_aat_layout_feature_selector_t)16},
180     {HB_TAG('j', 'p', '9', '0'),
181      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
182      HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS,
183      (hb_aat_layout_feature_selector_t)16},
184     {HB_TAG('l', 'i', 'g', 'a'),
185      HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,
186      HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON,
187      HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF},
188     {HB_TAG('l', 'n', 'u', 'm'),
189      HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,
190      HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS,
191      (hb_aat_layout_feature_selector_t)2},
192     {HB_TAG('m', 'g', 'r', 'k'),
193      HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS,
194      HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON,
195      HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF},
196     {HB_TAG('n', 'l', 'c', 'k'),
197      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
198      HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS,
199      (hb_aat_layout_feature_selector_t)16},
200     {HB_TAG('o', 'n', 'u', 'm'),
201      HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,
202      HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS,
203      (hb_aat_layout_feature_selector_t)2},
204     {HB_TAG('o', 'r', 'd', 'n'),
205      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,
206      HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS,
207      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
208     {HB_TAG('p', 'a', 'l', 't'),
209      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
210      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,
211      (hb_aat_layout_feature_selector_t)7},
212     {HB_TAG('p', 'c', 'a', 'p'),
213      HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,
214      HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS,
215      HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
216     {HB_TAG('p', 'k', 'n', 'a'),
217      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
218      HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,
219      (hb_aat_layout_feature_selector_t)7},
220     {HB_TAG('p', 'n', 'u', 'm'),
221      HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,
222      HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS,
223      (hb_aat_layout_feature_selector_t)4},
224     {HB_TAG('p', 'w', 'i', 'd'),
225      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
226      HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,
227      (hb_aat_layout_feature_selector_t)7},
228     {HB_TAG('q', 'w', 'i', 'd'),
229      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
230      HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT,
231      (hb_aat_layout_feature_selector_t)7},
232     {HB_TAG('r', 'u', 'b', 'y'),
233      HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA,
234      HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON,
235      HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
236     {HB_TAG('s', 'i', 'n', 'f'),
237      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,
238      HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS,
239      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
240     {HB_TAG('s', 'm', 'c', 'p'),
241      HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,
242      HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS,
243      HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
244     {HB_TAG('s', 'm', 'p', 'l'),
245      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
246      HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS,
247      (hb_aat_layout_feature_selector_t)16},
248     {HB_TAG('s', 's', '0', '1'),
249      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
250      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON,
251      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF},
252     {HB_TAG('s', 's', '0', '2'),
253      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
254      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON,
255      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF},
256     {HB_TAG('s', 's', '0', '3'),
257      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
258      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON,
259      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF},
260     {HB_TAG('s', 's', '0', '4'),
261      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
262      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON,
263      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF},
264     {HB_TAG('s', 's', '0', '5'),
265      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
266      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON,
267      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF},
268     {HB_TAG('s', 's', '0', '6'),
269      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
270      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON,
271      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF},
272     {HB_TAG('s', 's', '0', '7'),
273      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
274      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON,
275      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF},
276     {HB_TAG('s', 's', '0', '8'),
277      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
278      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON,
279      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF},
280     {HB_TAG('s', 's', '0', '9'),
281      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
282      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON,
283      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF},
284     {HB_TAG('s', 's', '1', '0'),
285      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
286      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON,
287      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF},
288     {HB_TAG('s', 's', '1', '1'),
289      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
290      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON,
291      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF},
292     {HB_TAG('s', 's', '1', '2'),
293      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
294      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON,
295      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF},
296     {HB_TAG('s', 's', '1', '3'),
297      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
298      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON,
299      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF},
300     {HB_TAG('s', 's', '1', '4'),
301      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
302      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON,
303      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF},
304     {HB_TAG('s', 's', '1', '5'),
305      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
306      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON,
307      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF},
308     {HB_TAG('s', 's', '1', '6'),
309      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
310      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON,
311      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF},
312     {HB_TAG('s', 's', '1', '7'),
313      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
314      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON,
315      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF},
316     {HB_TAG('s', 's', '1', '8'),
317      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
318      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON,
319      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF},
320     {HB_TAG('s', 's', '1', '9'),
321      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
322      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON,
323      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF},
324     {HB_TAG('s', 's', '2', '0'),
325      HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,
326      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON,
327      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF},
328     {HB_TAG('s', 'u', 'b', 's'),
329      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,
330      HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS,
331      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
332     {HB_TAG('s', 'u', 'p', 's'),
333      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,
334      HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS,
335      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
336     {HB_TAG('s', 'w', 's', 'h'),
337      HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES,
338      HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON,
339      HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF},
340     {HB_TAG('t', 'i', 't', 'l'),
341      HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS,
342      HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS,
343      HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS},
344     {HB_TAG('t', 'n', 'a', 'm'),
345      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
346      HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS,
347      (hb_aat_layout_feature_selector_t)16},
348     {HB_TAG('t', 'n', 'u', 'm'),
349      HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,
350      HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS,
351      (hb_aat_layout_feature_selector_t)4},
352     {HB_TAG('t', 'r', 'a', 'd'),
353      HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,
354      HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS,
355      (hb_aat_layout_feature_selector_t)16},
356     {HB_TAG('t', 'w', 'i', 'd'),
357      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
358      HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT,
359      (hb_aat_layout_feature_selector_t)7},
360     {HB_TAG('u', 'n', 'i', 'c'),
361      HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE,
362      (hb_aat_layout_feature_selector_t)14,
363      (hb_aat_layout_feature_selector_t)15},
364     {HB_TAG('v', 'a', 'l', 't'),
365      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
366      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,
367      (hb_aat_layout_feature_selector_t)7},
368     {HB_TAG('v', 'e', 'r', 't'),
369      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,
370      HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,
371      HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
372     {HB_TAG('v', 'h', 'a', 'l'),
373      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
374      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,
375      (hb_aat_layout_feature_selector_t)7},
376     {HB_TAG('v', 'k', 'n', 'a'),
377      HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,
378      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON,
379      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
380     {HB_TAG('v', 'p', 'a', 'l'),
381      HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,
382      HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,
383      (hb_aat_layout_feature_selector_t)7},
384     {HB_TAG('v', 'r', 't', '2'),
385      HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,
386      HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,
387      HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
388     {HB_TAG('z', 'e', 'r', 'o'),
389      HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,
390      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,
391      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
392 };
393 
hb_aat_layout_find_feature_mapping(hb_tag_t tag)394 const hb_aat_feature_mapping_t *hb_aat_layout_find_feature_mapping(hb_tag_t tag)
395 {
396     return hb_sorted_array(feature_mappings).bsearch(tag);
397 }
398 #endif
399 
400 #ifndef HB_NO_AAT
401 
402 /*
403  * mort/morx/kerx/trak
404  */
405 
hb_aat_layout_compile_map(const hb_aat_map_builder_t * mapper,hb_aat_map_t * map)406 void hb_aat_layout_compile_map(const hb_aat_map_builder_t *mapper, hb_aat_map_t *map)
407 {
408     const AAT::morx &morx = *mapper->face->table.morx;
409     if (morx.has_data()) {
410         morx.compile_flags(mapper, map);
411         return;
412     }
413 
414     const AAT::mort &mort = *mapper->face->table.mort;
415     if (mort.has_data()) {
416         mort.compile_flags(mapper, map);
417         return;
418     }
419 }
420 
421 /*
422  * hb_aat_layout_has_substitution:
423  * @face:
424  *
425  * Returns:
426  * Since: 2.3.0
427  */
hb_aat_layout_has_substitution(hb_face_t * face)428 hb_bool_t hb_aat_layout_has_substitution(hb_face_t *face)
429 {
430     return face->table.morx->has_data() || face->table.mort->has_data();
431 }
432 
hb_aat_layout_substitute(const hb_ot_shape_plan_t * plan,hb_font_t * font,hb_buffer_t * buffer)433 void hb_aat_layout_substitute(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
434 {
435     hb_blob_t *morx_blob = font->face->table.morx.get_blob();
436     const AAT::morx &morx = *morx_blob->as<AAT::morx>();
437     if (morx.has_data()) {
438         AAT::hb_aat_apply_context_t c(plan, font, buffer, morx_blob);
439         morx.apply(&c);
440         return;
441     }
442 
443     hb_blob_t *mort_blob = font->face->table.mort.get_blob();
444     const AAT::mort &mort = *mort_blob->as<AAT::mort>();
445     if (mort.has_data()) {
446         AAT::hb_aat_apply_context_t c(plan, font, buffer, mort_blob);
447         mort.apply(&c);
448         return;
449     }
450 }
451 
hb_aat_layout_zero_width_deleted_glyphs(hb_buffer_t * buffer)452 void hb_aat_layout_zero_width_deleted_glyphs(hb_buffer_t *buffer)
453 {
454     unsigned int count = buffer->len;
455     hb_glyph_info_t *info = buffer->info;
456     hb_glyph_position_t *pos = buffer->pos;
457     for (unsigned int i = 0; i < count; i++)
458         if (unlikely(info[i].codepoint == AAT::DELETED_GLYPH))
459             pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
460 }
461 
is_deleted_glyph(const hb_glyph_info_t * info)462 static bool is_deleted_glyph(const hb_glyph_info_t *info)
463 {
464     return info->codepoint == AAT::DELETED_GLYPH;
465 }
466 
hb_aat_layout_remove_deleted_glyphs(hb_buffer_t * buffer)467 void hb_aat_layout_remove_deleted_glyphs(hb_buffer_t *buffer)
468 {
469     hb_ot_layout_delete_glyphs_inplace(buffer, is_deleted_glyph);
470 }
471 
472 /*
473  * hb_aat_layout_has_positioning:
474  * @face:
475  *
476  * Returns:
477  * Since: 2.3.0
478  */
hb_aat_layout_has_positioning(hb_face_t * face)479 hb_bool_t hb_aat_layout_has_positioning(hb_face_t *face)
480 {
481     return face->table.kerx->has_data();
482 }
483 
hb_aat_layout_position(const hb_ot_shape_plan_t * plan,hb_font_t * font,hb_buffer_t * buffer)484 void hb_aat_layout_position(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
485 {
486     hb_blob_t *kerx_blob = font->face->table.kerx.get_blob();
487     const AAT::kerx &kerx = *kerx_blob->as<AAT::kerx>();
488 
489     AAT::hb_aat_apply_context_t c(plan, font, buffer, kerx_blob);
490     c.set_ankr_table(font->face->table.ankr.get());
491     kerx.apply(&c);
492 }
493 
494 /*
495  * hb_aat_layout_has_tracking:
496  * @face:
497  *
498  * Returns:
499  * Since: 2.3.0
500  */
hb_aat_layout_has_tracking(hb_face_t * face)501 hb_bool_t hb_aat_layout_has_tracking(hb_face_t *face)
502 {
503     return face->table.trak->has_data();
504 }
505 
hb_aat_layout_track(const hb_ot_shape_plan_t * plan,hb_font_t * font,hb_buffer_t * buffer)506 void hb_aat_layout_track(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
507 {
508     const AAT::trak &trak = *font->face->table.trak;
509 
510     AAT::hb_aat_apply_context_t c(plan, font, buffer);
511     trak.apply(&c);
512 }
513 
514 /**
515  * hb_aat_layout_get_feature_types:
516  * @face: a face object
517  * @start_offset: iteration's start offset
518  * @feature_count:(inout) (allow-none): buffer size as input, filled size as output
519  * @features: (out caller-allocates) (array length=feature_count): features buffer
520  *
521  * Return value: Number of all available feature types.
522  *
523  * Since: 2.2.0
524  */
hb_aat_layout_get_feature_types(hb_face_t * face,unsigned int start_offset,unsigned int * feature_count,hb_aat_layout_feature_type_t * features)525 unsigned int hb_aat_layout_get_feature_types(hb_face_t *face,
526                                              unsigned int start_offset,
527                                              unsigned int *feature_count, /* IN/OUT.  May be NULL. */
528                                              hb_aat_layout_feature_type_t *features /* OUT.     May be NULL. */)
529 {
530     return face->table.feat->get_feature_types(start_offset, feature_count, features);
531 }
532 
533 /**
534  * hb_aat_layout_feature_type_get_name_id:
535  * @face: a face object
536  * @feature_type: feature id
537  *
538  * Return value: Name ID index
539  *
540  * Since: 2.2.0
541  */
hb_aat_layout_feature_type_get_name_id(hb_face_t * face,hb_aat_layout_feature_type_t feature_type)542 hb_ot_name_id_t hb_aat_layout_feature_type_get_name_id(hb_face_t *face, hb_aat_layout_feature_type_t feature_type)
543 {
544     return face->table.feat->get_feature_name_id(feature_type);
545 }
546 
547 /**
548  * hb_aat_layout_feature_type_get_selectors:
549  * @face:    a face object
550  * @feature_type: feature id
551  * @start_offset:    iteration's start offset
552  * @selector_count: (inout) (allow-none): buffer size as input, filled size as output
553  * @selectors: (out caller-allocates) (array length=selector_count): settings buffer
554  * @default_index: (out) (allow-none): index of default selector if any
555  *
556  * If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then
557  * the feature type is non-exclusive.  Otherwise, @default_index is the index of
558  * the selector that is selected by default.
559  *
560  * Return value: Number of all available feature selectors.
561  *
562  * Since: 2.2.0
563  */
hb_aat_layout_feature_type_get_selector_infos(hb_face_t * face,hb_aat_layout_feature_type_t feature_type,unsigned int start_offset,unsigned int * selector_count,hb_aat_layout_feature_selector_info_t * selectors,unsigned int * default_index)564 unsigned int hb_aat_layout_feature_type_get_selector_infos(
565     hb_face_t *face,
566     hb_aat_layout_feature_type_t feature_type,
567     unsigned int start_offset,
568     unsigned int *selector_count,                     /* IN/OUT.  May be NULL. */
569     hb_aat_layout_feature_selector_info_t *selectors, /* OUT.     May be NULL. */
570     unsigned int *default_index /* OUT.     May be NULL. */)
571 {
572     return face->table.feat->get_selector_infos(feature_type, start_offset, selector_count, selectors, default_index);
573 }
574 
575 #endif
576