OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2009,2010 Red Hat, Inc. | 2 * Copyright © 2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2011 Google, Inc. | 3 * Copyright © 2010,2011 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 10 matching lines...) Expand all Loading... |
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 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 | 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
24 * | 24 * |
25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #include "hb-ot-map-private.hh" | 29 #include "hb-ot-map-private.hh" |
30 | 30 |
31 #include "hb-ot-shape-private.hh" | |
32 | |
33 | |
34 | 31 |
35 void | 32 void |
36 hb_ot_map_t::add_lookups (hb_face_t *face, | 33 hb_ot_map_t::add_lookups (hb_face_t *face, |
37 unsigned int table_index, | 34 unsigned int table_index, |
38 unsigned int feature_index, | 35 unsigned int feature_index, |
39 hb_mask_t mask) | 36 hb_mask_t mask) |
40 { | 37 { |
41 unsigned int lookup_indices[32]; | 38 unsigned int lookup_indices[32]; |
42 unsigned int offset, len; | 39 unsigned int offset, len; |
43 | 40 |
(...skipping 12 matching lines...) Expand all Loading... |
56 return; | 53 return; |
57 lookup->mask = mask; | 54 lookup->mask = mask; |
58 lookup->index = lookup_indices[i]; | 55 lookup->index = lookup_indices[i]; |
59 } | 56 } |
60 | 57 |
61 offset += len; | 58 offset += len; |
62 } while (len == ARRAY_LENGTH (lookup_indices)); | 59 } while (len == ARRAY_LENGTH (lookup_indices)); |
63 } | 60 } |
64 | 61 |
65 | 62 |
66 void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool gl
obal) | 63 void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool gl
obal, bool has_fallback) |
67 { | 64 { |
68 feature_info_t *info = feature_infos.push(); | 65 feature_info_t *info = feature_infos.push(); |
69 if (unlikely (!info)) return; | 66 if (unlikely (!info)) return; |
70 info->tag = tag; | 67 info->tag = tag; |
71 info->seq = feature_infos.len; | 68 info->seq = feature_infos.len; |
72 info->max_value = value; | 69 info->max_value = value; |
73 info->global = global; | 70 info->global = global; |
| 71 info->has_fallback = has_fallback; |
74 info->default_value = global ? value : 0; | 72 info->default_value = global ? value : 0; |
75 info->stage[0] = current_stage[0]; | 73 info->stage[0] = current_stage[0]; |
76 info->stage[1] = current_stage[1]; | 74 info->stage[1] = current_stage[1]; |
77 } | 75 } |
78 | 76 |
79 void hb_ot_map_t::apply (unsigned int table_index, | 77 /* Keep the next two functions in sync. */ |
80 » » » hb_ot_map_t::apply_lookup_func_t apply_lookup_func, | 78 |
81 » » » void *face_or_font, | 79 void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h
b_buffer_t *buffer) const |
82 » » » hb_buffer_t *buffer) const | |
83 { | 80 { |
| 81 const unsigned int table_index = 0; |
84 unsigned int i = 0; | 82 unsigned int i = 0; |
85 | 83 |
86 for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; paus
e_index++) { | 84 for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; paus
e_index++) { |
87 const pause_map_t *pause = &pauses[table_index][pause_index]; | 85 const pause_map_t *pause = &pauses[table_index][pause_index]; |
88 for (; i < pause->num_lookups; i++) | 86 for (; i < pause->num_lookups; i++) |
89 apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lo
okups[table_index][i].mask); | 87 hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].inde
x, lookups[table_index][i].mask); |
90 | 88 |
91 pause->callback.func (this, face_or_font, buffer, pause->callback.user_data)
; | 89 buffer->clear_output (); |
| 90 |
| 91 if (pause->callback) |
| 92 pause->callback (plan, font, buffer); |
92 } | 93 } |
93 | 94 |
94 for (; i < lookups[table_index].len; i++) | 95 for (; i < lookups[table_index].len; i++) |
95 apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, look
ups[table_index][i].mask); | 96 hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index,
lookups[table_index][i].mask); |
96 } | 97 } |
97 | 98 |
98 void hb_ot_map_t::substitute_closure (hb_face_t *face, | 99 void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
buffer_t *buffer) const |
99 » » » » hb_set_t *glyphs) const | |
100 { | 100 { |
101 unsigned int table_index = 0; | 101 const unsigned int table_index = 1; |
102 unsigned int i = 0; | 102 unsigned int i = 0; |
103 | 103 |
104 for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; paus
e_index++) { | 104 for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; paus
e_index++) { |
105 const pause_map_t *pause = &pauses[table_index][pause_index]; | 105 const pause_map_t *pause = &pauses[table_index][pause_index]; |
106 for (; i < pause->num_lookups; i++) | 106 for (; i < pause->num_lookups; i++) |
107 hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index]
[i].index); | 107 hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index,
lookups[table_index][i].mask); |
| 108 |
| 109 if (pause->callback) |
| 110 pause->callback (plan, font, buffer); |
108 } | 111 } |
109 | 112 |
110 for (; i < lookups[table_index].len; i++) | 113 for (; i < lookups[table_index].len; i++) |
111 hb_ot_layout_substitute_closure_lookup (face, glyphs, lookups[table_index][i
].index); | 114 hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index, l
ookups[table_index][i].mask); |
112 } | 115 } |
113 | 116 |
114 void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus
e_func_t pause_func, void *user_data) | 117 void hb_ot_map_t::substitute_closure (const hb_ot_shape_plan_t *plan, hb_face_t
*face, hb_set_t *glyphs) const |
115 { | 118 { |
116 if (pause_func) { | 119 unsigned int table_index = 0; |
117 pause_info_t *p = pauses[table_index].push (); | 120 for (unsigned int i = 0; i < lookups[table_index].len; i++) |
118 if (likely (p)) { | 121 hb_ot_layout_substitute_closure_lookup (face, lookups[table_index][i].index,
glyphs); |
119 p->stage = current_stage[table_index]; | 122 } |
120 p->callback.func = pause_func; | 123 |
121 p->callback.user_data = user_data; | 124 void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus
e_func_t pause_func) |
122 } | 125 { |
| 126 pause_info_t *p = pauses[table_index].push (); |
| 127 if (likely (p)) { |
| 128 p->stage = current_stage[table_index]; |
| 129 p->callback = pause_func; |
123 } | 130 } |
124 | 131 |
125 current_stage[table_index]++; | 132 current_stage[table_index]++; |
126 } | 133 } |
127 | 134 |
128 void | 135 void |
129 hb_ot_map_builder_t::compile (hb_face_t *face, | 136 hb_ot_map_builder_t::compile (hb_face_t *face, |
130 const hb_segment_properties_t *props, | 137 const hb_segment_properties_t *props, |
131 hb_ot_map_t &m) | 138 hb_ot_map_t &m) |
132 { | 139 { |
(...skipping 29 matching lines...) Expand all Loading... |
162 feature_infos[++j] = feature_infos[i]; | 169 feature_infos[++j] = feature_infos[i]; |
163 else { | 170 else { |
164 if (feature_infos[i].global) { | 171 if (feature_infos[i].global) { |
165 feature_infos[j].global = true; | 172 feature_infos[j].global = true; |
166 feature_infos[j].max_value = feature_infos[i].max_value; | 173 feature_infos[j].max_value = feature_infos[i].max_value; |
167 feature_infos[j].default_value = feature_infos[i].default_value; | 174 feature_infos[j].default_value = feature_infos[i].default_value; |
168 } else { | 175 } else { |
169 feature_infos[j].global = false; | 176 feature_infos[j].global = false; |
170 feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_
infos[i].max_value); | 177 feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_
infos[i].max_value); |
171 } | 178 } |
| 179 feature_infos[j].has_fallback = feature_infos[j].has_fallback || feature
_infos[i].has_fallback; |
172 feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_info
s[i].stage[0]); | 180 feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_info
s[i].stage[0]); |
173 feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_info
s[i].stage[1]); | 181 feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_info
s[i].stage[1]); |
174 /* Inherit default_value from j */ | 182 /* Inherit default_value from j */ |
175 } | 183 } |
176 feature_infos.shrink (j + 1); | 184 feature_infos.shrink (j + 1); |
177 } | 185 } |
178 | 186 |
179 | 187 |
180 /* Allocate bits now */ | 188 /* Allocate bits now */ |
181 unsigned int next_bit = 1; | 189 unsigned int next_bit = 1; |
(...skipping 14 matching lines...) Expand all Loading... |
196 | 204 |
197 bool found = false; | 205 bool found = false; |
198 unsigned int feature_index[2]; | 206 unsigned int feature_index[2]; |
199 for (unsigned int table_index = 0; table_index < 2; table_index++) | 207 for (unsigned int table_index = 0; table_index < 2; table_index++) |
200 found |= hb_ot_layout_language_find_feature (face, | 208 found |= hb_ot_layout_language_find_feature (face, |
201 table_tags[table_index], | 209 table_tags[table_index], |
202 script_index[table_index], | 210 script_index[table_index], |
203 language_index[table_index], | 211 language_index[table_index], |
204 info->tag, | 212 info->tag, |
205 &feature_index[table_index]); | 213 &feature_index[table_index]); |
206 if (!found) | 214 if (!found && !info->has_fallback) |
207 continue; | 215 continue; |
208 | 216 |
209 | 217 |
210 hb_ot_map_t::feature_map_t *map = m.features.push (); | 218 hb_ot_map_t::feature_map_t *map = m.features.push (); |
211 if (unlikely (!map)) | 219 if (unlikely (!map)) |
212 break; | 220 break; |
213 | 221 |
214 map->tag = info->tag; | 222 map->tag = info->tag; |
215 map->index[0] = feature_index[0]; | 223 map->index[0] = feature_index[0]; |
216 map->index[1] = feature_index[1]; | 224 map->index[1] = feature_index[1]; |
217 map->stage[0] = info->stage[0]; | 225 map->stage[0] = info->stage[0]; |
218 map->stage[1] = info->stage[1]; | 226 map->stage[1] = info->stage[1]; |
219 if (info->global && info->max_value == 1) { | 227 if (info->global && info->max_value == 1) { |
220 /* Uses the global bit */ | 228 /* Uses the global bit */ |
221 map->shift = 0; | 229 map->shift = 0; |
222 map->mask = 1; | 230 map->mask = 1; |
223 } else { | 231 } else { |
224 map->shift = next_bit; | 232 map->shift = next_bit; |
225 map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); | 233 map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); |
226 next_bit += bits_needed; | 234 next_bit += bits_needed; |
227 if (info->global) | 235 if (info->global) |
228 m.global_mask |= (info->default_value << map->shift) & map->mask; | 236 m.global_mask |= (info->default_value << map->shift) & map->mask; |
229 } | 237 } |
230 map->_1_mask = (1 << map->shift) & map->mask; | 238 map->_1_mask = (1 << map->shift) & map->mask; |
| 239 map->needs_fallback = !found; |
231 | 240 |
232 } | 241 } |
233 feature_infos.shrink (0); /* Done with these */ | 242 feature_infos.shrink (0); /* Done with these */ |
234 | 243 |
235 | 244 |
236 add_gsub_pause (NULL, NULL); | 245 add_gsub_pause (NULL); |
237 add_gpos_pause (NULL, NULL); | 246 add_gpos_pause (NULL); |
238 | 247 |
239 for (unsigned int table_index = 0; table_index < 2; table_index++) { | 248 for (unsigned int table_index = 0; table_index < 2; table_index++) { |
240 hb_tag_t table_tag = table_tags[table_index]; | 249 hb_tag_t table_tag = table_tags[table_index]; |
241 | 250 |
242 /* Collect lookup indices for features */ | 251 /* Collect lookup indices for features */ |
243 | 252 |
244 unsigned int required_feature_index; | 253 unsigned int required_feature_index; |
245 if (hb_ot_layout_language_get_required_feature_index (face, | 254 if (hb_ot_layout_language_get_required_feature_index (face, |
246 table_tag, | 255 table_tag, |
247 script_index[table_ind
ex], | 256 script_index[table_ind
ex], |
(...skipping 30 matching lines...) Expand all Loading... |
278 if (likely (pause_map)) { | 287 if (likely (pause_map)) { |
279 pause_map->num_lookups = last_num_lookups; | 288 pause_map->num_lookups = last_num_lookups; |
280 pause_map->callback = pauses[table_index][pause_index].callback; | 289 pause_map->callback = pauses[table_index][pause_index].callback; |
281 } | 290 } |
282 | 291 |
283 pause_index++; | 292 pause_index++; |
284 } | 293 } |
285 } | 294 } |
286 } | 295 } |
287 } | 296 } |
288 | |
289 | |
OLD | NEW |