OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 1998-2004 David Turner and Werner Lemberg | 2 * Copyright © 1998-2004 David Turner and Werner Lemberg |
3 * Copyright © 2006 Behdad Esfahbod | 3 * Copyright © 2006 Behdad Esfahbod |
4 * Copyright © 2007,2008,2009 Red Hat, Inc. | 4 * Copyright © 2007,2008,2009 Red Hat, Inc. |
| 5 * Copyright © 2012 Google, Inc. |
5 * | 6 * |
6 * This is part of HarfBuzz, a text shaping library. | 7 * This is part of HarfBuzz, a text shaping library. |
7 * | 8 * |
8 * Permission is hereby granted, without written agreement and without | 9 * Permission is hereby granted, without written agreement and without |
9 * license or royalty fees, to use, copy, modify, and distribute this | 10 * license or royalty fees, to use, copy, modify, and distribute this |
10 * software and its documentation for any purpose, provided that the | 11 * software and its documentation for any purpose, provided that the |
11 * above copyright notice and the following two paragraphs appear in | 12 * above copyright notice and the following two paragraphs appear in |
12 * all copies of this software. | 13 * all copies of this software. |
13 * | 14 * |
14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 16 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 17 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 18 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
18 * DAMAGE. | 19 * DAMAGE. |
19 * | 20 * |
20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 21 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 22 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 23 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 24 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 25 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
25 * | 26 * |
26 * Red Hat Author(s): Behdad Esfahbod | 27 * Red Hat Author(s): Behdad Esfahbod |
| 28 * Google Author(s): Behdad Esfahbod |
27 */ | 29 */ |
28 | 30 |
29 #include "hb-ot-layout-private.hh" | 31 #include "hb-ot-layout-private.hh" |
30 | 32 |
31 #include "hb-ot-layout-gdef-table.hh" | 33 #include "hb-ot-layout-gdef-table.hh" |
32 #include "hb-ot-layout-gsub-table.hh" | 34 #include "hb-ot-layout-gsub-table.hh" |
33 #include "hb-ot-layout-gpos-table.hh" | 35 #include "hb-ot-layout-gpos-table.hh" |
34 #include "hb-ot-maxp-table.hh" | 36 #include "hb-ot-maxp-table.hh" |
35 | 37 |
36 | |
37 #include <stdlib.h> | 38 #include <stdlib.h> |
38 #include <string.h> | 39 #include <string.h> |
39 | 40 |
40 | 41 |
| 42 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) |
41 | 43 |
42 hb_ot_layout_t * | 44 hb_ot_layout_t * |
43 _hb_ot_layout_create (hb_face_t *face) | 45 _hb_ot_layout_create (hb_face_t *face) |
44 { | 46 { |
45 /* TODO Remove this object altogether */ | |
46 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); | 47 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); |
| 48 if (unlikely (!layout)) |
| 49 return NULL; |
47 | 50 |
48 layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_reference_table (face,
HB_OT_TAG_GDEF)); | 51 layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (
HB_OT_TAG_GDEF)); |
49 layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob); | 52 layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); |
50 | 53 |
51 layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_reference_table (face,
HB_OT_TAG_GSUB)); | 54 layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (
HB_OT_TAG_GSUB)); |
52 layout->gsub = Sanitizer<GSUB>::lock_instance (layout->gsub_blob); | 55 layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob); |
53 | 56 |
54 layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_reference_table (face,
HB_OT_TAG_GPOS)); | 57 layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (
HB_OT_TAG_GPOS)); |
55 layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob); | 58 layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); |
| 59 |
| 60 layout->gsub_lookup_count = layout->gsub->get_lookup_count (); |
| 61 layout->gpos_lookup_count = layout->gpos->get_lookup_count (); |
| 62 |
| 63 layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_co
unt (), sizeof (hb_set_digest_t)); |
| 64 layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_co
unt (), sizeof (hb_set_digest_t)); |
| 65 |
| 66 if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) || |
| 67 » » (layout->gpos_lookup_count && !layout->gpos_digests))) |
| 68 { |
| 69 _hb_ot_layout_destroy (layout); |
| 70 return NULL; |
| 71 } |
| 72 |
| 73 for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) |
| 74 layout->gsub->add_coverage (&layout->gsub_digests[i], i); |
| 75 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) |
| 76 layout->gpos->add_coverage (&layout->gpos_digests[i], i); |
56 | 77 |
57 return layout; | 78 return layout; |
58 } | 79 } |
59 | 80 |
60 void | 81 void |
61 _hb_ot_layout_destroy (hb_ot_layout_t *layout) | 82 _hb_ot_layout_destroy (hb_ot_layout_t *layout) |
62 { | 83 { |
63 hb_blob_destroy (layout->gdef_blob); | 84 hb_blob_destroy (layout->gdef_blob); |
64 hb_blob_destroy (layout->gsub_blob); | 85 hb_blob_destroy (layout->gsub_blob); |
65 hb_blob_destroy (layout->gpos_blob); | 86 hb_blob_destroy (layout->gpos_blob); |
66 | 87 |
| 88 free (layout->gsub_digests); |
| 89 free (layout->gpos_digests); |
| 90 |
67 free (layout); | 91 free (layout); |
68 } | 92 } |
69 | 93 |
70 static inline const GDEF& | 94 static inline const OT::GDEF& |
71 _get_gdef (hb_face_t *face) | 95 _get_gdef (hb_face_t *face) |
72 { | 96 { |
73 return likely (face->ot_layout && face->ot_layout->gdef) ? *face->ot_layout->g
def : Null(GDEF); | 97 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF
); |
| 98 return *hb_ot_layout_from_face (face)->gdef; |
74 } | 99 } |
75 static inline const GSUB& | 100 static inline const OT::GSUB& |
76 _get_gsub (hb_face_t *face) | 101 _get_gsub (hb_face_t *face) |
77 { | 102 { |
78 return likely (face->ot_layout && face->ot_layout->gsub) ? *face->ot_layout->g
sub : Null(GSUB); | 103 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB
); |
| 104 return *hb_ot_layout_from_face (face)->gsub; |
79 } | 105 } |
80 static inline const GPOS& | 106 static inline const OT::GPOS& |
81 _get_gpos (hb_face_t *face) | 107 _get_gpos (hb_face_t *face) |
82 { | 108 { |
83 return likely (face->ot_layout && face->ot_layout->gpos) ? *face->ot_layout->g
pos : Null(GPOS); | 109 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS
); |
| 110 return *hb_ot_layout_from_face (face)->gpos; |
84 } | 111 } |
85 | 112 |
86 | 113 |
87 /* | 114 /* |
88 * GDEF | 115 * GDEF |
89 */ | 116 */ |
90 | 117 |
91 hb_bool_t | 118 hb_bool_t |
92 hb_ot_layout_has_glyph_classes (hb_face_t *face) | 119 hb_ot_layout_has_glyph_classes (hb_face_t *face) |
93 { | 120 { |
94 return _get_gdef (face).has_glyph_classes (); | 121 return _get_gdef (face).has_glyph_classes (); |
95 } | 122 } |
96 | 123 |
97 unsigned int | |
98 _hb_ot_layout_get_glyph_property (hb_face_t *face, | |
99 hb_glyph_info_t *info) | |
100 { | |
101 if (!info->props_cache()) | |
102 { | |
103 const GDEF &gdef = _get_gdef (face); | |
104 info->props_cache() = gdef.get_glyph_props (info->codepoint); | |
105 } | |
106 | |
107 return info->props_cache(); | |
108 } | |
109 | |
110 static hb_bool_t | |
111 _hb_ot_layout_match_properties (hb_face_t *face, | |
112 hb_codepoint_t codepoint, | |
113 unsigned int glyph_props, | |
114 unsigned int lookup_props) | |
115 { | |
116 /* Not covered, if, for example, glyph class is ligature and | |
117 * lookup_props includes LookupFlags::IgnoreLigatures | |
118 */ | |
119 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) | |
120 return false; | |
121 | |
122 if (glyph_props & HB_OT_LAYOUT_GLYPH_CLASS_MARK) | |
123 { | |
124 /* If using mark filtering sets, the high short of | |
125 * lookup_props has the set index. | |
126 */ | |
127 if (lookup_props & LookupFlag::UseMarkFilteringSet) | |
128 return _get_gdef (face).mark_set_covers (lookup_props >> 16, codepoint); | |
129 | |
130 /* The second byte of lookup_props has the meaning | |
131 * "ignore marks of attachment type different than | |
132 * the attachment type specified." | |
133 */ | |
134 if (lookup_props & LookupFlag::MarkAttachmentType && glyph_props & LookupFla
g::MarkAttachmentType) | |
135 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & L
ookupFlag::MarkAttachmentType); | |
136 } | |
137 | |
138 return true; | |
139 } | |
140 | |
141 hb_bool_t | |
142 _hb_ot_layout_check_glyph_property (hb_face_t *face, | |
143 hb_glyph_info_t *ginfo, | |
144 unsigned int lookup_props, | |
145 unsigned int *property_out) | |
146 { | |
147 unsigned int property; | |
148 | |
149 property = _hb_ot_layout_get_glyph_property (face, ginfo); | |
150 (void) (property_out && (*property_out = property)); | |
151 | |
152 return _hb_ot_layout_match_properties (face, ginfo->codepoint, property, looku
p_props); | |
153 } | |
154 | |
155 hb_bool_t | |
156 _hb_ot_layout_skip_mark (hb_face_t *face, | |
157 hb_glyph_info_t *ginfo, | |
158 unsigned int lookup_props, | |
159 unsigned int *property_out) | |
160 { | |
161 unsigned int property; | |
162 | |
163 property = _hb_ot_layout_get_glyph_property (face, ginfo); | |
164 (void) (property_out && (*property_out = property)); | |
165 | |
166 /* If it's a mark, skip it we don't accept it. */ | |
167 if (unlikely (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) | |
168 return !_hb_ot_layout_match_properties (face, ginfo->codepoint, property, lo
okup_props); | |
169 | |
170 /* If not a mark, don't skip. */ | |
171 return false; | |
172 } | |
173 | |
174 | |
175 | 124 |
176 unsigned int | 125 unsigned int |
177 hb_ot_layout_get_attach_points (hb_face_t *face, | 126 hb_ot_layout_get_attach_points (hb_face_t *face, |
178 hb_codepoint_t glyph, | 127 hb_codepoint_t glyph, |
179 unsigned int start_offset, | 128 unsigned int start_offset, |
180 unsigned int *point_count /* IN/OUT */, | 129 unsigned int *point_count /* IN/OUT */, |
181 unsigned int *point_array /* OUT */) | 130 unsigned int *point_array /* OUT */) |
182 { | 131 { |
183 return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, p
oint_array); | 132 return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, p
oint_array); |
184 } | 133 } |
185 | 134 |
186 unsigned int | 135 unsigned int |
187 hb_ot_layout_get_ligature_carets (hb_font_t *font, | 136 hb_ot_layout_get_ligature_carets (hb_font_t *font, |
188 hb_direction_t direction, | 137 hb_direction_t direction, |
189 hb_codepoint_t glyph, | 138 hb_codepoint_t glyph, |
190 unsigned int start_offset, | 139 unsigned int start_offset, |
191 unsigned int *caret_count /* IN/OUT */, | 140 unsigned int *caret_count /* IN/OUT */, |
192 int *caret_array /* OUT */) | 141 int *caret_array /* OUT */) |
193 { | 142 { |
194 return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_of
fset, caret_count, caret_array); | 143 return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_of
fset, caret_count, caret_array); |
195 } | 144 } |
196 | 145 |
| 146 |
197 /* | 147 /* |
198 * GSUB/GPOS | 148 * GSUB/GPOS |
199 */ | 149 */ |
200 | 150 |
201 static const GSUBGPOS& | 151 static const OT::GSUBGPOS& |
202 get_gsubgpos_table (hb_face_t *face, | 152 get_gsubgpos_table (hb_face_t *face, |
203 hb_tag_t table_tag) | 153 hb_tag_t table_tag) |
204 { | 154 { |
205 switch (table_tag) { | 155 switch (table_tag) { |
206 case HB_OT_TAG_GSUB: return _get_gsub (face); | 156 case HB_OT_TAG_GSUB: return _get_gsub (face); |
207 case HB_OT_TAG_GPOS: return _get_gpos (face); | 157 case HB_OT_TAG_GPOS: return _get_gpos (face); |
208 default: return Null(GSUBGPOS); | 158 default: return OT::Null(OT::GSUBGPOS); |
209 } | 159 } |
210 } | 160 } |
211 | 161 |
212 | 162 |
213 unsigned int | 163 unsigned int |
214 hb_ot_layout_table_get_script_tags (hb_face_t *face, | 164 hb_ot_layout_table_get_script_tags (hb_face_t *face, |
215 hb_tag_t table_tag, | 165 hb_tag_t table_tag, |
216 unsigned int start_offset, | 166 unsigned int start_offset, |
217 unsigned int *script_count /* IN/OUT */, | 167 unsigned int *script_count /* IN/OUT */, |
218 hb_tag_t *script_tags /* OUT */) | 168 hb_tag_t *script_tags /* OUT */) |
219 { | 169 { |
220 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 170 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
221 | 171 |
222 return g.get_script_tags (start_offset, script_count, script_tags); | 172 return g.get_script_tags (start_offset, script_count, script_tags); |
223 } | 173 } |
224 | 174 |
225 hb_bool_t | 175 hb_bool_t |
226 hb_ot_layout_table_find_script (hb_face_t *face, | 176 hb_ot_layout_table_find_script (hb_face_t *face, |
227 hb_tag_t table_tag, | 177 hb_tag_t table_tag, |
228 hb_tag_t script_tag, | 178 hb_tag_t script_tag, |
229 unsigned int *script_index) | 179 unsigned int *script_index) |
230 { | 180 { |
231 ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); | 181 ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); |
232 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 182 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
233 | 183 |
234 if (g.find_script_index (script_tag, script_index)) | 184 if (g.find_script_index (script_tag, script_index)) |
235 return true; | 185 return true; |
236 | 186 |
237 /* try finding 'DFLT' */ | 187 /* try finding 'DFLT' */ |
238 if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) | 188 if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) |
239 return false; | 189 return false; |
240 | 190 |
241 /* try with 'dflt'; MS site has had typos and many fonts use it now :(. | 191 /* try with 'dflt'; MS site has had typos and many fonts use it now :(. |
242 * including many versions of DejaVu Sans Mono! */ | 192 * including many versions of DejaVu Sans Mono! */ |
243 if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) | 193 if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) |
244 return false; | 194 return false; |
245 | 195 |
246 if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; | 196 if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; |
247 return false; | 197 return false; |
248 } | 198 } |
249 | 199 |
250 hb_bool_t | 200 hb_bool_t |
251 hb_ot_layout_table_choose_script (hb_face_t *face, | 201 hb_ot_layout_table_choose_script (hb_face_t *face, |
252 hb_tag_t table_tag, | 202 hb_tag_t table_tag, |
253 const hb_tag_t *script_tags, | 203 const hb_tag_t *script_tags, |
254 unsigned int *script_index, | 204 unsigned int *script_index, |
255 hb_tag_t *chosen_script) | 205 hb_tag_t *chosen_script) |
256 { | 206 { |
257 ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); | 207 ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); |
258 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 208 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
259 | 209 |
260 while (*script_tags) | 210 while (*script_tags) |
261 { | 211 { |
262 if (g.find_script_index (*script_tags, script_index)) { | 212 if (g.find_script_index (*script_tags, script_index)) { |
263 if (chosen_script) | 213 if (chosen_script) |
264 *chosen_script = *script_tags; | 214 *chosen_script = *script_tags; |
265 return true; | 215 return true; |
266 } | 216 } |
267 script_tags++; | 217 script_tags++; |
268 } | 218 } |
(...skipping 27 matching lines...) Expand all Loading... |
296 return false; | 246 return false; |
297 } | 247 } |
298 | 248 |
299 unsigned int | 249 unsigned int |
300 hb_ot_layout_table_get_feature_tags (hb_face_t *face, | 250 hb_ot_layout_table_get_feature_tags (hb_face_t *face, |
301 hb_tag_t table_tag, | 251 hb_tag_t table_tag, |
302 unsigned int start_offset, | 252 unsigned int start_offset, |
303 unsigned int *feature_count /* IN/OUT */, | 253 unsigned int *feature_count /* IN/OUT */, |
304 hb_tag_t *feature_tags /* OUT */) | 254 hb_tag_t *feature_tags /* OUT */) |
305 { | 255 { |
306 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 256 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
307 | 257 |
308 return g.get_feature_tags (start_offset, feature_count, feature_tags); | 258 return g.get_feature_tags (start_offset, feature_count, feature_tags); |
309 } | 259 } |
310 | 260 |
311 | 261 |
312 unsigned int | 262 unsigned int |
313 hb_ot_layout_script_get_language_tags (hb_face_t *face, | 263 hb_ot_layout_script_get_language_tags (hb_face_t *face, |
314 hb_tag_t table_tag, | 264 hb_tag_t table_tag, |
315 unsigned int script_index, | 265 unsigned int script_index, |
316 unsigned int start_offset, | 266 unsigned int start_offset, |
317 unsigned int *language_count /* IN/OUT */
, | 267 unsigned int *language_count /* IN/OUT */
, |
318 hb_tag_t *language_tags /* OUT */) | 268 hb_tag_t *language_tags /* OUT */) |
319 { | 269 { |
320 const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_inde
x); | 270 const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_
index); |
321 | 271 |
322 return s.get_lang_sys_tags (start_offset, language_count, language_tags); | 272 return s.get_lang_sys_tags (start_offset, language_count, language_tags); |
323 } | 273 } |
324 | 274 |
325 hb_bool_t | 275 hb_bool_t |
326 hb_ot_layout_script_find_language (hb_face_t *face, | 276 hb_ot_layout_script_find_language (hb_face_t *face, |
327 hb_tag_t table_tag, | 277 hb_tag_t table_tag, |
328 unsigned int script_index, | 278 unsigned int script_index, |
329 hb_tag_t language_tag, | 279 hb_tag_t language_tag, |
330 unsigned int *language_index) | 280 unsigned int *language_index) |
331 { | 281 { |
332 ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); | 282 ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_IND
EX); |
333 const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_inde
x); | 283 const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_
index); |
334 | 284 |
335 if (s.find_lang_sys_index (language_tag, language_index)) | 285 if (s.find_lang_sys_index (language_tag, language_index)) |
336 return true; | 286 return true; |
337 | 287 |
338 /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ | 288 /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ |
339 if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) | 289 if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) |
340 return false; | 290 return false; |
341 | 291 |
342 if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; | 292 if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; |
343 return false; | 293 return false; |
344 } | 294 } |
345 | 295 |
346 hb_bool_t | 296 hb_bool_t |
347 hb_ot_layout_language_get_required_feature_index (hb_face_t *face, | 297 hb_ot_layout_language_get_required_feature_index (hb_face_t *face, |
348 hb_tag_t table_tag, | 298 hb_tag_t table_tag, |
349 unsigned int script_index, | 299 unsigned int script_index, |
350 unsigned int language_index, | 300 unsigned int language_index, |
351 unsigned int *feature_index) | 301 unsigned int *feature_index) |
352 { | 302 { |
353 const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_ind
ex).get_lang_sys (language_index); | 303 const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script
_index).get_lang_sys (language_index); |
354 | 304 |
355 if (feature_index) *feature_index = l.get_required_feature_index (); | 305 if (feature_index) *feature_index = l.get_required_feature_index (); |
356 | 306 |
357 return l.has_required_feature (); | 307 return l.has_required_feature (); |
358 } | 308 } |
359 | 309 |
360 unsigned int | 310 unsigned int |
361 hb_ot_layout_language_get_feature_indexes (hb_face_t *face, | 311 hb_ot_layout_language_get_feature_indexes (hb_face_t *face, |
362 hb_tag_t table_tag, | 312 hb_tag_t table_tag, |
363 unsigned int script_index, | 313 unsigned int script_index, |
364 unsigned int language_index, | 314 unsigned int language_index, |
365 unsigned int start_offset, | 315 unsigned int start_offset, |
366 unsigned int *feature_count /* IN/OUT
*/, | 316 unsigned int *feature_count /* IN/OUT
*/, |
367 unsigned int *feature_indexes /* OUT
*/) | 317 unsigned int *feature_indexes /* OUT
*/) |
368 { | 318 { |
369 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 319 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
370 const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); | 320 const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_inde
x); |
371 | 321 |
372 return l.get_feature_indexes (start_offset, feature_count, feature_indexes); | 322 return l.get_feature_indexes (start_offset, feature_count, feature_indexes); |
373 } | 323 } |
374 | 324 |
375 unsigned int | 325 unsigned int |
376 hb_ot_layout_language_get_feature_tags (hb_face_t *face, | 326 hb_ot_layout_language_get_feature_tags (hb_face_t *face, |
377 hb_tag_t table_tag, | 327 hb_tag_t table_tag, |
378 unsigned int script_index, | 328 unsigned int script_index, |
379 unsigned int language_index, | 329 unsigned int language_index, |
380 unsigned int start_offset, | 330 unsigned int start_offset, |
381 unsigned int *feature_count /* IN/OUT */
, | 331 unsigned int *feature_count /* IN/OUT */
, |
382 hb_tag_t *feature_tags /* OUT */) | 332 hb_tag_t *feature_tags /* OUT */) |
383 { | 333 { |
384 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 334 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
385 const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); | 335 const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_inde
x); |
386 | 336 |
387 ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); | 337 ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); |
388 unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsign
ed int *) feature_tags); | 338 unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsign
ed int *) feature_tags); |
389 | 339 |
390 if (feature_tags) { | 340 if (feature_tags) { |
391 unsigned int count = *feature_count; | 341 unsigned int count = *feature_count; |
392 for (unsigned int i = 0; i < count; i++) | 342 for (unsigned int i = 0; i < count; i++) |
393 feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]); | 343 feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]); |
394 } | 344 } |
395 | 345 |
396 return ret; | 346 return ret; |
397 } | 347 } |
398 | 348 |
399 | 349 |
400 hb_bool_t | 350 hb_bool_t |
401 hb_ot_layout_language_find_feature (hb_face_t *face, | 351 hb_ot_layout_language_find_feature (hb_face_t *face, |
402 hb_tag_t table_tag, | 352 hb_tag_t table_tag, |
403 unsigned int script_index, | 353 unsigned int script_index, |
404 unsigned int language_index, | 354 unsigned int language_index, |
405 hb_tag_t feature_tag, | 355 hb_tag_t feature_tag, |
406 unsigned int *feature_index) | 356 unsigned int *feature_index) |
407 { | 357 { |
408 ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); | 358 ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); |
409 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 359 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
410 const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); | 360 const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_inde
x); |
411 | 361 |
412 unsigned int num_features = l.get_feature_count (); | 362 unsigned int num_features = l.get_feature_count (); |
413 for (unsigned int i = 0; i < num_features; i++) { | 363 for (unsigned int i = 0; i < num_features; i++) { |
414 unsigned int f_index = l.get_feature_index (i); | 364 unsigned int f_index = l.get_feature_index (i); |
415 | 365 |
416 if (feature_tag == g.get_feature_tag (f_index)) { | 366 if (feature_tag == g.get_feature_tag (f_index)) { |
417 if (feature_index) *feature_index = f_index; | 367 if (feature_index) *feature_index = f_index; |
418 return true; | 368 return true; |
419 } | 369 } |
420 } | 370 } |
421 | 371 |
422 if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; | 372 if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; |
423 return false; | 373 return false; |
424 } | 374 } |
425 | 375 |
426 unsigned int | 376 unsigned int |
427 hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face, | 377 hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face, |
428 hb_tag_t table_tag, | 378 hb_tag_t table_tag, |
429 unsigned int feature_index, | 379 unsigned int feature_index, |
430 unsigned int start_offset, | 380 unsigned int start_offset, |
431 unsigned int *lookup_count /* IN/OUT */
, | 381 unsigned int *lookup_count /* IN/OUT */
, |
432 unsigned int *lookup_indexes /* OUT */) | 382 unsigned int *lookup_indexes /* OUT */) |
433 { | 383 { |
434 const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 384 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
435 const Feature &f = g.get_feature (feature_index); | 385 const OT::Feature &f = g.get_feature (feature_index); |
436 | 386 |
437 return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); | 387 return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); |
438 } | 388 } |
439 | 389 |
440 | 390 |
441 /* | 391 /* |
442 * GSUB | 392 * OT::GSUB |
443 */ | 393 */ |
444 | 394 |
445 hb_bool_t | 395 hb_bool_t |
446 hb_ot_layout_has_substitution (hb_face_t *face) | 396 hb_ot_layout_has_substitution (hb_face_t *face) |
447 { | 397 { |
448 return &_get_gsub (face) != &Null(GSUB); | 398 return &_get_gsub (face) != &OT::Null(OT::GSUB); |
| 399 } |
| 400 |
| 401 hb_bool_t |
| 402 hb_ot_layout_would_substitute_lookup (hb_face_t *face, |
| 403 » » » » unsigned int lookup_index, |
| 404 » » » » const hb_codepoint_t *glyphs, |
| 405 » » » » unsigned int glyphs_length, |
| 406 » » » » hb_bool_t zero_context) |
| 407 { |
| 408 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false; |
| 409 return hb_ot_layout_would_substitute_lookup_fast (face, lookup_index, glyphs,
glyphs_length, zero_context); |
| 410 } |
| 411 |
| 412 hb_bool_t |
| 413 hb_ot_layout_would_substitute_lookup_fast (hb_face_t *face, |
| 414 » » » » » unsigned int lookup_index, |
| 415 » » » » » const hb_codepoint_t *glyphs, |
| 416 » » » » » unsigned int glyphs_length, |
| 417 » » » » » hb_bool_t zero_context) |
| 418 { |
| 419 if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count
)) return false; |
| 420 OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); |
| 421 |
| 422 const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lo
okup_index); |
| 423 |
| 424 return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_
index]); |
449 } | 425 } |
450 | 426 |
451 void | 427 void |
452 hb_ot_layout_substitute_start (hb_buffer_t *buffer) | 428 hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) |
453 { | 429 { |
454 GSUB::substitute_start (buffer); | 430 OT::GSUB::substitute_start (font, buffer); |
455 } | 431 } |
456 | 432 |
457 hb_bool_t | 433 hb_bool_t |
458 hb_ot_layout_substitute_lookup (hb_face_t *face, | 434 hb_ot_layout_substitute_lookup (hb_font_t *font, |
459 hb_buffer_t *buffer, | 435 hb_buffer_t *buffer, |
460 unsigned int lookup_index, | 436 unsigned int lookup_index, |
461 hb_mask_t mask) | 437 hb_mask_t mask) |
462 { | 438 { |
463 hb_apply_context_t c (NULL, face, buffer, mask); | 439 if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup
_count)) return false; |
464 return _get_gsub (face).substitute_lookup (&c, lookup_index); | 440 |
| 441 OT::hb_apply_context_t c (font, buffer, mask); |
| 442 |
| 443 const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_look
up (lookup_index); |
| 444 |
| 445 return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[
lookup_index]); |
465 } | 446 } |
466 | 447 |
467 void | 448 void |
468 hb_ot_layout_substitute_finish (hb_buffer_t *buffer HB_UNUSED) | 449 hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) |
469 { | 450 { |
470 GSUB::substitute_finish (buffer); | 451 OT::GSUB::substitute_finish (font, buffer); |
471 } | 452 } |
472 | 453 |
473 void | 454 void |
474 hb_ot_layout_substitute_closure_lookup (hb_face_t *face, | 455 hb_ot_layout_substitute_closure_lookup (hb_face_t *face, |
475 » » » » hb_set_t *glyphs, | 456 » » » » unsigned int lookup_index, |
476 » » » » unsigned int lookup_index) | 457 » » » » hb_set_t *glyphs) |
477 { | 458 { |
478 hb_closure_context_t c (face, glyphs); | 459 OT::hb_closure_context_t c (face, glyphs); |
479 _get_gsub (face).closure_lookup (&c, lookup_index); | 460 _get_gsub (face).closure_lookup (&c, lookup_index); |
480 } | 461 } |
481 | 462 |
482 /* | 463 /* |
483 * GPOS | 464 * OT::GPOS |
484 */ | 465 */ |
485 | 466 |
486 hb_bool_t | 467 hb_bool_t |
487 hb_ot_layout_has_positioning (hb_face_t *face) | 468 hb_ot_layout_has_positioning (hb_face_t *face) |
488 { | 469 { |
489 return &_get_gpos (face) != &Null(GPOS); | 470 return &_get_gpos (face) != &OT::Null(OT::GPOS); |
490 } | 471 } |
491 | 472 |
492 void | 473 void |
493 hb_ot_layout_position_start (hb_buffer_t *buffer) | 474 hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) |
494 { | 475 { |
495 GPOS::position_start (buffer); | 476 OT::GPOS::position_start (font, buffer); |
496 } | 477 } |
497 | 478 |
498 hb_bool_t | 479 hb_bool_t |
499 hb_ot_layout_position_lookup (hb_font_t *font, | 480 hb_ot_layout_position_lookup (hb_font_t *font, |
500 » » » » hb_buffer_t *buffer, | 481 » » » hb_buffer_t *buffer, |
501 » » » » unsigned int lookup_index, | 482 » » » unsigned int lookup_index, |
502 » » » » hb_mask_t mask) | 483 » » » hb_mask_t mask) |
503 { | 484 { |
504 hb_apply_context_t c (font, font->face, buffer, mask); | 485 if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup
_count)) return false; |
505 return _get_gpos (font->face).position_lookup (&c, lookup_index); | 486 |
| 487 OT::hb_apply_context_t c (font, buffer, mask); |
| 488 |
| 489 const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup
(lookup_index); |
| 490 |
| 491 return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[
lookup_index]); |
506 } | 492 } |
507 | 493 |
508 void | 494 void |
509 hb_ot_layout_position_finish (hb_buffer_t *buffer) | 495 hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t ze
ro_width_attached_marks) |
510 { | 496 { |
511 GPOS::position_finish (buffer); | 497 OT::GPOS::position_finish (font, buffer, zero_width_attached_marks); |
512 } | 498 } |
513 | |
514 | |
OLD | NEW |