OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2009,2010 Red Hat, Inc. | 2 * Copyright © 2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2011,2013 Google, Inc. | 3 * Copyright © 2010,2011,2013 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 found_script[table_index] = hb_ot_layout_table_choose_script (face, table_ta
g, script_tags, &script_index[table_index], &chosen_script[table_index]); | 92 found_script[table_index] = hb_ot_layout_table_choose_script (face, table_ta
g, script_tags, &script_index[table_index], &chosen_script[table_index]); |
93 hb_ot_layout_script_find_language (face, table_tag, script_index[table_index
], language_tag, &language_index[table_index]); | 93 hb_ot_layout_script_find_language (face, table_tag, script_index[table_index
], language_tag, &language_index[table_index]); |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, | 97 void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, |
98 hb_ot_map_feature_flags_t flags) | 98 hb_ot_map_feature_flags_t flags) |
99 { | 99 { |
100 feature_info_t *info = feature_infos.push(); | 100 feature_info_t *info = feature_infos.push(); |
101 if (unlikely (!info)) return; | 101 if (unlikely (!info)) return; |
| 102 if (unlikely (!tag)) return; |
102 info->tag = tag; | 103 info->tag = tag; |
103 info->seq = feature_infos.len; | 104 info->seq = feature_infos.len; |
104 info->max_value = value; | 105 info->max_value = value; |
105 info->flags = flags; | 106 info->flags = flags; |
106 info->default_value = (flags & F_GLOBAL) ? value : 0; | 107 info->default_value = (flags & F_GLOBAL) ? value : 0; |
107 info->stage[0] = current_stage[0]; | 108 info->stage[0] = current_stage[0]; |
108 info->stage[1] = current_stage[1]; | 109 info->stage[1] = current_stage[1]; |
109 } | 110 } |
110 | 111 |
111 | 112 |
(...skipping 12 matching lines...) Expand all Loading... |
124 } | 125 } |
125 | 126 |
126 current_stage[table_index]++; | 127 current_stage[table_index]++; |
127 } | 128 } |
128 | 129 |
129 void | 130 void |
130 hb_ot_map_builder_t::compile (hb_ot_map_t &m) | 131 hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
131 { | 132 { |
132 m.global_mask = 1; | 133 m.global_mask = 1; |
133 | 134 |
134 for (unsigned int table_index = 0; table_index < 2; table_index++) { | 135 unsigned int required_feature_index[2]; |
| 136 hb_tag_t required_feature_tag[2]; |
| 137 /* We default to applying required feature in stage 0. If the required |
| 138 * feature has a tag that is known to the shaper, we apply required feature |
| 139 * in the stage for that tag. |
| 140 */ |
| 141 unsigned int required_feature_stage[2] = {0, 0}; |
| 142 |
| 143 for (unsigned int table_index = 0; table_index < 2; table_index++) |
| 144 { |
135 m.chosen_script[table_index] = chosen_script[table_index]; | 145 m.chosen_script[table_index] = chosen_script[table_index]; |
136 m.found_script[table_index] = found_script[table_index]; | 146 m.found_script[table_index] = found_script[table_index]; |
| 147 |
| 148 hb_ot_layout_language_get_required_feature (face, |
| 149 table_tags[table_index], |
| 150 script_index[table_index], |
| 151 language_index[table_index], |
| 152 &required_feature_index[table_in
dex], |
| 153 &required_feature_tag[table_inde
x]); |
137 } | 154 } |
138 | 155 |
139 if (!feature_infos.len) | 156 if (!feature_infos.len) |
140 return; | 157 return; |
141 | 158 |
142 /* Sort features and merge duplicates */ | 159 /* Sort features and merge duplicates */ |
143 { | 160 { |
144 feature_infos.sort (); | 161 feature_infos.qsort (); |
145 unsigned int j = 0; | 162 unsigned int j = 0; |
146 for (unsigned int i = 1; i < feature_infos.len; i++) | 163 for (unsigned int i = 1; i < feature_infos.len; i++) |
147 if (feature_infos[i].tag != feature_infos[j].tag) | 164 if (feature_infos[i].tag != feature_infos[j].tag) |
148 feature_infos[++j] = feature_infos[i]; | 165 feature_infos[++j] = feature_infos[i]; |
149 else { | 166 else { |
150 if (feature_infos[i].flags & F_GLOBAL) { | 167 if (feature_infos[i].flags & F_GLOBAL) { |
151 feature_infos[j].flags |= F_GLOBAL; | 168 feature_infos[j].flags |= F_GLOBAL; |
152 feature_infos[j].max_value = feature_infos[i].max_value; | 169 feature_infos[j].max_value = feature_infos[i].max_value; |
153 feature_infos[j].default_value = feature_infos[i].default_value; | 170 feature_infos[j].default_value = feature_infos[i].default_value; |
154 } else { | 171 } else { |
155 feature_infos[j].flags &= ~F_GLOBAL; | 172 feature_infos[j].flags &= ~F_GLOBAL; |
156 feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_
infos[i].max_value); | 173 feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_
infos[i].max_value); |
157 /* Inherit default_value from j */ | 174 /* Inherit default_value from j */ |
158 } | 175 } |
159 feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK); | 176 feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK); |
160 feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_info
s[i].stage[0]); | 177 feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_info
s[i].stage[0]); |
161 feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_info
s[i].stage[1]); | 178 feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_info
s[i].stage[1]); |
162 } | 179 } |
163 feature_infos.shrink (j + 1); | 180 feature_infos.shrink (j + 1); |
164 } | 181 } |
165 | 182 |
166 | 183 |
167 /* Allocate bits now */ | 184 /* Allocate bits now */ |
168 unsigned int next_bit = 1; | 185 unsigned int next_bit = 1; |
169 for (unsigned int i = 0; i < feature_infos.len; i++) { | 186 for (unsigned int i = 0; i < feature_infos.len; i++) |
| 187 { |
170 const feature_info_t *info = &feature_infos[i]; | 188 const feature_info_t *info = &feature_infos[i]; |
171 | 189 |
172 unsigned int bits_needed; | 190 unsigned int bits_needed; |
173 | 191 |
174 if ((info->flags & F_GLOBAL) && info->max_value == 1) | 192 if ((info->flags & F_GLOBAL) && info->max_value == 1) |
175 /* Uses the global bit */ | 193 /* Uses the global bit */ |
176 bits_needed = 0; | 194 bits_needed = 0; |
177 else | 195 else |
178 bits_needed = _hb_bit_storage (info->max_value); | 196 bits_needed = _hb_bit_storage (info->max_value); |
179 | 197 |
180 if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) | 198 if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) |
181 continue; /* Feature disabled, or not enough bits. */ | 199 continue; /* Feature disabled, or not enough bits. */ |
182 | 200 |
183 | 201 |
184 hb_bool_t found = false; | 202 hb_bool_t found = false; |
185 unsigned int feature_index[2]; | 203 unsigned int feature_index[2]; |
186 for (unsigned int table_index = 0; table_index < 2; table_index++) | 204 for (unsigned int table_index = 0; table_index < 2; table_index++) |
| 205 { |
| 206 if (required_feature_tag[table_index] == info->tag) |
| 207 { |
| 208 required_feature_stage[table_index] = info->stage[table_index]; |
| 209 found = true; |
| 210 continue; |
| 211 } |
187 found |= hb_ot_layout_language_find_feature (face, | 212 found |= hb_ot_layout_language_find_feature (face, |
188 table_tags[table_index], | 213 table_tags[table_index], |
189 script_index[table_index], | 214 script_index[table_index], |
190 language_index[table_index], | 215 language_index[table_index], |
191 info->tag, | 216 info->tag, |
192 &feature_index[table_index]); | 217 &feature_index[table_index]); |
| 218 } |
193 if (!found && !(info->flags & F_HAS_FALLBACK)) | 219 if (!found && !(info->flags & F_HAS_FALLBACK)) |
194 continue; | 220 continue; |
195 | 221 |
196 | 222 |
197 hb_ot_map_t::feature_map_t *map = m.features.push (); | 223 hb_ot_map_t::feature_map_t *map = m.features.push (); |
198 if (unlikely (!map)) | 224 if (unlikely (!map)) |
199 break; | 225 break; |
200 | 226 |
201 map->tag = info->tag; | 227 map->tag = info->tag; |
202 map->index[0] = feature_index[0]; | 228 map->index[0] = feature_index[0]; |
(...skipping 14 matching lines...) Expand all Loading... |
217 map->_1_mask = (1 << map->shift) & map->mask; | 243 map->_1_mask = (1 << map->shift) & map->mask; |
218 map->needs_fallback = !found; | 244 map->needs_fallback = !found; |
219 | 245 |
220 } | 246 } |
221 feature_infos.shrink (0); /* Done with these */ | 247 feature_infos.shrink (0); /* Done with these */ |
222 | 248 |
223 | 249 |
224 add_gsub_pause (NULL); | 250 add_gsub_pause (NULL); |
225 add_gpos_pause (NULL); | 251 add_gpos_pause (NULL); |
226 | 252 |
227 for (unsigned int table_index = 0; table_index < 2; table_index++) { | 253 for (unsigned int table_index = 0; table_index < 2; table_index++) |
228 hb_tag_t table_tag = table_tags[table_index]; | 254 { |
229 | |
230 /* Collect lookup indices for features */ | 255 /* Collect lookup indices for features */ |
231 | 256 |
232 unsigned int required_feature_index; | |
233 if (hb_ot_layout_language_get_required_feature_index (face, | |
234 table_tag, | |
235 script_index[table_ind
ex], | |
236 language_index[table_i
ndex], | |
237 &required_feature_inde
x)) | |
238 m.add_lookups (face, table_index, required_feature_index, 1, true); | |
239 | |
240 unsigned int stage_index = 0; | 257 unsigned int stage_index = 0; |
241 unsigned int last_num_lookups = 0; | 258 unsigned int last_num_lookups = 0; |
242 for (unsigned stage = 0; stage < current_stage[table_index]; stage++) | 259 for (unsigned stage = 0; stage < current_stage[table_index]; stage++) |
243 { | 260 { |
| 261 if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX &
& |
| 262 required_feature_stage[table_index] == stage) |
| 263 m.add_lookups (face, table_index, |
| 264 required_feature_index[table_index], |
| 265 1 /* mask */, |
| 266 true /* auto_zwj */); |
| 267 |
244 for (unsigned i = 0; i < m.features.len; i++) | 268 for (unsigned i = 0; i < m.features.len; i++) |
245 if (m.features[i].stage[table_index] == stage) | 269 if (m.features[i].stage[table_index] == stage) |
246 m.add_lookups (face, table_index, | 270 m.add_lookups (face, table_index, |
247 m.features[i].index[table_index], | 271 m.features[i].index[table_index], |
248 m.features[i].mask, | 272 m.features[i].mask, |
249 m.features[i].auto_zwj); | 273 m.features[i].auto_zwj); |
250 | 274 |
251 /* Sort lookups and merge duplicates */ | 275 /* Sort lookups and merge duplicates */ |
252 if (last_num_lookups < m.lookups[table_index].len) | 276 if (last_num_lookups < m.lookups[table_index].len) |
253 { | 277 { |
254 » m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].le
n); | 278 » m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].l
en); |
255 | 279 |
256 unsigned int j = last_num_lookups; | 280 unsigned int j = last_num_lookups; |
257 for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++) | 281 for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++) |
258 if (m.lookups[table_index][i].index != m.lookups[table_index][j].index
) | 282 if (m.lookups[table_index][i].index != m.lookups[table_index][j].index
) |
259 m.lookups[table_index][++j] = m.lookups[table_index][i]; | 283 m.lookups[table_index][++j] = m.lookups[table_index][i]; |
260 else | 284 else |
261 { | 285 { |
262 m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; | 286 m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; |
263 m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto
_zwj; | 287 m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto
_zwj; |
264 } | 288 } |
265 m.lookups[table_index].shrink (j + 1); | 289 m.lookups[table_index].shrink (j + 1); |
266 } | 290 } |
267 | 291 |
268 last_num_lookups = m.lookups[table_index].len; | 292 last_num_lookups = m.lookups[table_index].len; |
269 | 293 |
270 if (stage_index < stages[table_index].len && stages[table_index][stage_ind
ex].index == stage) { | 294 if (stage_index < stages[table_index].len && stages[table_index][stage_ind
ex].index == stage) { |
271 hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push (); | 295 hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push (); |
272 if (likely (stage_map)) { | 296 if (likely (stage_map)) { |
273 stage_map->last_lookup = last_num_lookups; | 297 stage_map->last_lookup = last_num_lookups; |
274 stage_map->pause_func = stages[table_index][stage_index].pause_func; | 298 stage_map->pause_func = stages[table_index][stage_index].pause_func; |
275 } | 299 } |
276 | 300 |
277 stage_index++; | 301 stage_index++; |
278 } | 302 } |
279 } | 303 } |
280 } | 304 } |
281 } | 305 } |
OLD | NEW |